koffi 0.9.5 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (882) hide show
  1. package/LICENSE.txt +661 -0
  2. package/README.md +74 -9
  3. package/package.json +27 -7
  4. package/src/call.hh +2 -1
  5. package/src/call_arm32.cc +525 -0
  6. package/src/call_arm32_fwd.S +108 -0
  7. package/src/call_arm64.cc +90 -63
  8. package/src/call_arm64_fwd.S +24 -29
  9. package/src/call_x64_sysv.cc +61 -48
  10. package/src/call_x64_win.cc +69 -43
  11. package/src/call_x86.cc +83 -62
  12. package/src/ffi.cc +166 -37
  13. package/src/ffi.hh +43 -12
  14. package/src/util.cc +72 -32
  15. package/src/util.hh +127 -18
  16. package/test/files/node32.cmd +6 -0
  17. package/test/files/node64.cmd +6 -0
  18. package/test/registry/machines.json +185 -0
  19. package/test/registry/sha256sum.txt +24 -0
  20. package/test/test.js +625 -0
  21. package/test/tests/misc.c +40 -0
  22. package/test/tests/misc.js +54 -0
  23. package/test/tests/raylib.js +167 -0
  24. package/vendor/dragonbox/include/dragonbox/dragonbox.h +6 -2
  25. package/vendor/dragonbox/other_files/Dragonbox.pdf +0 -0
  26. package/vendor/libcc/libcc.cc +36 -18
  27. package/vendor/libcc/libcc.hh +23 -1
  28. package/vendor/raylib/BINDINGS.md +123 -0
  29. package/vendor/raylib/CHANGELOG +1495 -0
  30. package/vendor/raylib/CMakeLists.txt +33 -0
  31. package/vendor/raylib/CMakeOptions.txt +87 -0
  32. package/vendor/raylib/CONTRIBUTING.md +76 -0
  33. package/vendor/raylib/CONTRIBUTORS.md +63 -0
  34. package/vendor/raylib/CONVENTIONS.md +95 -0
  35. package/vendor/raylib/HISTORY.md +364 -0
  36. package/vendor/raylib/LICENSE +16 -0
  37. package/vendor/raylib/README.md +141 -0
  38. package/vendor/raylib/ROADMAP.md +76 -0
  39. package/vendor/raylib/SPONSORS.md +68 -0
  40. package/vendor/raylib/cmake/AddIfFlagCompiles.cmake +12 -0
  41. package/vendor/raylib/cmake/BuildOptions.cmake +18 -0
  42. package/vendor/raylib/cmake/CompileDefinitions.cmake +110 -0
  43. package/vendor/raylib/cmake/CompilerFlags.cmake +79 -0
  44. package/vendor/raylib/cmake/EnumOption.cmake +9 -0
  45. package/vendor/raylib/cmake/GlfwImport.cmake +34 -0
  46. package/vendor/raylib/cmake/InstallConfigurations.cmake +29 -0
  47. package/vendor/raylib/cmake/JoinPaths.cmake +26 -0
  48. package/vendor/raylib/cmake/LibraryConfigurations.cmake +108 -0
  49. package/vendor/raylib/cmake/LibraryPathToLinkerFlags.cmake +24 -0
  50. package/vendor/raylib/cmake/PackConfigurations.cmake +13 -0
  51. package/vendor/raylib/cmake/PopulateConfigVariablesLocally.cmake +11 -0
  52. package/vendor/raylib/cmake/raylib-config-version.cmake +21 -0
  53. package/vendor/raylib/cmake/raylib-config.cmake +76 -0
  54. package/vendor/raylib/examples/CMakeLists.txt +139 -0
  55. package/vendor/raylib/examples/Makefile +565 -0
  56. package/vendor/raylib/examples/Makefile.Android +405 -0
  57. package/vendor/raylib/examples/Makefile.Web +1053 -0
  58. package/vendor/raylib/examples/README.md +203 -0
  59. package/vendor/raylib/examples/audio/audio_module_playing.c +146 -0
  60. package/vendor/raylib/examples/audio/audio_module_playing.png +0 -0
  61. package/vendor/raylib/examples/audio/audio_multichannel_sound.c +73 -0
  62. package/vendor/raylib/examples/audio/audio_multichannel_sound.png +0 -0
  63. package/vendor/raylib/examples/audio/audio_music_stream.c +93 -0
  64. package/vendor/raylib/examples/audio/audio_music_stream.png +0 -0
  65. package/vendor/raylib/examples/audio/audio_raw_stream.c +167 -0
  66. package/vendor/raylib/examples/audio/audio_raw_stream.png +0 -0
  67. package/vendor/raylib/examples/audio/audio_sound_loading.c +64 -0
  68. package/vendor/raylib/examples/audio/audio_sound_loading.png +0 -0
  69. package/vendor/raylib/examples/audio/resources/LICENSE.md +10 -0
  70. package/vendor/raylib/examples/audio/resources/coin.wav +0 -0
  71. package/vendor/raylib/examples/audio/resources/country.mp3 +0 -0
  72. package/vendor/raylib/examples/audio/resources/mini1111.xm +0 -0
  73. package/vendor/raylib/examples/audio/resources/sound.wav +0 -0
  74. package/vendor/raylib/examples/audio/resources/spring.wav +0 -0
  75. package/vendor/raylib/examples/audio/resources/target.flac +0 -0
  76. package/vendor/raylib/examples/audio/resources/target.ogg +0 -0
  77. package/vendor/raylib/examples/audio/resources/weird.wav +0 -0
  78. package/vendor/raylib/examples/build.zig +86 -0
  79. package/vendor/raylib/examples/core/core_2d_camera.c +132 -0
  80. package/vendor/raylib/examples/core/core_2d_camera.png +0 -0
  81. package/vendor/raylib/examples/core/core_2d_camera_platformer.c +293 -0
  82. package/vendor/raylib/examples/core/core_2d_camera_platformer.png +0 -0
  83. package/vendor/raylib/examples/core/core_2d_camera_smooth_pixelperfect.png +0 -0
  84. package/vendor/raylib/examples/core/core_3d_camera_first_person.c +97 -0
  85. package/vendor/raylib/examples/core/core_3d_camera_first_person.png +0 -0
  86. package/vendor/raylib/examples/core/core_3d_camera_free.c +83 -0
  87. package/vendor/raylib/examples/core/core_3d_camera_free.png +0 -0
  88. package/vendor/raylib/examples/core/core_3d_camera_mode.c +73 -0
  89. package/vendor/raylib/examples/core/core_3d_camera_mode.png +0 -0
  90. package/vendor/raylib/examples/core/core_3d_picking.c +107 -0
  91. package/vendor/raylib/examples/core/core_3d_picking.png +0 -0
  92. package/vendor/raylib/examples/core/core_basic_screen_manager.c +150 -0
  93. package/vendor/raylib/examples/core/core_basic_screen_manager.png +0 -0
  94. package/vendor/raylib/examples/core/core_basic_window.c +62 -0
  95. package/vendor/raylib/examples/core/core_basic_window.png +0 -0
  96. package/vendor/raylib/examples/core/core_basic_window_web.c +85 -0
  97. package/vendor/raylib/examples/core/core_custom_frame_control.c +125 -0
  98. package/vendor/raylib/examples/core/core_custom_frame_control.png +0 -0
  99. package/vendor/raylib/examples/core/core_custom_logging.c +84 -0
  100. package/vendor/raylib/examples/core/core_custom_logging.png +0 -0
  101. package/vendor/raylib/examples/core/core_drop_files.c +76 -0
  102. package/vendor/raylib/examples/core/core_drop_files.png +0 -0
  103. package/vendor/raylib/examples/core/core_input_gamepad.c +195 -0
  104. package/vendor/raylib/examples/core/core_input_gamepad.png +0 -0
  105. package/vendor/raylib/examples/core/core_input_gestures.c +115 -0
  106. package/vendor/raylib/examples/core/core_input_gestures.png +0 -0
  107. package/vendor/raylib/examples/core/core_input_keys.c +59 -0
  108. package/vendor/raylib/examples/core/core_input_keys.png +0 -0
  109. package/vendor/raylib/examples/core/core_input_mouse.c +65 -0
  110. package/vendor/raylib/examples/core/core_input_mouse.png +0 -0
  111. package/vendor/raylib/examples/core/core_input_mouse_wheel.c +58 -0
  112. package/vendor/raylib/examples/core/core_input_mouse_wheel.png +0 -0
  113. package/vendor/raylib/examples/core/core_input_multitouch.c +70 -0
  114. package/vendor/raylib/examples/core/core_input_multitouch.png +0 -0
  115. package/vendor/raylib/examples/core/core_loading_thread.c +147 -0
  116. package/vendor/raylib/examples/core/core_loading_thread.png +0 -0
  117. package/vendor/raylib/examples/core/core_quat_conversion.c +132 -0
  118. package/vendor/raylib/examples/core/core_quat_conversion.png +0 -0
  119. package/vendor/raylib/examples/core/core_random_values.c +67 -0
  120. package/vendor/raylib/examples/core/core_random_values.png +0 -0
  121. package/vendor/raylib/examples/core/core_scissor_test.c +71 -0
  122. package/vendor/raylib/examples/core/core_scissor_test.png +0 -0
  123. package/vendor/raylib/examples/core/core_smooth_pixelperfect.c +117 -0
  124. package/vendor/raylib/examples/core/core_smooth_pixelperfect.png +0 -0
  125. package/vendor/raylib/examples/core/core_split_screen.c +155 -0
  126. package/vendor/raylib/examples/core/core_split_screen.png +0 -0
  127. package/vendor/raylib/examples/core/core_storage_values.c +87 -0
  128. package/vendor/raylib/examples/core/core_storage_values.png +0 -0
  129. package/vendor/raylib/examples/core/core_vr_simulator.c +143 -0
  130. package/vendor/raylib/examples/core/core_vr_simulator.png +0 -0
  131. package/vendor/raylib/examples/core/core_window_flags.c +191 -0
  132. package/vendor/raylib/examples/core/core_window_flags.png +0 -0
  133. package/vendor/raylib/examples/core/core_window_letterbox.c +112 -0
  134. package/vendor/raylib/examples/core/core_window_letterbox.png +0 -0
  135. package/vendor/raylib/examples/core/core_world_screen.c +78 -0
  136. package/vendor/raylib/examples/core/core_world_screen.png +0 -0
  137. package/vendor/raylib/examples/core/resources/LICENSE.md +4 -0
  138. package/vendor/raylib/examples/core/resources/distortion100.fs +52 -0
  139. package/vendor/raylib/examples/core/resources/distortion330.fs +53 -0
  140. package/vendor/raylib/examples/core/resources/ps3.png +0 -0
  141. package/vendor/raylib/examples/core/resources/xbox.png +0 -0
  142. package/vendor/raylib/examples/examples_template.c +100 -0
  143. package/vendor/raylib/examples/models/models_animation.c +114 -0
  144. package/vendor/raylib/examples/models/models_animation.png +0 -0
  145. package/vendor/raylib/examples/models/models_billboard.c +75 -0
  146. package/vendor/raylib/examples/models/models_billboard.png +0 -0
  147. package/vendor/raylib/examples/models/models_box_collisions.c +121 -0
  148. package/vendor/raylib/examples/models/models_box_collisions.png +0 -0
  149. package/vendor/raylib/examples/models/models_cubicmap.c +87 -0
  150. package/vendor/raylib/examples/models/models_cubicmap.png +0 -0
  151. package/vendor/raylib/examples/models/models_first_person_maze.c +122 -0
  152. package/vendor/raylib/examples/models/models_first_person_maze.png +0 -0
  153. package/vendor/raylib/examples/models/models_geometric_shapes.c +80 -0
  154. package/vendor/raylib/examples/models/models_geometric_shapes.png +0 -0
  155. package/vendor/raylib/examples/models/models_heightmap.c +82 -0
  156. package/vendor/raylib/examples/models/models_heightmap.png +0 -0
  157. package/vendor/raylib/examples/models/models_loading.c +146 -0
  158. package/vendor/raylib/examples/models/models_loading.png +0 -0
  159. package/vendor/raylib/examples/models/models_loading_gltf.c +105 -0
  160. package/vendor/raylib/examples/models/models_loading_gltf.png +0 -0
  161. package/vendor/raylib/examples/models/models_loading_vox.c +130 -0
  162. package/vendor/raylib/examples/models/models_loading_vox.png +0 -0
  163. package/vendor/raylib/examples/models/models_mesh_generation.c +179 -0
  164. package/vendor/raylib/examples/models/models_mesh_generation.png +0 -0
  165. package/vendor/raylib/examples/models/models_mesh_picking.c +223 -0
  166. package/vendor/raylib/examples/models/models_mesh_picking.png +0 -0
  167. package/vendor/raylib/examples/models/models_orthographic_projection.c +99 -0
  168. package/vendor/raylib/examples/models/models_orthographic_projection.png +0 -0
  169. package/vendor/raylib/examples/models/models_rlgl_solar_system.c +172 -0
  170. package/vendor/raylib/examples/models/models_rlgl_solar_system.png +0 -0
  171. package/vendor/raylib/examples/models/models_skybox.c +262 -0
  172. package/vendor/raylib/examples/models/models_skybox.png +0 -0
  173. package/vendor/raylib/examples/models/models_waving_cubes.c +112 -0
  174. package/vendor/raylib/examples/models/models_waving_cubes.png +0 -0
  175. package/vendor/raylib/examples/models/models_yaw_pitch_roll.c +117 -0
  176. package/vendor/raylib/examples/models/models_yaw_pitch_roll.png +0 -0
  177. package/vendor/raylib/examples/models/resources/LICENSE.md +23 -0
  178. package/vendor/raylib/examples/models/resources/billboard.png +0 -0
  179. package/vendor/raylib/examples/models/resources/cubicmap.png +0 -0
  180. package/vendor/raylib/examples/models/resources/cubicmap_atlas.png +0 -0
  181. package/vendor/raylib/examples/models/resources/dresden_square_1k.hdr +0 -0
  182. package/vendor/raylib/examples/models/resources/dresden_square_2k.hdr +0 -0
  183. package/vendor/raylib/examples/models/resources/heightmap.png +0 -0
  184. package/vendor/raylib/examples/models/resources/models/gltf/AnimatedMorphCube.glb +0 -0
  185. package/vendor/raylib/examples/models/resources/models/gltf/AnimatedTriangle.gltf +118 -0
  186. package/vendor/raylib/examples/models/resources/models/gltf/BoxAnimated.glb +0 -0
  187. package/vendor/raylib/examples/models/resources/models/gltf/LICENSE +23 -0
  188. package/vendor/raylib/examples/models/resources/models/gltf/girl.glb +0 -0
  189. package/vendor/raylib/examples/models/resources/models/gltf/raylib_32x32.glb +0 -0
  190. package/vendor/raylib/examples/models/resources/models/gltf/rigged_figure.glb +0 -0
  191. package/vendor/raylib/examples/models/resources/models/gltf/vertex_colored_object.glb +0 -0
  192. package/vendor/raylib/examples/models/resources/models/iqm/guy.blend +0 -0
  193. package/vendor/raylib/examples/models/resources/models/iqm/guy.iqm +0 -0
  194. package/vendor/raylib/examples/models/resources/models/iqm/guyanim.iqm +0 -0
  195. package/vendor/raylib/examples/models/resources/models/iqm/guytex.png +0 -0
  196. package/vendor/raylib/examples/models/resources/models/iqm/vertex_colored_object.iqm +0 -0
  197. package/vendor/raylib/examples/models/resources/models/obj/bridge.obj +1725 -0
  198. package/vendor/raylib/examples/models/resources/models/obj/bridge_diffuse.png +0 -0
  199. package/vendor/raylib/examples/models/resources/models/obj/castle.obj +12919 -0
  200. package/vendor/raylib/examples/models/resources/models/obj/castle_diffuse.png +0 -0
  201. package/vendor/raylib/examples/models/resources/models/obj/cube.obj +68 -0
  202. package/vendor/raylib/examples/models/resources/models/obj/cube_diffuse.png +0 -0
  203. package/vendor/raylib/examples/models/resources/models/obj/house.obj +4564 -0
  204. package/vendor/raylib/examples/models/resources/models/obj/house_diffuse.png +0 -0
  205. package/vendor/raylib/examples/models/resources/models/obj/market.obj +7301 -0
  206. package/vendor/raylib/examples/models/resources/models/obj/market_diffuse.png +0 -0
  207. package/vendor/raylib/examples/models/resources/models/obj/plane.obj +10858 -0
  208. package/vendor/raylib/examples/models/resources/models/obj/plane_diffuse.png +0 -0
  209. package/vendor/raylib/examples/models/resources/models/obj/turret.obj +1888 -0
  210. package/vendor/raylib/examples/models/resources/models/obj/turret_diffuse.png +0 -0
  211. package/vendor/raylib/examples/models/resources/models/obj/well.obj +1030 -0
  212. package/vendor/raylib/examples/models/resources/models/obj/well_diffuse.png +0 -0
  213. package/vendor/raylib/examples/models/resources/models/vox/LICENSE +9 -0
  214. package/vendor/raylib/examples/models/resources/models/vox/chr_knight.vox +0 -0
  215. package/vendor/raylib/examples/models/resources/models/vox/chr_sword.vox +0 -0
  216. package/vendor/raylib/examples/models/resources/models/vox/monu9.vox +0 -0
  217. package/vendor/raylib/examples/models/resources/shaders/glsl100/cubemap.fs +29 -0
  218. package/vendor/raylib/examples/models/resources/shaders/glsl100/cubemap.vs +20 -0
  219. package/vendor/raylib/examples/models/resources/shaders/glsl100/skybox.fs +31 -0
  220. package/vendor/raylib/examples/models/resources/shaders/glsl100/skybox.vs +24 -0
  221. package/vendor/raylib/examples/models/resources/shaders/glsl330/cubemap.fs +30 -0
  222. package/vendor/raylib/examples/models/resources/shaders/glsl330/cubemap.vs +20 -0
  223. package/vendor/raylib/examples/models/resources/shaders/glsl330/skybox.fs +30 -0
  224. package/vendor/raylib/examples/models/resources/shaders/glsl330/skybox.vs +24 -0
  225. package/vendor/raylib/examples/models/resources/skybox.png +0 -0
  226. package/vendor/raylib/examples/models/rlights.h +183 -0
  227. package/vendor/raylib/examples/others/easings.h +263 -0
  228. package/vendor/raylib/examples/others/easings_testbed.c +227 -0
  229. package/vendor/raylib/examples/others/embedded_files_loading.c +103 -0
  230. package/vendor/raylib/examples/others/external/include/GLFW/glfw3.h +5538 -0
  231. package/vendor/raylib/examples/others/external/include/GLFW/glfw3native.h +572 -0
  232. package/vendor/raylib/examples/others/external/include/glad.h +5466 -0
  233. package/vendor/raylib/examples/others/external/lib/libglfw3.a +0 -0
  234. package/vendor/raylib/examples/others/raudio_standalone.c +152 -0
  235. package/vendor/raylib/examples/others/raylib_opengl_interop.c +152 -0
  236. package/vendor/raylib/examples/others/raylib_opengl_interop.png +0 -0
  237. package/vendor/raylib/examples/others/resources/audio/country.mp3 +0 -0
  238. package/vendor/raylib/examples/others/resources/audio/target.ogg +0 -0
  239. package/vendor/raylib/examples/others/resources/audio/weird.wav +0 -0
  240. package/vendor/raylib/examples/others/resources/audio_data.h +4893 -0
  241. package/vendor/raylib/examples/others/resources/image_data.h +9848 -0
  242. package/vendor/raylib/examples/others/resources/shaders/glsl100/point_particle.fs +16 -0
  243. package/vendor/raylib/examples/others/resources/shaders/glsl100/point_particle.vs +24 -0
  244. package/vendor/raylib/examples/others/resources/shaders/glsl330/point_particle.fs +17 -0
  245. package/vendor/raylib/examples/others/resources/shaders/glsl330/point_particle.vs +24 -0
  246. package/vendor/raylib/examples/others/resources/shaders/glsl430/gol.glsl +41 -0
  247. package/vendor/raylib/examples/others/resources/shaders/glsl430/gol_render.glsl +29 -0
  248. package/vendor/raylib/examples/others/resources/shaders/glsl430/gol_transfert.glsl +51 -0
  249. package/vendor/raylib/examples/others/rlgl_compute_shader.c +173 -0
  250. package/vendor/raylib/examples/others/rlgl_standalone.c +469 -0
  251. package/vendor/raylib/examples/physics/physics_demo.c +128 -0
  252. package/vendor/raylib/examples/physics/physics_demo.png +0 -0
  253. package/vendor/raylib/examples/physics/physics_friction.c +142 -0
  254. package/vendor/raylib/examples/physics/physics_friction.png +0 -0
  255. package/vendor/raylib/examples/physics/physics_movement.c +128 -0
  256. package/vendor/raylib/examples/physics/physics_movement.png +0 -0
  257. package/vendor/raylib/examples/physics/physics_restitution.c +129 -0
  258. package/vendor/raylib/examples/physics/physics_restitution.png +0 -0
  259. package/vendor/raylib/examples/physics/physics_shatter.c +111 -0
  260. package/vendor/raylib/examples/physics/physics_shatter.png +0 -0
  261. package/vendor/raylib/examples/raylib_compile_execute.bat +32 -0
  262. package/vendor/raylib/examples/raylib_makefile_example.bat +27 -0
  263. package/vendor/raylib/examples/shaders/resources/LICENSE.md +11 -0
  264. package/vendor/raylib/examples/shaders/resources/fudesumi.png +0 -0
  265. package/vendor/raylib/examples/shaders/resources/mask.png +0 -0
  266. package/vendor/raylib/examples/shaders/resources/models/barracks.obj +22251 -0
  267. package/vendor/raylib/examples/shaders/resources/models/barracks_diffuse.png +0 -0
  268. package/vendor/raylib/examples/shaders/resources/models/church.obj +5116 -0
  269. package/vendor/raylib/examples/shaders/resources/models/church_diffuse.png +0 -0
  270. package/vendor/raylib/examples/shaders/resources/models/watermill.obj +5316 -0
  271. package/vendor/raylib/examples/shaders/resources/models/watermill_diffuse.png +0 -0
  272. package/vendor/raylib/examples/shaders/resources/plasma.png +0 -0
  273. package/vendor/raylib/examples/shaders/resources/raysan.png +0 -0
  274. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/base.fs +23 -0
  275. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/base.vs +26 -0
  276. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/base_lighting.vs +59 -0
  277. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/base_lighting_instanced.vs +36 -0
  278. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/bloom.fs +39 -0
  279. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/blur.fs +34 -0
  280. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/color_mix.fs +26 -0
  281. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/cross_hatching.fs +47 -0
  282. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/cross_stitching.fs +57 -0
  283. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/cubes_panning.fs +60 -0
  284. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/depth.fs +26 -0
  285. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/distortion.fs +54 -0
  286. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/dream_vision.fs +37 -0
  287. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/eratosthenes.fs +60 -0
  288. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/fisheye.fs +43 -0
  289. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/fog.fs +94 -0
  290. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/grayscale.fs +25 -0
  291. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/julia_set.fs +83 -0
  292. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/lighting.fs +81 -0
  293. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/mask.fs +24 -0
  294. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/outline.fs +34 -0
  295. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/palette_switch.fs +41 -0
  296. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/pixelizer.fs +32 -0
  297. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/posterization.fs +29 -0
  298. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/predator.fs +31 -0
  299. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/raymarching.fs +431 -0
  300. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/reload.fs +39 -0
  301. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/scanlines.fs +44 -0
  302. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/sobel.fs +40 -0
  303. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/spotlight.fs +77 -0
  304. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/swirl.fs +46 -0
  305. package/vendor/raylib/examples/shaders/resources/shaders/glsl100/wave.fs +36 -0
  306. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/base.fs +22 -0
  307. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/base.vs +26 -0
  308. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/base_lighting.vs +59 -0
  309. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/bloom.fs +37 -0
  310. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/blur.fs +32 -0
  311. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/cross_hatching.fs +45 -0
  312. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/cross_stitching.fs +55 -0
  313. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/distortion.fs +52 -0
  314. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/dream_vision.fs +35 -0
  315. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/fisheye.fs +41 -0
  316. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/fog.fs +92 -0
  317. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/grayscale.fs +23 -0
  318. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/palette_switch.fs +27 -0
  319. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/pixelizer.fs +30 -0
  320. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/posterization.fs +27 -0
  321. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/predator.fs +29 -0
  322. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/scanlines.fs +42 -0
  323. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/sobel.fs +38 -0
  324. package/vendor/raylib/examples/shaders/resources/shaders/glsl120/swirl.fs +44 -0
  325. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/base.fs +25 -0
  326. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/base.vs +26 -0
  327. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/base_lighting.vs +32 -0
  328. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/base_lighting_instanced.vs +36 -0
  329. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/bloom.fs +40 -0
  330. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/blur.fs +35 -0
  331. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/color_mix.fs +27 -0
  332. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/cross_hatching.fs +48 -0
  333. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/cross_stitching.fs +59 -0
  334. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/cubes_panning.fs +61 -0
  335. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/depth.fs +27 -0
  336. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/distortion.fs +56 -0
  337. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/dream_vision.fs +34 -0
  338. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/eratosthenes.fs +59 -0
  339. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/fisheye.fs +40 -0
  340. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/fog.fs +95 -0
  341. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/grayscale.fs +26 -0
  342. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/julia_set.fs +81 -0
  343. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/lighting.fs +82 -0
  344. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/mask.fs +22 -0
  345. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/outline.fs +35 -0
  346. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/overdraw.fs +26 -0
  347. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/palette_switch.fs +30 -0
  348. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/pixelizer.fs +33 -0
  349. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/posterization.fs +31 -0
  350. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/predator.fs +32 -0
  351. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/raymarching.fs +430 -0
  352. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/reload.fs +40 -0
  353. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/scanlines.fs +49 -0
  354. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/sobel.fs +41 -0
  355. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/spotlight.fs +65 -0
  356. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/swirl.fs +47 -0
  357. package/vendor/raylib/examples/shaders/resources/shaders/glsl330/wave.fs +37 -0
  358. package/vendor/raylib/examples/shaders/resources/space.png +0 -0
  359. package/vendor/raylib/examples/shaders/resources/texel_checker.png +0 -0
  360. package/vendor/raylib/examples/shaders/rlights.h +183 -0
  361. package/vendor/raylib/examples/shaders/shaders_basic_lighting.c +152 -0
  362. package/vendor/raylib/examples/shaders/shaders_basic_lighting.png +0 -0
  363. package/vendor/raylib/examples/shaders/shaders_custom_uniform.c +127 -0
  364. package/vendor/raylib/examples/shaders/shaders_custom_uniform.png +0 -0
  365. package/vendor/raylib/examples/shaders/shaders_eratosthenes.c +92 -0
  366. package/vendor/raylib/examples/shaders/shaders_eratosthenes.png +0 -0
  367. package/vendor/raylib/examples/shaders/shaders_fog.c +160 -0
  368. package/vendor/raylib/examples/shaders/shaders_fog.png +0 -0
  369. package/vendor/raylib/examples/shaders/shaders_hot_reloading.c +130 -0
  370. package/vendor/raylib/examples/shaders/shaders_hot_reloading.png +0 -0
  371. package/vendor/raylib/examples/shaders/shaders_julia_set.c +191 -0
  372. package/vendor/raylib/examples/shaders/shaders_julia_set.png +0 -0
  373. package/vendor/raylib/examples/shaders/shaders_mesh_instancing.c +224 -0
  374. package/vendor/raylib/examples/shaders/shaders_mesh_instancing.png +0 -0
  375. package/vendor/raylib/examples/shaders/shaders_model_shader.c +103 -0
  376. package/vendor/raylib/examples/shaders/shaders_model_shader.png +0 -0
  377. package/vendor/raylib/examples/shaders/shaders_multi_sample2d.c +105 -0
  378. package/vendor/raylib/examples/shaders/shaders_multi_sample2d.png +0 -0
  379. package/vendor/raylib/examples/shaders/shaders_palette_switch.c +147 -0
  380. package/vendor/raylib/examples/shaders/shaders_palette_switch.png +0 -0
  381. package/vendor/raylib/examples/shaders/shaders_postprocessing.c +170 -0
  382. package/vendor/raylib/examples/shaders/shaders_postprocessing.png +0 -0
  383. package/vendor/raylib/examples/shaders/shaders_raymarching.c +113 -0
  384. package/vendor/raylib/examples/shaders/shaders_raymarching.png +0 -0
  385. package/vendor/raylib/examples/shaders/shaders_shapes_textures.c +116 -0
  386. package/vendor/raylib/examples/shaders/shaders_shapes_textures.png +0 -0
  387. package/vendor/raylib/examples/shaders/shaders_simple_mask.c +144 -0
  388. package/vendor/raylib/examples/shaders/shaders_simple_mask.png +0 -0
  389. package/vendor/raylib/examples/shaders/shaders_spotlight.c +254 -0
  390. package/vendor/raylib/examples/shaders/shaders_spotlight.png +0 -0
  391. package/vendor/raylib/examples/shaders/shaders_texture_drawing.c +80 -0
  392. package/vendor/raylib/examples/shaders/shaders_texture_drawing.png +0 -0
  393. package/vendor/raylib/examples/shaders/shaders_texture_outline.c +97 -0
  394. package/vendor/raylib/examples/shaders/shaders_texture_outline.png +0 -0
  395. package/vendor/raylib/examples/shaders/shaders_texture_waves.c +110 -0
  396. package/vendor/raylib/examples/shaders/shaders_texture_waves.png +0 -0
  397. package/vendor/raylib/examples/shapes/shapes_basic_shapes.c +78 -0
  398. package/vendor/raylib/examples/shapes/shapes_basic_shapes.png +0 -0
  399. package/vendor/raylib/examples/shapes/shapes_bouncing_ball.c +76 -0
  400. package/vendor/raylib/examples/shapes/shapes_bouncing_ball.png +0 -0
  401. package/vendor/raylib/examples/shapes/shapes_collision_area.c +108 -0
  402. package/vendor/raylib/examples/shapes/shapes_collision_area.png +0 -0
  403. package/vendor/raylib/examples/shapes/shapes_colors_palette.c +99 -0
  404. package/vendor/raylib/examples/shapes/shapes_colors_palette.png +0 -0
  405. package/vendor/raylib/examples/shapes/shapes_draw_circle_sector.c +83 -0
  406. package/vendor/raylib/examples/shapes/shapes_draw_circle_sector.png +0 -0
  407. package/vendor/raylib/examples/shapes/shapes_draw_rectangle_rounded.c +89 -0
  408. package/vendor/raylib/examples/shapes/shapes_draw_rectangle_rounded.png +0 -0
  409. package/vendor/raylib/examples/shapes/shapes_draw_ring.c +96 -0
  410. package/vendor/raylib/examples/shapes/shapes_draw_ring.png +0 -0
  411. package/vendor/raylib/examples/shapes/shapes_easings_ball_anim.c +110 -0
  412. package/vendor/raylib/examples/shapes/shapes_easings_ball_anim.png +0 -0
  413. package/vendor/raylib/examples/shapes/shapes_easings_box_anim.c +136 -0
  414. package/vendor/raylib/examples/shapes/shapes_easings_box_anim.png +0 -0
  415. package/vendor/raylib/examples/shapes/shapes_easings_rectangle_array.c +118 -0
  416. package/vendor/raylib/examples/shapes/shapes_easings_rectangle_array.png +0 -0
  417. package/vendor/raylib/examples/shapes/shapes_following_eyes.c +104 -0
  418. package/vendor/raylib/examples/shapes/shapes_following_eyes.png +0 -0
  419. package/vendor/raylib/examples/shapes/shapes_lines_bezier.c +59 -0
  420. package/vendor/raylib/examples/shapes/shapes_lines_bezier.png +0 -0
  421. package/vendor/raylib/examples/shapes/shapes_logo_raylib.c +56 -0
  422. package/vendor/raylib/examples/shapes/shapes_logo_raylib.png +0 -0
  423. package/vendor/raylib/examples/shapes/shapes_logo_raylib_anim.c +160 -0
  424. package/vendor/raylib/examples/shapes/shapes_logo_raylib_anim.png +0 -0
  425. package/vendor/raylib/examples/shapes/shapes_rectangle_scaling.c +94 -0
  426. package/vendor/raylib/examples/shapes/shapes_rectangle_scaling.png +0 -0
  427. package/vendor/raylib/examples/text/resources/KAISG.ttf +0 -0
  428. package/vendor/raylib/examples/text/resources/LICENSE.md +20 -0
  429. package/vendor/raylib/examples/text/resources/anonymous_pro_bold.ttf +0 -0
  430. package/vendor/raylib/examples/text/resources/custom_alagard.png +0 -0
  431. package/vendor/raylib/examples/text/resources/custom_jupiter_crash.png +0 -0
  432. package/vendor/raylib/examples/text/resources/custom_mecha.png +0 -0
  433. package/vendor/raylib/examples/text/resources/dejavu.fnt +1115 -0
  434. package/vendor/raylib/examples/text/resources/dejavu.png +0 -0
  435. package/vendor/raylib/examples/text/resources/fonts/alagard.png +0 -0
  436. package/vendor/raylib/examples/text/resources/fonts/alpha_beta.png +0 -0
  437. package/vendor/raylib/examples/text/resources/fonts/jupiter_crash.png +0 -0
  438. package/vendor/raylib/examples/text/resources/fonts/mecha.png +0 -0
  439. package/vendor/raylib/examples/text/resources/fonts/pixantiqua.png +0 -0
  440. package/vendor/raylib/examples/text/resources/fonts/pixelplay.png +0 -0
  441. package/vendor/raylib/examples/text/resources/fonts/romulus.png +0 -0
  442. package/vendor/raylib/examples/text/resources/fonts/setback.png +0 -0
  443. package/vendor/raylib/examples/text/resources/noto_cjk.fnt +580 -0
  444. package/vendor/raylib/examples/text/resources/noto_cjk.png +0 -0
  445. package/vendor/raylib/examples/text/resources/pixantiqua.fnt +188 -0
  446. package/vendor/raylib/examples/text/resources/pixantiqua.png +0 -0
  447. package/vendor/raylib/examples/text/resources/pixantiqua.ttf +0 -0
  448. package/vendor/raylib/examples/text/resources/shaders/glsl100/alpha_discard.fs +20 -0
  449. package/vendor/raylib/examples/text/resources/shaders/glsl100/sdf.fs +25 -0
  450. package/vendor/raylib/examples/text/resources/shaders/glsl330/alpha_discard.fs +19 -0
  451. package/vendor/raylib/examples/text/resources/shaders/glsl330/sdf.fs +26 -0
  452. package/vendor/raylib/examples/text/resources/symbola.fnt +191 -0
  453. package/vendor/raylib/examples/text/resources/symbola.png +0 -0
  454. package/vendor/raylib/examples/text/text_draw_3d.c +739 -0
  455. package/vendor/raylib/examples/text/text_draw_3d.png +0 -0
  456. package/vendor/raylib/examples/text/text_font_filters.c +134 -0
  457. package/vendor/raylib/examples/text/text_font_filters.png +0 -0
  458. package/vendor/raylib/examples/text/text_font_loading.c +91 -0
  459. package/vendor/raylib/examples/text/text_font_loading.png +0 -0
  460. package/vendor/raylib/examples/text/text_font_sdf.c +141 -0
  461. package/vendor/raylib/examples/text/text_font_sdf.png +0 -0
  462. package/vendor/raylib/examples/text/text_font_spritefont.c +85 -0
  463. package/vendor/raylib/examples/text/text_font_spritefont.png +0 -0
  464. package/vendor/raylib/examples/text/text_format_text.c +62 -0
  465. package/vendor/raylib/examples/text/text_format_text.png +0 -0
  466. package/vendor/raylib/examples/text/text_input_box.c +127 -0
  467. package/vendor/raylib/examples/text/text_input_box.png +0 -0
  468. package/vendor/raylib/examples/text/text_raylib_fonts.c +105 -0
  469. package/vendor/raylib/examples/text/text_raylib_fonts.png +0 -0
  470. package/vendor/raylib/examples/text/text_rectangle_bounds.c +264 -0
  471. package/vendor/raylib/examples/text/text_rectangle_bounds.png +0 -0
  472. package/vendor/raylib/examples/text/text_unicode.c +465 -0
  473. package/vendor/raylib/examples/text/text_unicode.png +0 -0
  474. package/vendor/raylib/examples/text/text_writing_anim.c +62 -0
  475. package/vendor/raylib/examples/text/text_writing_anim.png +0 -0
  476. package/vendor/raylib/examples/textures/resources/KAISG.ttf +0 -0
  477. package/vendor/raylib/examples/textures/resources/LICENSE.md +18 -0
  478. package/vendor/raylib/examples/textures/resources/boom.wav +0 -0
  479. package/vendor/raylib/examples/textures/resources/button.png +0 -0
  480. package/vendor/raylib/examples/textures/resources/buttonfx.wav +0 -0
  481. package/vendor/raylib/examples/textures/resources/cat.png +0 -0
  482. package/vendor/raylib/examples/textures/resources/custom_jupiter_crash.png +0 -0
  483. package/vendor/raylib/examples/textures/resources/cyberpunk_street_background.png +0 -0
  484. package/vendor/raylib/examples/textures/resources/cyberpunk_street_foreground.png +0 -0
  485. package/vendor/raylib/examples/textures/resources/cyberpunk_street_midground.png +0 -0
  486. package/vendor/raylib/examples/textures/resources/explosion.png +0 -0
  487. package/vendor/raylib/examples/textures/resources/fudesumi.png +0 -0
  488. package/vendor/raylib/examples/textures/resources/fudesumi.raw +0 -0
  489. package/vendor/raylib/examples/textures/resources/ninepatch_button.png +0 -0
  490. package/vendor/raylib/examples/textures/resources/parrots.png +0 -0
  491. package/vendor/raylib/examples/textures/resources/patterns.png +0 -0
  492. package/vendor/raylib/examples/textures/resources/raylib_logo.png +0 -0
  493. package/vendor/raylib/examples/textures/resources/scarfy.png +0 -0
  494. package/vendor/raylib/examples/textures/resources/spark_flame.png +0 -0
  495. package/vendor/raylib/examples/textures/resources/wabbit_alpha.png +0 -0
  496. package/vendor/raylib/examples/textures/textures_background_scrolling.c +87 -0
  497. package/vendor/raylib/examples/textures/textures_background_scrolling.png +0 -0
  498. package/vendor/raylib/examples/textures/textures_blend_modes.c +93 -0
  499. package/vendor/raylib/examples/textures/textures_blend_modes.png +0 -0
  500. package/vendor/raylib/examples/textures/textures_bunnymark.c +120 -0
  501. package/vendor/raylib/examples/textures/textures_bunnymark.png +0 -0
  502. package/vendor/raylib/examples/textures/textures_draw_tiled.c +165 -0
  503. package/vendor/raylib/examples/textures/textures_draw_tiled.png +0 -0
  504. package/vendor/raylib/examples/textures/textures_image_drawing.c +91 -0
  505. package/vendor/raylib/examples/textures/textures_image_drawing.png +0 -0
  506. package/vendor/raylib/examples/textures/textures_image_generation.c +102 -0
  507. package/vendor/raylib/examples/textures/textures_image_generation.png +0 -0
  508. package/vendor/raylib/examples/textures/textures_image_loading.c +64 -0
  509. package/vendor/raylib/examples/textures/textures_image_loading.png +0 -0
  510. package/vendor/raylib/examples/textures/textures_image_processing.c +169 -0
  511. package/vendor/raylib/examples/textures/textures_image_processing.png +0 -0
  512. package/vendor/raylib/examples/textures/textures_image_text.c +83 -0
  513. package/vendor/raylib/examples/textures/textures_image_text.png +0 -0
  514. package/vendor/raylib/examples/textures/textures_logo_raylib.c +57 -0
  515. package/vendor/raylib/examples/textures/textures_logo_raylib.png +0 -0
  516. package/vendor/raylib/examples/textures/textures_mouse_painting.c +221 -0
  517. package/vendor/raylib/examples/textures/textures_mouse_painting.png +0 -0
  518. package/vendor/raylib/examples/textures/textures_npatch_drawing.c +109 -0
  519. package/vendor/raylib/examples/textures/textures_npatch_drawing.png +0 -0
  520. package/vendor/raylib/examples/textures/textures_particles_blending.c +135 -0
  521. package/vendor/raylib/examples/textures/textures_particles_blending.png +0 -0
  522. package/vendor/raylib/examples/textures/textures_polygon.c +100 -0
  523. package/vendor/raylib/examples/textures/textures_polygon.png +0 -0
  524. package/vendor/raylib/examples/textures/textures_raw_data.c +99 -0
  525. package/vendor/raylib/examples/textures/textures_raw_data.png +0 -0
  526. package/vendor/raylib/examples/textures/textures_rectangle.c +99 -0
  527. package/vendor/raylib/examples/textures/textures_rectangle.png +0 -0
  528. package/vendor/raylib/examples/textures/textures_sprite_button.c +97 -0
  529. package/vendor/raylib/examples/textures/textures_sprite_button.png +0 -0
  530. package/vendor/raylib/examples/textures/textures_sprite_explosion.c +120 -0
  531. package/vendor/raylib/examples/textures/textures_sprite_explosion.png +0 -0
  532. package/vendor/raylib/examples/textures/textures_srcrec_dstrec.c +82 -0
  533. package/vendor/raylib/examples/textures/textures_srcrec_dstrec.png +0 -0
  534. package/vendor/raylib/examples/textures/textures_to_image.c +68 -0
  535. package/vendor/raylib/examples/textures/textures_to_image.png +0 -0
  536. package/vendor/raylib/logo/raylib.ico +0 -0
  537. package/vendor/raylib/logo/raylib_128x128.png +0 -0
  538. package/vendor/raylib/logo/raylib_144x144.png +0 -0
  539. package/vendor/raylib/logo/raylib_16x16.png +0 -0
  540. package/vendor/raylib/logo/raylib_180x180.png +0 -0
  541. package/vendor/raylib/logo/raylib_24x24.png +0 -0
  542. package/vendor/raylib/logo/raylib_256x256.png +0 -0
  543. package/vendor/raylib/logo/raylib_32x32.png +0 -0
  544. package/vendor/raylib/logo/raylib_36x36.png +0 -0
  545. package/vendor/raylib/logo/raylib_48x48.png +0 -0
  546. package/vendor/raylib/logo/raylib_512x512.png +0 -0
  547. package/vendor/raylib/logo/raylib_64x64.png +0 -0
  548. package/vendor/raylib/logo/raylib_72x72.png +0 -0
  549. package/vendor/raylib/logo/raylib_96x96.png +0 -0
  550. package/vendor/raylib/logo/raylib_logo_animation.gif +0 -0
  551. package/vendor/raylib/parser/LICENSE +16 -0
  552. package/vendor/raylib/parser/README.md +63 -0
  553. package/vendor/raylib/parser/raylib_api.json +6668 -0
  554. package/vendor/raylib/parser/raylib_api.txt +3568 -0
  555. package/vendor/raylib/parser/raylib_api.xml +2509 -0
  556. package/vendor/raylib/parser/raylib_parser.c +1003 -0
  557. package/vendor/raylib/projects/4coder/Makefile +401 -0
  558. package/vendor/raylib/projects/4coder/Makefile.Android +300 -0
  559. package/vendor/raylib/projects/4coder/main.c +39 -0
  560. package/vendor/raylib/projects/4coder/project.4coder +54 -0
  561. package/vendor/raylib/projects/Builder/README.md +24 -0
  562. package/vendor/raylib/projects/Builder/examples/README.md +1 -0
  563. package/vendor/raylib/projects/Builder/examples/meson.build +25 -0
  564. package/vendor/raylib/projects/Builder/meson.build +25 -0
  565. package/vendor/raylib/projects/CMake/CMakeLists.txt +44 -0
  566. package/vendor/raylib/projects/CMake/core_basic_window.c +62 -0
  567. package/vendor/raylib/projects/CodeBlocks/README.md +22 -0
  568. package/vendor/raylib/projects/CodeBlocks/compiler_settings.png +0 -0
  569. package/vendor/raylib/projects/CodeBlocks/core_basic_window.c +58 -0
  570. package/vendor/raylib/projects/CodeBlocks/core_basic_window.cbp +137 -0
  571. package/vendor/raylib/projects/Geany/core_basic_window.c +52 -0
  572. package/vendor/raylib/projects/Geany/raylib.c.tags +452 -0
  573. package/vendor/raylib/projects/Geany/raylib_compile_execute.bat +21 -0
  574. package/vendor/raylib/projects/Geany/raylib_compile_sources.bat +42 -0
  575. package/vendor/raylib/projects/Geany/raylib_project.geany +41 -0
  576. package/vendor/raylib/projects/Notepad++/README.md +19 -0
  577. package/vendor/raylib/projects/Notepad++/c_raylib.xml +3104 -0
  578. package/vendor/raylib/projects/Notepad++/npes_saved_mingw.txt +0 -0
  579. package/vendor/raylib/projects/Notepad++/npes_saved_tcc.txt +0 -0
  580. package/vendor/raylib/projects/Notepad++/npes_saved_w64devkit.txt +0 -0
  581. package/vendor/raylib/projects/Notepad++/npes_saved_zig.txt +0 -0
  582. package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_npp.xml +3060 -0
  583. package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_npp_parser.c +150 -0
  584. package/vendor/raylib/projects/Notepad++/raylib_npp_parser/raylib_to_parse.h +631 -0
  585. package/vendor/raylib/projects/README.md +18 -0
  586. package/vendor/raylib/projects/SublimeText/README.md +13 -0
  587. package/vendor/raylib/projects/SublimeText/raylib.sublime-build +13 -0
  588. package/vendor/raylib/projects/SublimeText/raylib.sublime-project +8 -0
  589. package/vendor/raylib/projects/VS2019/examples/audio_module_playing.vcxproj +387 -0
  590. package/vendor/raylib/projects/VS2019/examples/audio_multichannel_sound.vcxproj +387 -0
  591. package/vendor/raylib/projects/VS2019/examples/audio_music_stream.vcxproj +387 -0
  592. package/vendor/raylib/projects/VS2019/examples/audio_raw_stream.vcxproj +387 -0
  593. package/vendor/raylib/projects/VS2019/examples/audio_sound_loading.vcxproj +387 -0
  594. package/vendor/raylib/projects/VS2019/examples/core_2d_camera.vcxproj +387 -0
  595. package/vendor/raylib/projects/VS2019/examples/core_2d_camera_platformer.vcxproj +387 -0
  596. package/vendor/raylib/projects/VS2019/examples/core_3d_camera_first_person.vcxproj +387 -0
  597. package/vendor/raylib/projects/VS2019/examples/core_3d_camera_free.vcxproj +387 -0
  598. package/vendor/raylib/projects/VS2019/examples/core_3d_camera_mode.vcxproj +387 -0
  599. package/vendor/raylib/projects/VS2019/examples/core_3d_picking.vcxproj +387 -0
  600. package/vendor/raylib/projects/VS2019/examples/core_basic_window.vcxproj +387 -0
  601. package/vendor/raylib/projects/VS2019/examples/core_custom_logging.vcxproj +387 -0
  602. package/vendor/raylib/projects/VS2019/examples/core_drop_files.vcxproj +387 -0
  603. package/vendor/raylib/projects/VS2019/examples/core_input_gamepad.vcxproj +387 -0
  604. package/vendor/raylib/projects/VS2019/examples/core_input_gestures.vcxproj +387 -0
  605. package/vendor/raylib/projects/VS2019/examples/core_input_keys.vcxproj +387 -0
  606. package/vendor/raylib/projects/VS2019/examples/core_input_mouse.vcxproj +387 -0
  607. package/vendor/raylib/projects/VS2019/examples/core_input_mouse_wheel.vcxproj +387 -0
  608. package/vendor/raylib/projects/VS2019/examples/core_input_multitouch.vcxproj +387 -0
  609. package/vendor/raylib/projects/VS2019/examples/core_loading_thread.vcxproj +387 -0
  610. package/vendor/raylib/projects/VS2019/examples/core_quat_conversion.vcxproj +387 -0
  611. package/vendor/raylib/projects/VS2019/examples/core_random_values.vcxproj +387 -0
  612. package/vendor/raylib/projects/VS2019/examples/core_scissor_test.vcxproj +387 -0
  613. package/vendor/raylib/projects/VS2019/examples/core_split_screen.vcxproj +387 -0
  614. package/vendor/raylib/projects/VS2019/examples/core_storage_values.vcxproj +387 -0
  615. package/vendor/raylib/projects/VS2019/examples/core_vr_simulator.vcxproj +387 -0
  616. package/vendor/raylib/projects/VS2019/examples/core_window_flags.vcxproj +387 -0
  617. package/vendor/raylib/projects/VS2019/examples/core_window_letterbox.vcxproj +387 -0
  618. package/vendor/raylib/projects/VS2019/examples/core_world_screen.vcxproj +387 -0
  619. package/vendor/raylib/projects/VS2019/examples/easings_testbed.vcxproj +387 -0
  620. package/vendor/raylib/projects/VS2019/examples/embedded_files_loading.vcxproj +387 -0
  621. package/vendor/raylib/projects/VS2019/examples/models_animation.vcxproj +387 -0
  622. package/vendor/raylib/projects/VS2019/examples/models_billboard.vcxproj +387 -0
  623. package/vendor/raylib/projects/VS2019/examples/models_box_collisions.vcxproj +387 -0
  624. package/vendor/raylib/projects/VS2019/examples/models_cubicmap.vcxproj +387 -0
  625. package/vendor/raylib/projects/VS2019/examples/models_first_person_maze.vcxproj +387 -0
  626. package/vendor/raylib/projects/VS2019/examples/models_geometric_shapes.vcxproj +387 -0
  627. package/vendor/raylib/projects/VS2019/examples/models_heightmap.vcxproj +387 -0
  628. package/vendor/raylib/projects/VS2019/examples/models_loading.vcxproj +387 -0
  629. package/vendor/raylib/projects/VS2019/examples/models_loading_gltf.vcxproj +387 -0
  630. package/vendor/raylib/projects/VS2019/examples/models_loading_vox.vcxproj +387 -0
  631. package/vendor/raylib/projects/VS2019/examples/models_mesh_generation.vcxproj +387 -0
  632. package/vendor/raylib/projects/VS2019/examples/models_mesh_picking.vcxproj +387 -0
  633. package/vendor/raylib/projects/VS2019/examples/models_orthographic_projection.vcxproj +387 -0
  634. package/vendor/raylib/projects/VS2019/examples/models_rlgl_solar_system.vcxproj +387 -0
  635. package/vendor/raylib/projects/VS2019/examples/models_skybox.vcxproj +387 -0
  636. package/vendor/raylib/projects/VS2019/examples/models_waving_cubes.vcxproj +387 -0
  637. package/vendor/raylib/projects/VS2019/examples/models_yaw_pitch_roll.vcxproj +387 -0
  638. package/vendor/raylib/projects/VS2019/examples/physics_demo.vcxproj +387 -0
  639. package/vendor/raylib/projects/VS2019/examples/physics_friction.vcxproj +387 -0
  640. package/vendor/raylib/projects/VS2019/examples/physics_movement.vcxproj +387 -0
  641. package/vendor/raylib/projects/VS2019/examples/physics_restitution.vcxproj +387 -0
  642. package/vendor/raylib/projects/VS2019/examples/physics_shatter.vcxproj +387 -0
  643. package/vendor/raylib/projects/VS2019/examples/raudio_standalone.vcxproj +387 -0
  644. package/vendor/raylib/projects/VS2019/examples/rlgl_standalone.vcxproj +391 -0
  645. package/vendor/raylib/projects/VS2019/examples/shaders_basic_lighting.vcxproj +387 -0
  646. package/vendor/raylib/projects/VS2019/examples/shaders_custom_uniform.vcxproj +387 -0
  647. package/vendor/raylib/projects/VS2019/examples/shaders_eratosthenes.vcxproj +387 -0
  648. package/vendor/raylib/projects/VS2019/examples/shaders_fog.vcxproj +387 -0
  649. package/vendor/raylib/projects/VS2019/examples/shaders_hot_reloading.vcxproj +387 -0
  650. package/vendor/raylib/projects/VS2019/examples/shaders_julia_set.vcxproj +387 -0
  651. package/vendor/raylib/projects/VS2019/examples/shaders_mesh_instancing.vcxproj +387 -0
  652. package/vendor/raylib/projects/VS2019/examples/shaders_model_shader.vcxproj +387 -0
  653. package/vendor/raylib/projects/VS2019/examples/shaders_multi_sample2d.vcxproj +387 -0
  654. package/vendor/raylib/projects/VS2019/examples/shaders_palette_switch.vcxproj +387 -0
  655. package/vendor/raylib/projects/VS2019/examples/shaders_postprocessing.vcxproj +387 -0
  656. package/vendor/raylib/projects/VS2019/examples/shaders_raymarching.vcxproj +387 -0
  657. package/vendor/raylib/projects/VS2019/examples/shaders_shapes_textures.vcxproj +387 -0
  658. package/vendor/raylib/projects/VS2019/examples/shaders_simple_mask.vcxproj +387 -0
  659. package/vendor/raylib/projects/VS2019/examples/shaders_spotlight.vcxproj +387 -0
  660. package/vendor/raylib/projects/VS2019/examples/shaders_texture_drawing.vcxproj +387 -0
  661. package/vendor/raylib/projects/VS2019/examples/shaders_texture_waves.vcxproj +387 -0
  662. package/vendor/raylib/projects/VS2019/examples/shapes_basic_shapes.vcxproj +387 -0
  663. package/vendor/raylib/projects/VS2019/examples/shapes_bouncing_ball.vcxproj +387 -0
  664. package/vendor/raylib/projects/VS2019/examples/shapes_collision_area.vcxproj +387 -0
  665. package/vendor/raylib/projects/VS2019/examples/shapes_colors_palette.vcxproj +387 -0
  666. package/vendor/raylib/projects/VS2019/examples/shapes_draw_circle_sector.vcxproj +387 -0
  667. package/vendor/raylib/projects/VS2019/examples/shapes_draw_rectangle_rounded.vcxproj +387 -0
  668. package/vendor/raylib/projects/VS2019/examples/shapes_draw_ring.vcxproj +387 -0
  669. package/vendor/raylib/projects/VS2019/examples/shapes_easings_ball_anim.vcxproj +387 -0
  670. package/vendor/raylib/projects/VS2019/examples/shapes_easings_box_anim.vcxproj +387 -0
  671. package/vendor/raylib/projects/VS2019/examples/shapes_easings_rectangle_array.vcxproj +387 -0
  672. package/vendor/raylib/projects/VS2019/examples/shapes_following_eyes.vcxproj +387 -0
  673. package/vendor/raylib/projects/VS2019/examples/shapes_lines_bezier.vcxproj +387 -0
  674. package/vendor/raylib/projects/VS2019/examples/shapes_logo_raylib.vcxproj +387 -0
  675. package/vendor/raylib/projects/VS2019/examples/shapes_logo_raylib_anim.vcxproj +387 -0
  676. package/vendor/raylib/projects/VS2019/examples/shapes_rectangle_scaling.vcxproj +387 -0
  677. package/vendor/raylib/projects/VS2019/examples/text_font_filters.vcxproj +387 -0
  678. package/vendor/raylib/projects/VS2019/examples/text_font_loading.vcxproj +387 -0
  679. package/vendor/raylib/projects/VS2019/examples/text_font_sdf.vcxproj +387 -0
  680. package/vendor/raylib/projects/VS2019/examples/text_font_spritefont.vcxproj +387 -0
  681. package/vendor/raylib/projects/VS2019/examples/text_format_text.vcxproj +387 -0
  682. package/vendor/raylib/projects/VS2019/examples/text_input_box.vcxproj +387 -0
  683. package/vendor/raylib/projects/VS2019/examples/text_raylib_fonts.vcxproj +387 -0
  684. package/vendor/raylib/projects/VS2019/examples/text_rectangle_bounds.vcxproj +387 -0
  685. package/vendor/raylib/projects/VS2019/examples/text_unicode.vcxproj +387 -0
  686. package/vendor/raylib/projects/VS2019/examples/text_writing_anim.vcxproj +387 -0
  687. package/vendor/raylib/projects/VS2019/examples/textures_background_scrolling.vcxproj +387 -0
  688. package/vendor/raylib/projects/VS2019/examples/textures_blend_modes.vcxproj +387 -0
  689. package/vendor/raylib/projects/VS2019/examples/textures_bunnymark.vcxproj +387 -0
  690. package/vendor/raylib/projects/VS2019/examples/textures_draw_tiled.vcxproj +387 -0
  691. package/vendor/raylib/projects/VS2019/examples/textures_image_drawing.vcxproj +387 -0
  692. package/vendor/raylib/projects/VS2019/examples/textures_image_generation.vcxproj +387 -0
  693. package/vendor/raylib/projects/VS2019/examples/textures_image_loading.vcxproj +387 -0
  694. package/vendor/raylib/projects/VS2019/examples/textures_image_processing.vcxproj +387 -0
  695. package/vendor/raylib/projects/VS2019/examples/textures_image_text.vcxproj +387 -0
  696. package/vendor/raylib/projects/VS2019/examples/textures_logo_raylib.vcxproj +387 -0
  697. package/vendor/raylib/projects/VS2019/examples/textures_mouse_painting.vcxproj +387 -0
  698. package/vendor/raylib/projects/VS2019/examples/textures_npatch_drawing.vcxproj +387 -0
  699. package/vendor/raylib/projects/VS2019/examples/textures_particles_blending.vcxproj +387 -0
  700. package/vendor/raylib/projects/VS2019/examples/textures_raw_data.vcxproj +387 -0
  701. package/vendor/raylib/projects/VS2019/examples/textures_rectangle.vcxproj +387 -0
  702. package/vendor/raylib/projects/VS2019/examples/textures_sprite_button.vcxproj +387 -0
  703. package/vendor/raylib/projects/VS2019/examples/textures_sprite_explosion.vcxproj +387 -0
  704. package/vendor/raylib/projects/VS2019/examples/textures_srcrec_dstrec.vcxproj +387 -0
  705. package/vendor/raylib/projects/VS2019/examples/textures_to_image.vcxproj +387 -0
  706. package/vendor/raylib/projects/VS2019/raylib/raylib.rc +0 -0
  707. package/vendor/raylib/projects/VS2019/raylib/raylib.vcxproj +341 -0
  708. package/vendor/raylib/projects/VS2019/raylib/resource.h +14 -0
  709. package/vendor/raylib/projects/VS2019/raylib.sln +2274 -0
  710. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.c +437 -0
  711. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.h +344 -0
  712. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/main.c +64 -0
  713. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj +226 -0
  714. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters +10 -0
  715. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user +4 -0
  716. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.Packaging/AndroidManifest.xml +22 -0
  717. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.Packaging/build.xml +90 -0
  718. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.Packaging/project.properties +3 -0
  719. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.Packaging/raylib_android.Packaging.androidproj +134 -0
  720. package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.Packaging/res/values/strings.xml +4 -0
  721. package/vendor/raylib/projects/VS2019-Android/raylib_android.sln +75 -0
  722. package/vendor/raylib/projects/VSCode/.vscode/c_cpp_properties.json +63 -0
  723. package/vendor/raylib/projects/VSCode/.vscode/launch.json +60 -0
  724. package/vendor/raylib/projects/VSCode/.vscode/settings.json +11 -0
  725. package/vendor/raylib/projects/VSCode/.vscode/tasks.json +71 -0
  726. package/vendor/raylib/projects/VSCode/Makefile +408 -0
  727. package/vendor/raylib/projects/VSCode/Makefile.Android +300 -0
  728. package/vendor/raylib/projects/VSCode/main.c +83 -0
  729. package/vendor/raylib/projects/VSCode/main.code-workspace +16 -0
  730. package/vendor/raylib/projects/scripts/README.md +68 -0
  731. package/vendor/raylib/projects/scripts/build-linux.sh +169 -0
  732. package/vendor/raylib/projects/scripts/build-osx.sh +171 -0
  733. package/vendor/raylib/projects/scripts/build-rpi.sh +169 -0
  734. package/vendor/raylib/projects/scripts/build-windows.bat +219 -0
  735. package/vendor/raylib/projects/scripts/core_basic_window.c +61 -0
  736. package/vendor/raylib/raylib.pc.in +13 -0
  737. package/vendor/raylib/src/CMakeLists.txt +121 -0
  738. package/vendor/raylib/src/Makefile +696 -0
  739. package/vendor/raylib/src/build.zig +60 -0
  740. package/vendor/raylib/src/config.h +230 -0
  741. package/vendor/raylib/src/external/cgltf.h +6501 -0
  742. package/vendor/raylib/src/external/dirent.h +183 -0
  743. package/vendor/raylib/src/external/dr_flac.h +12269 -0
  744. package/vendor/raylib/src/external/dr_mp3.h +4787 -0
  745. package/vendor/raylib/src/external/dr_wav.h +8019 -0
  746. package/vendor/raylib/src/external/glad.h +8640 -0
  747. package/vendor/raylib/src/external/glfw/.mailmap +10 -0
  748. package/vendor/raylib/src/external/glfw/CMake/GenerateMappings.cmake +33 -0
  749. package/vendor/raylib/src/external/glfw/CMake/Info.plist.in +38 -0
  750. package/vendor/raylib/src/external/glfw/CMake/MacOSXBundleInfo.plist.in +38 -0
  751. package/vendor/raylib/src/external/glfw/CMake/cmake_uninstall.cmake.in +29 -0
  752. package/vendor/raylib/src/external/glfw/CMake/glfw3.pc.in +13 -0
  753. package/vendor/raylib/src/external/glfw/CMake/glfw3Config.cmake.in +3 -0
  754. package/vendor/raylib/src/external/glfw/CMake/i686-w64-mingw32-clang.cmake +13 -0
  755. package/vendor/raylib/src/external/glfw/CMake/i686-w64-mingw32.cmake +13 -0
  756. package/vendor/raylib/src/external/glfw/CMake/modules/FindEpollShim.cmake +17 -0
  757. package/vendor/raylib/src/external/glfw/CMake/modules/FindOSMesa.cmake +18 -0
  758. package/vendor/raylib/src/external/glfw/CMake/modules/FindWaylandProtocols.cmake +26 -0
  759. package/vendor/raylib/src/external/glfw/CMake/modules/FindXKBCommon.cmake +34 -0
  760. package/vendor/raylib/src/external/glfw/CMake/x86_64-w64-mingw32-clang.cmake +13 -0
  761. package/vendor/raylib/src/external/glfw/CMake/x86_64-w64-mingw32.cmake +13 -0
  762. package/vendor/raylib/src/external/glfw/CMakeLists.txt +323 -0
  763. package/vendor/raylib/src/external/glfw/LICENSE.md +23 -0
  764. package/vendor/raylib/src/external/glfw/README.md +477 -0
  765. package/vendor/raylib/src/external/glfw/deps/getopt.c +230 -0
  766. package/vendor/raylib/src/external/glfw/deps/getopt.h +57 -0
  767. package/vendor/raylib/src/external/glfw/deps/glad/gl.h +3840 -0
  768. package/vendor/raylib/src/external/glfw/deps/glad/khrplatform.h +282 -0
  769. package/vendor/raylib/src/external/glfw/deps/glad/vk_platform.h +92 -0
  770. package/vendor/raylib/src/external/glfw/deps/glad/vulkan.h +3480 -0
  771. package/vendor/raylib/src/external/glfw/deps/glad_gl.c +1791 -0
  772. package/vendor/raylib/src/external/glfw/deps/glad_vulkan.c +593 -0
  773. package/vendor/raylib/src/external/glfw/deps/mingw/_mingw_dxhelper.h +117 -0
  774. package/vendor/raylib/src/external/glfw/deps/mingw/dinput.h +2467 -0
  775. package/vendor/raylib/src/external/glfw/deps/mingw/xinput.h +239 -0
  776. package/vendor/raylib/src/external/glfw/deps/vs2008/stdint.h +247 -0
  777. package/vendor/raylib/src/external/glfw/include/GLFW/glfw3.h +6075 -0
  778. package/vendor/raylib/src/external/glfw/include/GLFW/glfw3native.h +530 -0
  779. package/vendor/raylib/src/external/glfw/src/CMakeLists.txt +246 -0
  780. package/vendor/raylib/src/external/glfw/src/cocoa_init.m +620 -0
  781. package/vendor/raylib/src/external/glfw/src/cocoa_joystick.h +46 -0
  782. package/vendor/raylib/src/external/glfw/src/cocoa_joystick.m +483 -0
  783. package/vendor/raylib/src/external/glfw/src/cocoa_monitor.m +631 -0
  784. package/vendor/raylib/src/external/glfw/src/cocoa_platform.h +206 -0
  785. package/vendor/raylib/src/external/glfw/src/cocoa_time.c +62 -0
  786. package/vendor/raylib/src/external/glfw/src/cocoa_window.m +1923 -0
  787. package/vendor/raylib/src/external/glfw/src/context.c +756 -0
  788. package/vendor/raylib/src/external/glfw/src/egl_context.c +846 -0
  789. package/vendor/raylib/src/external/glfw/src/egl_context.h +229 -0
  790. package/vendor/raylib/src/external/glfw/src/glfw.rc.in +30 -0
  791. package/vendor/raylib/src/external/glfw/src/glfw_config.h.in +58 -0
  792. package/vendor/raylib/src/external/glfw/src/glx_context.c +699 -0
  793. package/vendor/raylib/src/external/glfw/src/glx_context.h +181 -0
  794. package/vendor/raylib/src/external/glfw/src/init.c +357 -0
  795. package/vendor/raylib/src/external/glfw/src/input.c +1406 -0
  796. package/vendor/raylib/src/external/glfw/src/internal.h +799 -0
  797. package/vendor/raylib/src/external/glfw/src/linux_joystick.c +428 -0
  798. package/vendor/raylib/src/external/glfw/src/linux_joystick.h +59 -0
  799. package/vendor/raylib/src/external/glfw/src/mappings.h +1550 -0
  800. package/vendor/raylib/src/external/glfw/src/mappings.h.in +73 -0
  801. package/vendor/raylib/src/external/glfw/src/monitor.c +542 -0
  802. package/vendor/raylib/src/external/glfw/src/nsgl_context.h +66 -0
  803. package/vendor/raylib/src/external/glfw/src/nsgl_context.m +369 -0
  804. package/vendor/raylib/src/external/glfw/src/null_init.c +57 -0
  805. package/vendor/raylib/src/external/glfw/src/null_joystick.c +53 -0
  806. package/vendor/raylib/src/external/glfw/src/null_joystick.h +31 -0
  807. package/vendor/raylib/src/external/glfw/src/null_monitor.c +159 -0
  808. package/vendor/raylib/src/external/glfw/src/null_platform.h +89 -0
  809. package/vendor/raylib/src/external/glfw/src/null_window.c +670 -0
  810. package/vendor/raylib/src/external/glfw/src/osmesa_context.c +372 -0
  811. package/vendor/raylib/src/external/glfw/src/osmesa_context.h +90 -0
  812. package/vendor/raylib/src/external/glfw/src/posix_thread.c +105 -0
  813. package/vendor/raylib/src/external/glfw/src/posix_thread.h +51 -0
  814. package/vendor/raylib/src/external/glfw/src/posix_time.c +90 -0
  815. package/vendor/raylib/src/external/glfw/src/posix_time.h +44 -0
  816. package/vendor/raylib/src/external/glfw/src/vulkan.c +332 -0
  817. package/vendor/raylib/src/external/glfw/src/wgl_context.c +798 -0
  818. package/vendor/raylib/src/external/glfw/src/wgl_context.h +160 -0
  819. package/vendor/raylib/src/external/glfw/src/win32_init.c +636 -0
  820. package/vendor/raylib/src/external/glfw/src/win32_joystick.c +753 -0
  821. package/vendor/raylib/src/external/glfw/src/win32_joystick.h +53 -0
  822. package/vendor/raylib/src/external/glfw/src/win32_monitor.c +537 -0
  823. package/vendor/raylib/src/external/glfw/src/win32_platform.h +462 -0
  824. package/vendor/raylib/src/external/glfw/src/win32_thread.c +99 -0
  825. package/vendor/raylib/src/external/glfw/src/win32_time.c +76 -0
  826. package/vendor/raylib/src/external/glfw/src/win32_window.c +2405 -0
  827. package/vendor/raylib/src/external/glfw/src/window.c +1114 -0
  828. package/vendor/raylib/src/external/glfw/src/wl_init.c +1310 -0
  829. package/vendor/raylib/src/external/glfw/src/wl_monitor.c +231 -0
  830. package/vendor/raylib/src/external/glfw/src/wl_platform.h +352 -0
  831. package/vendor/raylib/src/external/glfw/src/wl_window.c +1814 -0
  832. package/vendor/raylib/src/external/glfw/src/x11_init.c +1500 -0
  833. package/vendor/raylib/src/external/glfw/src/x11_monitor.c +614 -0
  834. package/vendor/raylib/src/external/glfw/src/x11_platform.h +798 -0
  835. package/vendor/raylib/src/external/glfw/src/x11_window.c +3310 -0
  836. package/vendor/raylib/src/external/glfw/src/xkb_unicode.c +942 -0
  837. package/vendor/raylib/src/external/glfw/src/xkb_unicode.h +28 -0
  838. package/vendor/raylib/src/external/jar_mod.h +1596 -0
  839. package/vendor/raylib/src/external/jar_xm.h +2470 -0
  840. package/vendor/raylib/src/external/miniaudio.h +70273 -0
  841. package/vendor/raylib/src/external/msf_gif.h +717 -0
  842. package/vendor/raylib/src/external/par_shapes.h +2155 -0
  843. package/vendor/raylib/src/external/sdefl.h +696 -0
  844. package/vendor/raylib/src/external/sinfl.h +584 -0
  845. package/vendor/raylib/src/external/stb_image.h +7897 -0
  846. package/vendor/raylib/src/external/stb_image_resize.h +2634 -0
  847. package/vendor/raylib/src/external/stb_image_write.h +1724 -0
  848. package/vendor/raylib/src/external/stb_rect_pack.h +623 -0
  849. package/vendor/raylib/src/external/stb_truetype.h +5077 -0
  850. package/vendor/raylib/src/external/stb_vorbis.h +5475 -0
  851. package/vendor/raylib/src/external/tinyobj_loader_c.h +1589 -0
  852. package/vendor/raylib/src/external/vox_loader.h +710 -0
  853. package/vendor/raylib/src/extras/easings.h +263 -0
  854. package/vendor/raylib/src/extras/physac.h +1977 -0
  855. package/vendor/raylib/src/extras/raygui.h +4342 -0
  856. package/vendor/raylib/src/extras/rmem.h +751 -0
  857. package/vendor/raylib/src/raudio.c +2380 -0
  858. package/vendor/raylib/src/raudio.h +198 -0
  859. package/vendor/raylib/src/raylib.dll.rc +27 -0
  860. package/vendor/raylib/src/raylib.dll.rc.data +0 -0
  861. package/vendor/raylib/src/raylib.h +1536 -0
  862. package/vendor/raylib/src/raylib.ico +0 -0
  863. package/vendor/raylib/src/raylib.rc +27 -0
  864. package/vendor/raylib/src/raylib.rc.data +0 -0
  865. package/vendor/raylib/src/raymath.h +1853 -0
  866. package/vendor/raylib/src/rcamera.h +567 -0
  867. package/vendor/raylib/src/rcore.c +6772 -0
  868. package/vendor/raylib/src/rgestures.h +566 -0
  869. package/vendor/raylib/src/rglfw.c +126 -0
  870. package/vendor/raylib/src/rlgl.h +4677 -0
  871. package/vendor/raylib/src/rmodels.c +5041 -0
  872. package/vendor/raylib/src/rshapes.c +1759 -0
  873. package/vendor/raylib/src/rtext.c +1790 -0
  874. package/vendor/raylib/src/rtextures.c +4761 -0
  875. package/vendor/raylib/src/shell.html +328 -0
  876. package/vendor/raylib/src/utils.c +433 -0
  877. package/vendor/raylib/src/utils.h +81 -0
  878. package/vendor/sqlite3/shell.c +23487 -0
  879. package/vendor/sqlite3/sqlite3.c +239246 -0
  880. package/vendor/sqlite3/sqlite3.h +12802 -0
  881. package/vendor/sqlite3/sqlite3ext.h +689 -0
  882. package/CMakeLists.txt +0 -60
@@ -0,0 +1,4761 @@
1
+ /**********************************************************************************************
2
+ *
3
+ * rtextures - Basic functions to load and draw textures
4
+ *
5
+ * CONFIGURATION:
6
+ *
7
+ * #define SUPPORT_FILEFORMAT_BMP
8
+ * #define SUPPORT_FILEFORMAT_PNG
9
+ * #define SUPPORT_FILEFORMAT_TGA
10
+ * #define SUPPORT_FILEFORMAT_JPG
11
+ * #define SUPPORT_FILEFORMAT_GIF
12
+ * #define SUPPORT_FILEFORMAT_PSD
13
+ * #define SUPPORT_FILEFORMAT_PIC
14
+ * #define SUPPORT_FILEFORMAT_HDR
15
+ * #define SUPPORT_FILEFORMAT_DDS
16
+ * #define SUPPORT_FILEFORMAT_PKM
17
+ * #define SUPPORT_FILEFORMAT_KTX
18
+ * #define SUPPORT_FILEFORMAT_PVR
19
+ * #define SUPPORT_FILEFORMAT_ASTC
20
+ * Select desired fileformats to be supported for image data loading. Some of those formats are
21
+ * supported by default, to remove support, just comment unrequired #define in this module
22
+ *
23
+ * #define SUPPORT_IMAGE_EXPORT
24
+ * Support image export in multiple file formats
25
+ *
26
+ * #define SUPPORT_IMAGE_MANIPULATION
27
+ * Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop...
28
+ * If not defined only three image editing functions supported: ImageFormat(), ImageAlphaMask(), ImageToPOT()
29
+ *
30
+ * #define SUPPORT_IMAGE_GENERATION
31
+ * Support procedural image generation functionality (gradient, spot, perlin-noise, cellular)
32
+ *
33
+ * DEPENDENCIES:
34
+ * stb_image - Multiple image formats loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
35
+ * NOTE: stb_image has been slightly modified to support Android platform.
36
+ * stb_image_resize - Multiple image resize algorythms
37
+ *
38
+ *
39
+ * LICENSE: zlib/libpng
40
+ *
41
+ * Copyright (c) 2013-2021 Ramon Santamaria (@raysan5)
42
+ *
43
+ * This software is provided "as-is", without any express or implied warranty. In no event
44
+ * will the authors be held liable for any damages arising from the use of this software.
45
+ *
46
+ * Permission is granted to anyone to use this software for any purpose, including commercial
47
+ * applications, and to alter it and redistribute it freely, subject to the following restrictions:
48
+ *
49
+ * 1. The origin of this software must not be misrepresented; you must not claim that you
50
+ * wrote the original software. If you use this software in a product, an acknowledgment
51
+ * in the product documentation would be appreciated but is not required.
52
+ *
53
+ * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
54
+ * as being the original software.
55
+ *
56
+ * 3. This notice may not be removed or altered from any source distribution.
57
+ *
58
+ **********************************************************************************************/
59
+
60
+ #include "raylib.h" // Declares module functions
61
+
62
+ // Check if config flags have been externally provided on compilation line
63
+ #if !defined(EXTERNAL_CONFIG_FLAGS)
64
+ #include "config.h" // Defines module configuration flags
65
+ #endif
66
+
67
+ #include "utils.h" // Required for: TRACELOG() and fopen() Android mapping
68
+ #include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2
69
+
70
+ #include <stdlib.h> // Required for: malloc(), free()
71
+ #include <string.h> // Required for: strlen() [Used in ImageTextEx()]
72
+ #include <math.h> // Required for: fabsf()
73
+ #include <stdio.h> // Required for: sprintf() [Used in ExportImageAsCode()]
74
+
75
+ // Support only desired texture formats on stb_image
76
+ #if !defined(SUPPORT_FILEFORMAT_BMP)
77
+ #define STBI_NO_BMP
78
+ #endif
79
+ #if !defined(SUPPORT_FILEFORMAT_PNG)
80
+ #define STBI_NO_PNG
81
+ #endif
82
+ #if !defined(SUPPORT_FILEFORMAT_TGA)
83
+ #define STBI_NO_TGA
84
+ #endif
85
+ #if !defined(SUPPORT_FILEFORMAT_JPG)
86
+ #define STBI_NO_JPEG // Image format .jpg and .jpeg
87
+ #endif
88
+ #if !defined(SUPPORT_FILEFORMAT_PSD)
89
+ #define STBI_NO_PSD
90
+ #endif
91
+ #if !defined(SUPPORT_FILEFORMAT_GIF)
92
+ #define STBI_NO_GIF
93
+ #endif
94
+ #if !defined(SUPPORT_FILEFORMAT_PIC)
95
+ #define STBI_NO_PIC
96
+ #endif
97
+ #if !defined(SUPPORT_FILEFORMAT_HDR)
98
+ #define STBI_NO_HDR
99
+ #endif
100
+
101
+ // Image fileformats not supported by default
102
+ #define STBI_NO_PIC
103
+ #define STBI_NO_PNM // Image format .ppm and .pgm
104
+
105
+ #if defined(__TINYC__)
106
+ #define STBI_NO_SIMD
107
+ #endif
108
+
109
+ #if (defined(SUPPORT_FILEFORMAT_BMP) || \
110
+ defined(SUPPORT_FILEFORMAT_PNG) || \
111
+ defined(SUPPORT_FILEFORMAT_TGA) || \
112
+ defined(SUPPORT_FILEFORMAT_JPG) || \
113
+ defined(SUPPORT_FILEFORMAT_PSD) || \
114
+ defined(SUPPORT_FILEFORMAT_GIF) || \
115
+ defined(SUPPORT_FILEFORMAT_PIC) || \
116
+ defined(SUPPORT_FILEFORMAT_HDR))
117
+
118
+ #define STBI_MALLOC RL_MALLOC
119
+ #define STBI_FREE RL_FREE
120
+ #define STBI_REALLOC RL_REALLOC
121
+
122
+ #define STB_IMAGE_IMPLEMENTATION
123
+ #include "external/stb_image.h" // Required for: stbi_load_from_file()
124
+ // NOTE: Used to read image data (multiple formats support)
125
+ #endif
126
+
127
+ #if defined(SUPPORT_IMAGE_EXPORT)
128
+ #define STBIW_MALLOC RL_MALLOC
129
+ #define STBIW_FREE RL_FREE
130
+ #define STBIW_REALLOC RL_REALLOC
131
+
132
+ #define STB_IMAGE_WRITE_IMPLEMENTATION
133
+ #include "external/stb_image_write.h" // Required for: stbi_write_*()
134
+ #endif
135
+
136
+ #if defined(SUPPORT_IMAGE_MANIPULATION)
137
+ #define STBIR_MALLOC(size,c) ((void)(c), RL_MALLOC(size))
138
+ #define STBIR_FREE(ptr,c) ((void)(c), RL_FREE(ptr))
139
+
140
+ #define STB_IMAGE_RESIZE_IMPLEMENTATION
141
+ #include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() [ImageResize()]
142
+ #endif
143
+
144
+ //----------------------------------------------------------------------------------
145
+ // Defines and Macros
146
+ //----------------------------------------------------------------------------------
147
+ #ifndef PIXELFORMAT_UNCOMPRESSED_R5G5B5A1_ALPHA_THRESHOLD
148
+ #define PIXELFORMAT_UNCOMPRESSED_R5G5B5A1_ALPHA_THRESHOLD 50 // Threshold over 255 to set alpha as 0
149
+ #endif
150
+
151
+ //----------------------------------------------------------------------------------
152
+ // Types and Structures Definition
153
+ //----------------------------------------------------------------------------------
154
+ // ...
155
+
156
+ //----------------------------------------------------------------------------------
157
+ // Global Variables Definition
158
+ //----------------------------------------------------------------------------------
159
+ // It's lonely here...
160
+
161
+ //----------------------------------------------------------------------------------
162
+ // Other Modules Functions Declaration (required by text)
163
+ //----------------------------------------------------------------------------------
164
+ // ...
165
+
166
+ //----------------------------------------------------------------------------------
167
+ // Module specific Functions Declaration
168
+ //----------------------------------------------------------------------------------
169
+ #if defined(SUPPORT_FILEFORMAT_DDS)
170
+ static Image LoadDDS(const unsigned char *fileData, unsigned int fileSize); // Load DDS file data
171
+ #endif
172
+ #if defined(SUPPORT_FILEFORMAT_PKM)
173
+ static Image LoadPKM(const unsigned char *fileData, unsigned int fileSize); // Load PKM file data
174
+ #endif
175
+ #if defined(SUPPORT_FILEFORMAT_KTX)
176
+ static Image LoadKTX(const unsigned char *fileData, unsigned int fileSize); // Load KTX file data
177
+ static int SaveKTX(Image image, const char *fileName); // Save image data as KTX file
178
+ #endif
179
+ #if defined(SUPPORT_FILEFORMAT_PVR)
180
+ static Image LoadPVR(const unsigned char *fileData, unsigned int fileSize); // Load PVR file data
181
+ #endif
182
+ #if defined(SUPPORT_FILEFORMAT_ASTC)
183
+ static Image LoadASTC(const unsigned char *fileData, unsigned int fileSize); // Load ASTC file data
184
+ #endif
185
+
186
+ static Vector4 *LoadImageDataNormalized(Image image); // Load pixel data from image as Vector4 array (float normalized)
187
+
188
+ //----------------------------------------------------------------------------------
189
+ // Module Functions Definition
190
+ //----------------------------------------------------------------------------------
191
+
192
+ // Load image from file into CPU memory (RAM)
193
+ Image LoadImage(const char *fileName)
194
+ {
195
+ Image image = { 0 };
196
+
197
+ #if defined(SUPPORT_FILEFORMAT_PNG) || \
198
+ defined(SUPPORT_FILEFORMAT_BMP) || \
199
+ defined(SUPPORT_FILEFORMAT_TGA) || \
200
+ defined(SUPPORT_FILEFORMAT_JPG) || \
201
+ defined(SUPPORT_FILEFORMAT_GIF) || \
202
+ defined(SUPPORT_FILEFORMAT_PIC) || \
203
+ defined(SUPPORT_FILEFORMAT_HDR) || \
204
+ defined(SUPPORT_FILEFORMAT_PSD)
205
+ #define STBI_REQUIRED
206
+ #endif
207
+
208
+ // Loading file to memory
209
+ unsigned int fileSize = 0;
210
+ unsigned char *fileData = LoadFileData(fileName, &fileSize);
211
+
212
+ // Loading image from memory data
213
+ if (fileData != NULL) image = LoadImageFromMemory(GetFileExtension(fileName), fileData, fileSize);
214
+
215
+ RL_FREE(fileData);
216
+
217
+ return image;
218
+ }
219
+
220
+ // Load an image from RAW file data
221
+ Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize)
222
+ {
223
+ Image image = { 0 };
224
+
225
+ unsigned int dataSize = 0;
226
+ unsigned char *fileData = LoadFileData(fileName, &dataSize);
227
+
228
+ if (fileData != NULL)
229
+ {
230
+ unsigned char *dataPtr = fileData;
231
+ unsigned int size = GetPixelDataSize(width, height, format);
232
+
233
+ if (headerSize > 0) dataPtr += headerSize;
234
+
235
+ image.data = RL_MALLOC(size); // Allocate required memory in bytes
236
+ memcpy(image.data, dataPtr, size); // Copy required data to image
237
+ image.width = width;
238
+ image.height = height;
239
+ image.mipmaps = 1;
240
+ image.format = format;
241
+
242
+ RL_FREE(fileData);
243
+ }
244
+
245
+ return image;
246
+ }
247
+
248
+ // Load animated image data
249
+ // - Image.data buffer includes all frames: [image#0][image#1][image#2][...]
250
+ // - Number of frames is returned through 'frames' parameter
251
+ // - All frames are returned in RGBA format
252
+ // - Frames delay data is discarded
253
+ Image LoadImageAnim(const char *fileName, int *frames)
254
+ {
255
+ Image image = { 0 };
256
+ int frameCount = 1;
257
+
258
+ #if defined(SUPPORT_FILEFORMAT_GIF)
259
+ if (IsFileExtension(fileName, ".gif"))
260
+ {
261
+ unsigned int dataSize = 0;
262
+ unsigned char *fileData = LoadFileData(fileName, &dataSize);
263
+
264
+ if (fileData != NULL)
265
+ {
266
+ int comp = 0;
267
+ int *delays = NULL;
268
+ image.data = stbi_load_gif_from_memory(fileData, dataSize, &delays, &image.width, &image.height, &frameCount, &comp, 4);
269
+
270
+ image.mipmaps = 1;
271
+ image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
272
+
273
+ RL_FREE(fileData);
274
+ RL_FREE(delays); // NOTE: Frames delays are discarded
275
+ }
276
+ }
277
+ #else
278
+ if (false) { }
279
+ #endif
280
+ else image = LoadImage(fileName);
281
+
282
+ // TODO: Support APNG animated images
283
+
284
+ *frames = frameCount;
285
+ return image;
286
+ }
287
+
288
+ // Load image from memory buffer, fileType refers to extension: i.e. ".png"
289
+ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)
290
+ {
291
+ Image image = { 0 };
292
+
293
+ char fileExtLower[16] = { 0 };
294
+ strcpy(fileExtLower, TextToLower(fileType));
295
+
296
+ #if defined(SUPPORT_FILEFORMAT_PNG)
297
+ if ((TextIsEqual(fileExtLower, ".png"))
298
+ #else
299
+ if ((false)
300
+ #endif
301
+ #if defined(SUPPORT_FILEFORMAT_BMP)
302
+ || (TextIsEqual(fileExtLower, ".bmp"))
303
+ #endif
304
+ #if defined(SUPPORT_FILEFORMAT_TGA)
305
+ || (TextIsEqual(fileExtLower, ".tga"))
306
+ #endif
307
+ #if defined(SUPPORT_FILEFORMAT_JPG)
308
+ || (TextIsEqual(fileExtLower, ".jpg") ||
309
+ TextIsEqual(fileExtLower, ".jpeg"))
310
+ #endif
311
+ #if defined(SUPPORT_FILEFORMAT_GIF)
312
+ || (TextIsEqual(fileExtLower, ".gif"))
313
+ #endif
314
+ #if defined(SUPPORT_FILEFORMAT_PIC)
315
+ || (TextIsEqual(fileExtLower, ".pic"))
316
+ #endif
317
+ #if defined(SUPPORT_FILEFORMAT_PSD)
318
+ || (TextIsEqual(fileExtLower, ".psd"))
319
+ #endif
320
+ )
321
+ {
322
+ #if defined(STBI_REQUIRED)
323
+ // NOTE: Using stb_image to load images (Supports multiple image formats)
324
+
325
+ if (fileData != NULL)
326
+ {
327
+ int comp = 0;
328
+ image.data = stbi_load_from_memory(fileData, dataSize, &image.width, &image.height, &comp, 0);
329
+
330
+ if (image.data != NULL)
331
+ {
332
+ image.mipmaps = 1;
333
+
334
+ if (comp == 1) image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
335
+ else if (comp == 2) image.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
336
+ else if (comp == 3) image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8;
337
+ else if (comp == 4) image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
338
+ }
339
+ }
340
+ #endif
341
+ }
342
+ #if defined(SUPPORT_FILEFORMAT_HDR)
343
+ else if (TextIsEqual(fileExtLower, ".hdr"))
344
+ {
345
+ #if defined(STBI_REQUIRED)
346
+ if (fileData != NULL)
347
+ {
348
+ int comp = 0;
349
+ image.data = stbi_loadf_from_memory(fileData, dataSize, &image.width, &image.height, &comp, 0);
350
+
351
+ image.mipmaps = 1;
352
+
353
+ if (comp == 1) image.format = PIXELFORMAT_UNCOMPRESSED_R32;
354
+ else if (comp == 3) image.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32;
355
+ else if (comp == 4) image.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32A32;
356
+ else
357
+ {
358
+ TRACELOG(LOG_WARNING, "IMAGE: HDR file format not supported");
359
+ UnloadImage(image);
360
+ }
361
+ }
362
+ #endif
363
+ }
364
+ #endif
365
+ #if defined(SUPPORT_FILEFORMAT_DDS)
366
+ else if (TextIsEqual(fileExtLower, ".dds")) image = LoadDDS(fileData, dataSize);
367
+ #endif
368
+ #if defined(SUPPORT_FILEFORMAT_PKM)
369
+ else if (TextIsEqual(fileExtLower, ".pkm")) image = LoadPKM(fileData, dataSize);
370
+ #endif
371
+ #if defined(SUPPORT_FILEFORMAT_KTX)
372
+ else if (TextIsEqual(fileExtLower, ".ktx")) image = LoadKTX(fileData, dataSize);
373
+ #endif
374
+ #if defined(SUPPORT_FILEFORMAT_PVR)
375
+ else if (TextIsEqual(fileExtLower, ".pvr")) image = LoadPVR(fileData, dataSize);
376
+ #endif
377
+ #if defined(SUPPORT_FILEFORMAT_ASTC)
378
+ else if (TextIsEqual(fileExtLower, ".astc")) image = LoadASTC(fileData, dataSize);
379
+ #endif
380
+ else TRACELOG(LOG_WARNING, "IMAGE: Data format not supported");
381
+
382
+ if (image.data != NULL) TRACELOG(LOG_INFO, "IMAGE: Data loaded successfully (%ix%i | %s | %i mipmaps)", image.width, image.height, rlGetPixelFormatName(image.format), image.mipmaps);
383
+ else TRACELOG(LOG_WARNING, "IMAGE: Failed to load image data");
384
+
385
+ return image;
386
+ }
387
+
388
+ // Load image from GPU texture data
389
+ // NOTE: Compressed texture formats not supported
390
+ Image LoadImageFromTexture(Texture2D texture)
391
+ {
392
+ Image image = { 0 };
393
+
394
+ if (texture.format < PIXELFORMAT_COMPRESSED_DXT1_RGB)
395
+ {
396
+ image.data = rlReadTexturePixels(texture.id, texture.width, texture.height, texture.format);
397
+
398
+ if (image.data != NULL)
399
+ {
400
+ image.width = texture.width;
401
+ image.height = texture.height;
402
+ image.format = texture.format;
403
+ image.mipmaps = 1;
404
+
405
+ #if defined(GRAPHICS_API_OPENGL_ES2)
406
+ // NOTE: Data retrieved on OpenGL ES 2.0 should be RGBA,
407
+ // coming from FBO color buffer attachment, but it seems
408
+ // original texture format is retrieved on RPI...
409
+ image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
410
+ #endif
411
+ TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Pixel data retrieved successfully", texture.id);
412
+ }
413
+ else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Failed to retrieve pixel data", texture.id);
414
+ }
415
+ else TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] Failed to retrieve compressed pixel data", texture.id);
416
+
417
+ return image;
418
+ }
419
+
420
+ // Load image from screen buffer and (screenshot)
421
+ Image LoadImageFromScreen(void)
422
+ {
423
+ Image image = { 0 };
424
+
425
+ image.width = GetScreenWidth();
426
+ image.height = GetScreenHeight();
427
+ image.mipmaps = 1;
428
+ image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
429
+ image.data = rlReadScreenPixels(image.width, image.height);
430
+
431
+ return image;
432
+ }
433
+
434
+ // Unload image from CPU memory (RAM)
435
+ void UnloadImage(Image image)
436
+ {
437
+ RL_FREE(image.data);
438
+ }
439
+
440
+ // Export image data to file
441
+ // NOTE: File format depends on fileName extension
442
+ bool ExportImage(Image image, const char *fileName)
443
+ {
444
+ int success = 0;
445
+
446
+ #if defined(SUPPORT_IMAGE_EXPORT)
447
+ int channels = 4;
448
+ bool allocatedData = false;
449
+ unsigned char *imgData = (unsigned char *)image.data;
450
+
451
+ if (image.format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) channels = 1;
452
+ else if (image.format == PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) channels = 2;
453
+ else if (image.format == PIXELFORMAT_UNCOMPRESSED_R8G8B8) channels = 3;
454
+ else if (image.format == PIXELFORMAT_UNCOMPRESSED_R8G8B8A8) channels = 4;
455
+ else
456
+ {
457
+ // NOTE: Getting Color array as RGBA unsigned char values
458
+ imgData = (unsigned char *)LoadImageColors(image);
459
+ allocatedData = true;
460
+ }
461
+
462
+ #if defined(SUPPORT_FILEFORMAT_PNG)
463
+ if (IsFileExtension(fileName, ".png"))
464
+ {
465
+ int dataSize = 0;
466
+ unsigned char *fileData = stbi_write_png_to_mem((const unsigned char *)imgData, image.width*channels, image.width, image.height, channels, &dataSize);
467
+ success = SaveFileData(fileName, fileData, dataSize);
468
+ RL_FREE(fileData);
469
+ }
470
+ #else
471
+ if (false) { }
472
+ #endif
473
+ #if defined(SUPPORT_FILEFORMAT_BMP)
474
+ else if (IsFileExtension(fileName, ".bmp")) success = stbi_write_bmp(fileName, image.width, image.height, channels, imgData);
475
+ #endif
476
+ #if defined(SUPPORT_FILEFORMAT_TGA)
477
+ else if (IsFileExtension(fileName, ".tga")) success = stbi_write_tga(fileName, image.width, image.height, channels, imgData);
478
+ #endif
479
+ #if defined(SUPPORT_FILEFORMAT_JPG)
480
+ else if (IsFileExtension(fileName, ".jpg")) success = stbi_write_jpg(fileName, image.width, image.height, channels, imgData, 90); // JPG quality: between 1 and 100
481
+ #endif
482
+ #if defined(SUPPORT_FILEFORMAT_KTX)
483
+ else if (IsFileExtension(fileName, ".ktx")) success = SaveKTX(image, fileName);
484
+ #endif
485
+ else if (IsFileExtension(fileName, ".raw"))
486
+ {
487
+ // Export raw pixel data (without header)
488
+ // NOTE: It's up to the user to track image parameters
489
+ success = SaveFileData(fileName, image.data, GetPixelDataSize(image.width, image.height, image.format));
490
+ }
491
+
492
+ if (allocatedData) RL_FREE(imgData);
493
+ #endif // SUPPORT_IMAGE_EXPORT
494
+
495
+ if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image exported successfully", fileName);
496
+ else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image", fileName);
497
+
498
+ return success;
499
+ }
500
+
501
+ // Export image as code file (.h) defining an array of bytes
502
+ bool ExportImageAsCode(Image image, const char *fileName)
503
+ {
504
+ bool success = false;
505
+
506
+ #if defined(SUPPORT_IMAGE_EXPORT)
507
+
508
+ #ifndef TEXT_BYTES_PER_LINE
509
+ #define TEXT_BYTES_PER_LINE 20
510
+ #endif
511
+
512
+ int dataSize = GetPixelDataSize(image.width, image.height, image.format);
513
+
514
+ // NOTE: Text data buffer size is estimated considering image data size in bytes
515
+ // and requiring 6 char bytes for every byte: "0x00, "
516
+ char *txtData = (char *)RL_CALLOC(dataSize*6 + 2000, sizeof(char));
517
+
518
+ int byteCount = 0;
519
+ byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
520
+ byteCount += sprintf(txtData + byteCount, "// //\n");
521
+ byteCount += sprintf(txtData + byteCount, "// ImageAsCode exporter v1.0 - Image pixel data exported as an array of bytes //\n");
522
+ byteCount += sprintf(txtData + byteCount, "// //\n");
523
+ byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
524
+ byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
525
+ byteCount += sprintf(txtData + byteCount, "// //\n");
526
+ byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2021 Ramon Santamaria (@raysan5) //\n");
527
+ byteCount += sprintf(txtData + byteCount, "// //\n");
528
+ byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
529
+
530
+ // Get file name from path and convert variable name to uppercase
531
+ char varFileName[256] = { 0 };
532
+ strcpy(varFileName, GetFileNameWithoutExt(fileName));
533
+ for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
534
+
535
+ // Add image information
536
+ byteCount += sprintf(txtData + byteCount, "// Image data information\n");
537
+ byteCount += sprintf(txtData + byteCount, "#define %s_WIDTH %i\n", varFileName, image.width);
538
+ byteCount += sprintf(txtData + byteCount, "#define %s_HEIGHT %i\n", varFileName, image.height);
539
+ byteCount += sprintf(txtData + byteCount, "#define %s_FORMAT %i // raylib internal pixel format\n\n", varFileName, image.format);
540
+
541
+ byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%i] = { ", varFileName, dataSize);
542
+ for (int i = 0; i < dataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)image.data)[i]);
543
+ byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]);
544
+
545
+ // NOTE: Text data size exported is determined by '\0' (NULL) character
546
+ success = SaveFileText(fileName, txtData);
547
+
548
+ RL_FREE(txtData);
549
+
550
+ #endif // SUPPORT_IMAGE_EXPORT
551
+
552
+ if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image exported successfully", fileName);
553
+ else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image", fileName);
554
+
555
+ return success;
556
+ }
557
+
558
+ //------------------------------------------------------------------------------------
559
+ // Image generation functions
560
+ //------------------------------------------------------------------------------------
561
+ // Generate image: plain color
562
+ Image GenImageColor(int width, int height, Color color)
563
+ {
564
+ Color *pixels = (Color *)RL_CALLOC(width*height, sizeof(Color));
565
+
566
+ for (int i = 0; i < width*height; i++) pixels[i] = color;
567
+
568
+ Image image = {
569
+ .data = pixels,
570
+ .width = width,
571
+ .height = height,
572
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
573
+ .mipmaps = 1
574
+ };
575
+
576
+ return image;
577
+ }
578
+
579
+ #if defined(SUPPORT_IMAGE_GENERATION)
580
+ // Generate image: vertical gradient
581
+ Image GenImageGradientV(int width, int height, Color top, Color bottom)
582
+ {
583
+ Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color));
584
+
585
+ for (int j = 0; j < height; j++)
586
+ {
587
+ float factor = (float)j/(float)height;
588
+ for (int i = 0; i < width; i++)
589
+ {
590
+ pixels[j*width + i].r = (int)((float)bottom.r*factor + (float)top.r*(1.f - factor));
591
+ pixels[j*width + i].g = (int)((float)bottom.g*factor + (float)top.g*(1.f - factor));
592
+ pixels[j*width + i].b = (int)((float)bottom.b*factor + (float)top.b*(1.f - factor));
593
+ pixels[j*width + i].a = (int)((float)bottom.a*factor + (float)top.a*(1.f - factor));
594
+ }
595
+ }
596
+
597
+ Image image = {
598
+ .data = pixels,
599
+ .width = width,
600
+ .height = height,
601
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
602
+ .mipmaps = 1
603
+ };
604
+
605
+ return image;
606
+ }
607
+
608
+ // Generate image: horizontal gradient
609
+ Image GenImageGradientH(int width, int height, Color left, Color right)
610
+ {
611
+ Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color));
612
+
613
+ for (int i = 0; i < width; i++)
614
+ {
615
+ float factor = (float)i/(float)width;
616
+ for (int j = 0; j < height; j++)
617
+ {
618
+ pixels[j*width + i].r = (int)((float)right.r*factor + (float)left.r*(1.f - factor));
619
+ pixels[j*width + i].g = (int)((float)right.g*factor + (float)left.g*(1.f - factor));
620
+ pixels[j*width + i].b = (int)((float)right.b*factor + (float)left.b*(1.f - factor));
621
+ pixels[j*width + i].a = (int)((float)right.a*factor + (float)left.a*(1.f - factor));
622
+ }
623
+ }
624
+
625
+ Image image = {
626
+ .data = pixels,
627
+ .width = width,
628
+ .height = height,
629
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
630
+ .mipmaps = 1
631
+ };
632
+
633
+ return image;
634
+ }
635
+
636
+ // Generate image: radial gradient
637
+ Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer)
638
+ {
639
+ Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color));
640
+ float radius = (width < height)? (float)width/2.0f : (float)height/2.0f;
641
+
642
+ float centerX = (float)width/2.0f;
643
+ float centerY = (float)height/2.0f;
644
+
645
+ for (int y = 0; y < height; y++)
646
+ {
647
+ for (int x = 0; x < width; x++)
648
+ {
649
+ float dist = hypotf((float)x - centerX, (float)y - centerY);
650
+ float factor = (dist - radius*density)/(radius*(1.0f - density));
651
+
652
+ factor = (float)fmax(factor, 0.0f);
653
+ factor = (float)fmin(factor, 1.f); // dist can be bigger than radius so we have to check
654
+
655
+ pixels[y*width + x].r = (int)((float)outer.r*factor + (float)inner.r*(1.0f - factor));
656
+ pixels[y*width + x].g = (int)((float)outer.g*factor + (float)inner.g*(1.0f - factor));
657
+ pixels[y*width + x].b = (int)((float)outer.b*factor + (float)inner.b*(1.0f - factor));
658
+ pixels[y*width + x].a = (int)((float)outer.a*factor + (float)inner.a*(1.0f - factor));
659
+ }
660
+ }
661
+
662
+ Image image = {
663
+ .data = pixels,
664
+ .width = width,
665
+ .height = height,
666
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
667
+ .mipmaps = 1
668
+ };
669
+
670
+ return image;
671
+ }
672
+
673
+ // Generate image: checked
674
+ Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2)
675
+ {
676
+ Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color));
677
+
678
+ for (int y = 0; y < height; y++)
679
+ {
680
+ for (int x = 0; x < width; x++)
681
+ {
682
+ if ((x/checksX + y/checksY)%2 == 0) pixels[y*width + x] = col1;
683
+ else pixels[y*width + x] = col2;
684
+ }
685
+ }
686
+
687
+ Image image = {
688
+ .data = pixels,
689
+ .width = width,
690
+ .height = height,
691
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
692
+ .mipmaps = 1
693
+ };
694
+
695
+ return image;
696
+ }
697
+
698
+ // Generate image: white noise
699
+ Image GenImageWhiteNoise(int width, int height, float factor)
700
+ {
701
+ Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color));
702
+
703
+ for (int i = 0; i < width*height; i++)
704
+ {
705
+ if (GetRandomValue(0, 99) < (int)(factor*100.0f)) pixels[i] = WHITE;
706
+ else pixels[i] = BLACK;
707
+ }
708
+
709
+ Image image = {
710
+ .data = pixels,
711
+ .width = width,
712
+ .height = height,
713
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
714
+ .mipmaps = 1
715
+ };
716
+
717
+ return image;
718
+ }
719
+
720
+ // Generate image: cellular algorithm. Bigger tileSize means bigger cells
721
+ Image GenImageCellular(int width, int height, int tileSize)
722
+ {
723
+ Color *pixels = (Color *)RL_MALLOC(width*height*sizeof(Color));
724
+
725
+ int seedsPerRow = width/tileSize;
726
+ int seedsPerCol = height/tileSize;
727
+ int seedCount = seedsPerRow*seedsPerCol;
728
+
729
+ Vector2 *seeds = (Vector2 *)RL_MALLOC(seedCount*sizeof(Vector2));
730
+
731
+ for (int i = 0; i < seedCount; i++)
732
+ {
733
+ int y = (i/seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1);
734
+ int x = (i%seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1);
735
+ seeds[i] = (Vector2){ (float)x, (float)y};
736
+ }
737
+
738
+ for (int y = 0; y < height; y++)
739
+ {
740
+ int tileY = y/tileSize;
741
+
742
+ for (int x = 0; x < width; x++)
743
+ {
744
+ int tileX = x/tileSize;
745
+
746
+ float minDistance = (float)strtod("Inf", NULL);
747
+
748
+ // Check all adjacent tiles
749
+ for (int i = -1; i < 2; i++)
750
+ {
751
+ if ((tileX + i < 0) || (tileX + i >= seedsPerRow)) continue;
752
+
753
+ for (int j = -1; j < 2; j++)
754
+ {
755
+ if ((tileY + j < 0) || (tileY + j >= seedsPerCol)) continue;
756
+
757
+ Vector2 neighborSeed = seeds[(tileY + j)*seedsPerRow + tileX + i];
758
+
759
+ float dist = (float)hypot(x - (int)neighborSeed.x, y - (int)neighborSeed.y);
760
+ minDistance = (float)fmin(minDistance, dist);
761
+ }
762
+ }
763
+
764
+ // I made this up but it seems to give good results at all tile sizes
765
+ int intensity = (int)(minDistance*256.0f/tileSize);
766
+ if (intensity > 255) intensity = 255;
767
+
768
+ pixels[y*width + x] = (Color){ intensity, intensity, intensity, 255 };
769
+ }
770
+ }
771
+
772
+ RL_FREE(seeds);
773
+
774
+ Image image = {
775
+ .data = pixels,
776
+ .width = width,
777
+ .height = height,
778
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
779
+ .mipmaps = 1
780
+ };
781
+
782
+ return image;
783
+ }
784
+ #endif // SUPPORT_IMAGE_GENERATION
785
+
786
+ //------------------------------------------------------------------------------------
787
+ // Image manipulation functions
788
+ //------------------------------------------------------------------------------------
789
+ // Copy an image to a new image
790
+ Image ImageCopy(Image image)
791
+ {
792
+ Image newImage = { 0 };
793
+
794
+ int width = image.width;
795
+ int height = image.height;
796
+ int size = 0;
797
+
798
+ for (int i = 0; i < image.mipmaps; i++)
799
+ {
800
+ size += GetPixelDataSize(width, height, image.format);
801
+
802
+ width /= 2;
803
+ height /= 2;
804
+
805
+ // Security check for NPOT textures
806
+ if (width < 1) width = 1;
807
+ if (height < 1) height = 1;
808
+ }
809
+
810
+ newImage.data = RL_MALLOC(size);
811
+
812
+ if (newImage.data != NULL)
813
+ {
814
+ // NOTE: Size must be provided in bytes
815
+ memcpy(newImage.data, image.data, size);
816
+
817
+ newImage.width = image.width;
818
+ newImage.height = image.height;
819
+ newImage.mipmaps = image.mipmaps;
820
+ newImage.format = image.format;
821
+ }
822
+
823
+ return newImage;
824
+ }
825
+
826
+ // Create an image from another image piece
827
+ Image ImageFromImage(Image image, Rectangle rec)
828
+ {
829
+ Image result = { 0 };
830
+
831
+ int bytesPerPixel = GetPixelDataSize(1, 1, image.format);
832
+
833
+ result.width = (int)rec.width;
834
+ result.height = (int)rec.height;
835
+ result.data = RL_CALLOC((int)(rec.width*rec.height)*bytesPerPixel, 1);
836
+ result.format = image.format;
837
+ result.mipmaps = 1;
838
+
839
+ for (int y = 0; y < rec.height; y++)
840
+ {
841
+ memcpy(((unsigned char *)result.data) + y*(int)rec.width*bytesPerPixel, ((unsigned char *)image.data) + ((y + (int)rec.y)*image.width + (int)rec.x)*bytesPerPixel, (int)rec.width*bytesPerPixel);
842
+ }
843
+
844
+ return result;
845
+ }
846
+
847
+ // Crop an image to area defined by a rectangle
848
+ // NOTE: Security checks are performed in case rectangle goes out of bounds
849
+ void ImageCrop(Image *image, Rectangle crop)
850
+ {
851
+ // Security check to avoid program crash
852
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
853
+
854
+ // Security checks to validate crop rectangle
855
+ if (crop.x < 0) { crop.width += crop.x; crop.x = 0; }
856
+ if (crop.y < 0) { crop.height += crop.y; crop.y = 0; }
857
+ if ((crop.x + crop.width) > image->width) crop.width = image->width - crop.x;
858
+ if ((crop.y + crop.height) > image->height) crop.height = image->height - crop.y;
859
+ if ((crop.x > image->width) || (crop.y > image->height))
860
+ {
861
+ TRACELOG(LOG_WARNING, "IMAGE: Failed to crop, rectangle out of bounds");
862
+ return;
863
+ }
864
+
865
+ if (image->mipmaps > 1) TRACELOG(LOG_WARNING, "Image manipulation only applied to base mipmap level");
866
+ if (image->format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "Image manipulation not supported for compressed formats");
867
+ else
868
+ {
869
+ int bytesPerPixel = GetPixelDataSize(1, 1, image->format);
870
+
871
+ unsigned char *croppedData = (unsigned char *)RL_MALLOC((int)(crop.width*crop.height)*bytesPerPixel);
872
+
873
+ // OPTION 1: Move cropped data line-by-line
874
+ for (int y = (int)crop.y, offsetSize = 0; y < (int)(crop.y + crop.height); y++)
875
+ {
876
+ memcpy(croppedData + offsetSize, ((unsigned char *)image->data) + (y*image->width + (int)crop.x)*bytesPerPixel, (int)crop.width*bytesPerPixel);
877
+ offsetSize += ((int)crop.width*bytesPerPixel);
878
+ }
879
+
880
+ /*
881
+ // OPTION 2: Move cropped data pixel-by-pixel or byte-by-byte
882
+ for (int y = (int)crop.y; y < (int)(crop.y + crop.height); y++)
883
+ {
884
+ for (int x = (int)crop.x; x < (int)(crop.x + crop.width); x++)
885
+ {
886
+ //memcpy(croppedData + ((y - (int)crop.y)*(int)crop.width + (x - (int)crop.x))*bytesPerPixel, ((unsigned char *)image->data) + (y*image->width + x)*bytesPerPixel, bytesPerPixel);
887
+ for (int i = 0; i < bytesPerPixel; i++) croppedData[((y - (int)crop.y)*(int)crop.width + (x - (int)crop.x))*bytesPerPixel + i] = ((unsigned char *)image->data)[(y*image->width + x)*bytesPerPixel + i];
888
+ }
889
+ }
890
+ */
891
+
892
+ RL_FREE(image->data);
893
+ image->data = croppedData;
894
+ image->width = (int)crop.width;
895
+ image->height = (int)crop.height;
896
+ }
897
+ }
898
+
899
+ // Convert image data to desired format
900
+ void ImageFormat(Image *image, int newFormat)
901
+ {
902
+ // Security check to avoid program crash
903
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
904
+
905
+ if ((newFormat != 0) && (image->format != newFormat))
906
+ {
907
+ if ((image->format < PIXELFORMAT_COMPRESSED_DXT1_RGB) && (newFormat < PIXELFORMAT_COMPRESSED_DXT1_RGB))
908
+ {
909
+ Vector4 *pixels = LoadImageDataNormalized(*image); // Supports 8 to 32 bit per channel
910
+
911
+ RL_FREE(image->data); // WARNING! We loose mipmaps data --> Regenerated at the end...
912
+ image->data = NULL;
913
+ image->format = newFormat;
914
+
915
+ int k = 0;
916
+
917
+ switch (image->format)
918
+ {
919
+ case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
920
+ {
921
+ image->data = (unsigned char *)RL_MALLOC(image->width*image->height*sizeof(unsigned char));
922
+
923
+ for (int i = 0; i < image->width*image->height; i++)
924
+ {
925
+ ((unsigned char *)image->data)[i] = (unsigned char)((pixels[i].x*0.299f + pixels[i].y*0.587f + pixels[i].z*0.114f)*255.0f);
926
+ }
927
+
928
+ } break;
929
+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
930
+ {
931
+ image->data = (unsigned char *)RL_MALLOC(image->width*image->height*2*sizeof(unsigned char));
932
+
933
+ for (int i = 0; i < image->width*image->height*2; i += 2, k++)
934
+ {
935
+ ((unsigned char *)image->data)[i] = (unsigned char)((pixels[k].x*0.299f + (float)pixels[k].y*0.587f + (float)pixels[k].z*0.114f)*255.0f);
936
+ ((unsigned char *)image->data)[i + 1] = (unsigned char)(pixels[k].w*255.0f);
937
+ }
938
+
939
+ } break;
940
+ case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
941
+ {
942
+ image->data = (unsigned short *)RL_MALLOC(image->width*image->height*sizeof(unsigned short));
943
+
944
+ unsigned char r = 0;
945
+ unsigned char g = 0;
946
+ unsigned char b = 0;
947
+
948
+ for (int i = 0; i < image->width*image->height; i++)
949
+ {
950
+ r = (unsigned char)(round(pixels[i].x*31.0f));
951
+ g = (unsigned char)(round(pixels[i].y*63.0f));
952
+ b = (unsigned char)(round(pixels[i].z*31.0f));
953
+
954
+ ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
955
+ }
956
+
957
+ } break;
958
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8:
959
+ {
960
+ image->data = (unsigned char *)RL_MALLOC(image->width*image->height*3*sizeof(unsigned char));
961
+
962
+ for (int i = 0, k = 0; i < image->width*image->height*3; i += 3, k++)
963
+ {
964
+ ((unsigned char *)image->data)[i] = (unsigned char)(pixels[k].x*255.0f);
965
+ ((unsigned char *)image->data)[i + 1] = (unsigned char)(pixels[k].y*255.0f);
966
+ ((unsigned char *)image->data)[i + 2] = (unsigned char)(pixels[k].z*255.0f);
967
+ }
968
+ } break;
969
+ case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
970
+ {
971
+ image->data = (unsigned short *)RL_MALLOC(image->width*image->height*sizeof(unsigned short));
972
+
973
+ unsigned char r = 0;
974
+ unsigned char g = 0;
975
+ unsigned char b = 0;
976
+ unsigned char a = 0;
977
+
978
+ for (int i = 0; i < image->width*image->height; i++)
979
+ {
980
+ r = (unsigned char)(round(pixels[i].x*31.0f));
981
+ g = (unsigned char)(round(pixels[i].y*31.0f));
982
+ b = (unsigned char)(round(pixels[i].z*31.0f));
983
+ a = (pixels[i].w > ((float)PIXELFORMAT_UNCOMPRESSED_R5G5B5A1_ALPHA_THRESHOLD/255.0f))? 1 : 0;
984
+
985
+ ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1 | (unsigned short)a;
986
+ }
987
+
988
+ } break;
989
+ case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
990
+ {
991
+ image->data = (unsigned short *)RL_MALLOC(image->width*image->height*sizeof(unsigned short));
992
+
993
+ unsigned char r = 0;
994
+ unsigned char g = 0;
995
+ unsigned char b = 0;
996
+ unsigned char a = 0;
997
+
998
+ for (int i = 0; i < image->width*image->height; i++)
999
+ {
1000
+ r = (unsigned char)(round(pixels[i].x*15.0f));
1001
+ g = (unsigned char)(round(pixels[i].y*15.0f));
1002
+ b = (unsigned char)(round(pixels[i].z*15.0f));
1003
+ a = (unsigned char)(round(pixels[i].w*15.0f));
1004
+
1005
+ ((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8 | (unsigned short)b << 4 | (unsigned short)a;
1006
+ }
1007
+
1008
+ } break;
1009
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
1010
+ {
1011
+ image->data = (unsigned char *)RL_MALLOC(image->width*image->height*4*sizeof(unsigned char));
1012
+
1013
+ for (int i = 0, k = 0; i < image->width*image->height*4; i += 4, k++)
1014
+ {
1015
+ ((unsigned char *)image->data)[i] = (unsigned char)(pixels[k].x*255.0f);
1016
+ ((unsigned char *)image->data)[i + 1] = (unsigned char)(pixels[k].y*255.0f);
1017
+ ((unsigned char *)image->data)[i + 2] = (unsigned char)(pixels[k].z*255.0f);
1018
+ ((unsigned char *)image->data)[i + 3] = (unsigned char)(pixels[k].w*255.0f);
1019
+ }
1020
+ } break;
1021
+ case PIXELFORMAT_UNCOMPRESSED_R32:
1022
+ {
1023
+ // WARNING: Image is converted to GRAYSCALE eqeuivalent 32bit
1024
+
1025
+ image->data = (float *)RL_MALLOC(image->width*image->height*sizeof(float));
1026
+
1027
+ for (int i = 0; i < image->width*image->height; i++)
1028
+ {
1029
+ ((float *)image->data)[i] = (float)(pixels[i].x*0.299f + pixels[i].y*0.587f + pixels[i].z*0.114f);
1030
+ }
1031
+ } break;
1032
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
1033
+ {
1034
+ image->data = (float *)RL_MALLOC(image->width*image->height*3*sizeof(float));
1035
+
1036
+ for (int i = 0, k = 0; i < image->width*image->height*3; i += 3, k++)
1037
+ {
1038
+ ((float *)image->data)[i] = pixels[k].x;
1039
+ ((float *)image->data)[i + 1] = pixels[k].y;
1040
+ ((float *)image->data)[i + 2] = pixels[k].z;
1041
+ }
1042
+ } break;
1043
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
1044
+ {
1045
+ image->data = (float *)RL_MALLOC(image->width*image->height*4*sizeof(float));
1046
+
1047
+ for (int i = 0, k = 0; i < image->width*image->height*4; i += 4, k++)
1048
+ {
1049
+ ((float *)image->data)[i] = pixels[k].x;
1050
+ ((float *)image->data)[i + 1] = pixels[k].y;
1051
+ ((float *)image->data)[i + 2] = pixels[k].z;
1052
+ ((float *)image->data)[i + 3] = pixels[k].w;
1053
+ }
1054
+ } break;
1055
+ default: break;
1056
+ }
1057
+
1058
+ RL_FREE(pixels);
1059
+ pixels = NULL;
1060
+
1061
+ // In case original image had mipmaps, generate mipmaps for formated image
1062
+ // NOTE: Original mipmaps are replaced by new ones, if custom mipmaps were used, they are lost
1063
+ if (image->mipmaps > 1)
1064
+ {
1065
+ image->mipmaps = 1;
1066
+ #if defined(SUPPORT_IMAGE_MANIPULATION)
1067
+ if (image->data != NULL) ImageMipmaps(image);
1068
+ #endif
1069
+ }
1070
+ }
1071
+ else TRACELOG(LOG_WARNING, "IMAGE: Data format is compressed, can not be converted");
1072
+ }
1073
+ }
1074
+
1075
+ // Convert image to POT (power-of-two)
1076
+ // NOTE: It could be useful on OpenGL ES 2.0 (RPI, HTML5)
1077
+ void ImageToPOT(Image *image, Color fill)
1078
+ {
1079
+ // Security check to avoid program crash
1080
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1081
+
1082
+ // Calculate next power-of-two values
1083
+ // NOTE: Just add the required amount of pixels at the right and bottom sides of image...
1084
+ int potWidth = (int)powf(2, ceilf(logf((float)image->width)/logf(2)));
1085
+ int potHeight = (int)powf(2, ceilf(logf((float)image->height)/logf(2)));
1086
+
1087
+ // Check if POT texture generation is required (if texture is not already POT)
1088
+ if ((potWidth != image->width) || (potHeight != image->height)) ImageResizeCanvas(image, potWidth, potHeight, 0, 0, fill);
1089
+ }
1090
+
1091
+ #if defined(SUPPORT_IMAGE_MANIPULATION)
1092
+ // Create an image from text (default font)
1093
+ Image ImageText(const char *text, int fontSize, Color color)
1094
+ {
1095
+ int defaultFontSize = 10; // Default Font chars height in pixel
1096
+ if (fontSize < defaultFontSize) fontSize = defaultFontSize;
1097
+ int spacing = fontSize/defaultFontSize;
1098
+
1099
+ Image imText = ImageTextEx(GetFontDefault(), text, (float)fontSize, (float)spacing, color);
1100
+
1101
+ return imText;
1102
+ }
1103
+
1104
+ // Create an image from text (custom sprite font)
1105
+ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint)
1106
+ {
1107
+ int size = (int)strlen(text); // Get size in bytes of text
1108
+
1109
+ int textOffsetX = 0; // Image drawing position X
1110
+ int textOffsetY = 0; // Offset between lines (on line break '\n')
1111
+
1112
+ // NOTE: Text image is generated at font base size, later scaled to desired font size
1113
+ Vector2 imSize = MeasureTextEx(font, text, (float)font.baseSize, spacing);
1114
+
1115
+ // Create image to store text
1116
+ Image imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
1117
+
1118
+ for (int i = 0; i < size; i++)
1119
+ {
1120
+ // Get next codepoint from byte string and glyph index in font
1121
+ int codepointByteCount = 0;
1122
+ int codepoint = GetCodepoint(&text[i], &codepointByteCount);
1123
+ int index = GetGlyphIndex(font, codepoint);
1124
+
1125
+ // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
1126
+ // but we need to draw all of the bad bytes using the '?' symbol moving one byte
1127
+ if (codepoint == 0x3f) codepointByteCount = 1;
1128
+
1129
+ if (codepoint == '\n')
1130
+ {
1131
+ // NOTE: Fixed line spacing of 1.5 line-height
1132
+ // TODO: Support custom line spacing defined by user
1133
+ textOffsetY += (font.baseSize + font.baseSize/2);
1134
+ textOffsetX = 0;
1135
+ }
1136
+ else
1137
+ {
1138
+ if ((codepoint != ' ') && (codepoint != '\t'))
1139
+ {
1140
+ Rectangle rec = { (float)(textOffsetX + font.glyphs[index].offsetX), (float)(textOffsetY + font.glyphs[index].offsetY), (float)font.recs[index].width, (float)font.recs[index].height };
1141
+ ImageDraw(&imText, font.glyphs[index].image, (Rectangle){ 0, 0, (float)font.glyphs[index].image.width, (float)font.glyphs[index].image.height }, rec, tint);
1142
+ }
1143
+
1144
+ if (font.glyphs[index].advanceX == 0) textOffsetX += (int)(font.recs[index].width + spacing);
1145
+ else textOffsetX += font.glyphs[index].advanceX + (int)spacing;
1146
+ }
1147
+
1148
+ i += (codepointByteCount - 1); // Move text bytes counter to next codepoint
1149
+ }
1150
+
1151
+ // Scale image depending on text size
1152
+ if (fontSize > imSize.y)
1153
+ {
1154
+ float scaleFactor = fontSize/imSize.y;
1155
+ TRACELOG(LOG_INFO, "IMAGE: Text scaled by factor: %f", scaleFactor);
1156
+
1157
+ // Using nearest-neighbor scaling algorithm for default font
1158
+ if (font.texture.id == GetFontDefault().texture.id) ImageResizeNN(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor));
1159
+ else ImageResize(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor));
1160
+ }
1161
+
1162
+ return imText;
1163
+ }
1164
+
1165
+ // Crop image depending on alpha value
1166
+ // NOTE: Threshold is defined as a percentatge: 0.0f -> 1.0f
1167
+ void ImageAlphaCrop(Image *image, float threshold)
1168
+ {
1169
+ // Security check to avoid program crash
1170
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1171
+
1172
+ Rectangle crop = GetImageAlphaBorder(*image, threshold);
1173
+
1174
+ // Crop if rectangle is valid
1175
+ if (((int)crop.width != 0) && ((int)crop.height != 0)) ImageCrop(image, crop);
1176
+ }
1177
+
1178
+ // Clear alpha channel to desired color
1179
+ // NOTE: Threshold defines the alpha limit, 0.0f to 1.0f
1180
+ void ImageAlphaClear(Image *image, Color color, float threshold)
1181
+ {
1182
+ // Security check to avoid program crash
1183
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1184
+
1185
+ if (image->mipmaps > 1) TRACELOG(LOG_WARNING, "Image manipulation only applied to base mipmap level");
1186
+ if (image->format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "Image manipulation not supported for compressed formats");
1187
+ else
1188
+ {
1189
+ switch (image->format)
1190
+ {
1191
+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
1192
+ {
1193
+ unsigned char thresholdValue = (unsigned char)(threshold*255.0f);
1194
+ for (int i = 1; i < image->width*image->height*2; i += 2)
1195
+ {
1196
+ if (((unsigned char *)image->data)[i] <= thresholdValue)
1197
+ {
1198
+ ((unsigned char *)image->data)[i - 1] = color.r;
1199
+ ((unsigned char *)image->data)[i] = color.a;
1200
+ }
1201
+ }
1202
+ } break;
1203
+ case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
1204
+ {
1205
+ unsigned char thresholdValue = ((threshold < 0.5f)? 0 : 1);
1206
+
1207
+ unsigned char r = (unsigned char)(round((float)color.r*31.0f));
1208
+ unsigned char g = (unsigned char)(round((float)color.g*31.0f));
1209
+ unsigned char b = (unsigned char)(round((float)color.b*31.0f));
1210
+ unsigned char a = (color.a < 128)? 0 : 1;
1211
+
1212
+ for (int i = 0; i < image->width*image->height; i++)
1213
+ {
1214
+ if ((((unsigned short *)image->data)[i] & 0b0000000000000001) <= thresholdValue)
1215
+ {
1216
+ ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1 | (unsigned short)a;
1217
+ }
1218
+ }
1219
+ } break;
1220
+ case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
1221
+ {
1222
+ unsigned char thresholdValue = (unsigned char)(threshold*15.0f);
1223
+
1224
+ unsigned char r = (unsigned char)(round((float)color.r*15.0f));
1225
+ unsigned char g = (unsigned char)(round((float)color.g*15.0f));
1226
+ unsigned char b = (unsigned char)(round((float)color.b*15.0f));
1227
+ unsigned char a = (unsigned char)(round((float)color.a*15.0f));
1228
+
1229
+ for (int i = 0; i < image->width*image->height; i++)
1230
+ {
1231
+ if ((((unsigned short *)image->data)[i] & 0x000f) <= thresholdValue)
1232
+ {
1233
+ ((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8 | (unsigned short)b << 4 | (unsigned short)a;
1234
+ }
1235
+ }
1236
+ } break;
1237
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
1238
+ {
1239
+ unsigned char thresholdValue = (unsigned char)(threshold*255.0f);
1240
+ for (int i = 3; i < image->width*image->height*4; i += 4)
1241
+ {
1242
+ if (((unsigned char *)image->data)[i] <= thresholdValue)
1243
+ {
1244
+ ((unsigned char *)image->data)[i - 3] = color.r;
1245
+ ((unsigned char *)image->data)[i - 2] = color.g;
1246
+ ((unsigned char *)image->data)[i - 1] = color.b;
1247
+ ((unsigned char *)image->data)[i] = color.a;
1248
+ }
1249
+ }
1250
+ } break;
1251
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
1252
+ {
1253
+ for (int i = 3; i < image->width*image->height*4; i += 4)
1254
+ {
1255
+ if (((float *)image->data)[i] <= threshold)
1256
+ {
1257
+ ((float *)image->data)[i - 3] = (float)color.r/255.0f;
1258
+ ((float *)image->data)[i - 2] = (float)color.g/255.0f;
1259
+ ((float *)image->data)[i - 1] = (float)color.b/255.0f;
1260
+ ((float *)image->data)[i] = (float)color.a/255.0f;
1261
+ }
1262
+ }
1263
+ } break;
1264
+ default: break;
1265
+ }
1266
+ }
1267
+ }
1268
+
1269
+ // Apply alpha mask to image
1270
+ // NOTE 1: Returned image is GRAY_ALPHA (16bit) or RGBA (32bit)
1271
+ // NOTE 2: alphaMask should be same size as image
1272
+ void ImageAlphaMask(Image *image, Image alphaMask)
1273
+ {
1274
+ if ((image->width != alphaMask.width) || (image->height != alphaMask.height))
1275
+ {
1276
+ TRACELOG(LOG_WARNING, "IMAGE: Alpha mask must be same size as image");
1277
+ }
1278
+ else if (image->format >= PIXELFORMAT_COMPRESSED_DXT1_RGB)
1279
+ {
1280
+ TRACELOG(LOG_WARNING, "IMAGE: Alpha mask can not be applied to compressed data formats");
1281
+ }
1282
+ else
1283
+ {
1284
+ // Force mask to be Grayscale
1285
+ Image mask = ImageCopy(alphaMask);
1286
+ if (mask.format != PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) ImageFormat(&mask, PIXELFORMAT_UNCOMPRESSED_GRAYSCALE);
1287
+
1288
+ // In case image is only grayscale, we just add alpha channel
1289
+ if (image->format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)
1290
+ {
1291
+ unsigned char *data = (unsigned char *)RL_MALLOC(image->width*image->height*2);
1292
+
1293
+ // Apply alpha mask to alpha channel
1294
+ for (int i = 0, k = 0; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 2)
1295
+ {
1296
+ data[k] = ((unsigned char *)image->data)[i];
1297
+ data[k + 1] = ((unsigned char *)mask.data)[i];
1298
+ }
1299
+
1300
+ RL_FREE(image->data);
1301
+ image->data = data;
1302
+ image->format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
1303
+ }
1304
+ else
1305
+ {
1306
+ // Convert image to RGBA
1307
+ if (image->format != PIXELFORMAT_UNCOMPRESSED_R8G8B8A8) ImageFormat(image, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8);
1308
+
1309
+ // Apply alpha mask to alpha channel
1310
+ for (int i = 0, k = 3; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 4)
1311
+ {
1312
+ ((unsigned char *)image->data)[k] = ((unsigned char *)mask.data)[i];
1313
+ }
1314
+ }
1315
+
1316
+ UnloadImage(mask);
1317
+ }
1318
+ }
1319
+
1320
+ // Premultiply alpha channel
1321
+ void ImageAlphaPremultiply(Image *image)
1322
+ {
1323
+ // Security check to avoid program crash
1324
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1325
+
1326
+ float alpha = 0.0f;
1327
+ Color *pixels = LoadImageColors(*image);
1328
+
1329
+ for (int i = 0; i < image->width*image->height; i++)
1330
+ {
1331
+ if (pixels[i].a == 0)
1332
+ {
1333
+ pixels[i].r = 0;
1334
+ pixels[i].g = 0;
1335
+ pixels[i].b = 0;
1336
+ }
1337
+ else if (pixels[i].a < 255)
1338
+ {
1339
+ alpha = (float)pixels[i].a/255.0f;
1340
+ pixels[i].r = (unsigned char)((float)pixels[i].r*alpha);
1341
+ pixels[i].g = (unsigned char)((float)pixels[i].g*alpha);
1342
+ pixels[i].b = (unsigned char)((float)pixels[i].b*alpha);
1343
+ }
1344
+ }
1345
+
1346
+ RL_FREE(image->data);
1347
+
1348
+ int format = image->format;
1349
+ image->data = pixels;
1350
+ image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
1351
+
1352
+ ImageFormat(image, format);
1353
+ }
1354
+
1355
+ // Resize and image to new size
1356
+ // NOTE: Uses stb default scaling filters (both bicubic):
1357
+ // STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM
1358
+ // STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL (high-quality Catmull-Rom)
1359
+ void ImageResize(Image *image, int newWidth, int newHeight)
1360
+ {
1361
+ // Security check to avoid program crash
1362
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1363
+
1364
+ bool fastPath = true;
1365
+ if ((image->format != PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) && (image->format != PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA) && (image->format != PIXELFORMAT_UNCOMPRESSED_R8G8B8) && (image->format != PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)) fastPath = true;
1366
+
1367
+ if (fastPath)
1368
+ {
1369
+ int bytesPerPixel = GetPixelDataSize(1, 1, image->format);
1370
+ unsigned char *output = (unsigned char *)RL_MALLOC(newWidth*newHeight*bytesPerPixel);
1371
+
1372
+ switch (image->format)
1373
+ {
1374
+ case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 1); break;
1375
+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 2); break;
1376
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 3); break;
1377
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: stbir_resize_uint8((unsigned char *)image->data, image->width, image->height, 0, output, newWidth, newHeight, 0, 4); break;
1378
+ default: break;
1379
+ }
1380
+
1381
+ RL_FREE(image->data);
1382
+ image->data = output;
1383
+ image->width = newWidth;
1384
+ image->height = newHeight;
1385
+ }
1386
+ else
1387
+ {
1388
+ // Get data as Color pixels array to work with it
1389
+ Color *pixels = LoadImageColors(*image);
1390
+ Color *output = (Color *)RL_MALLOC(newWidth*newHeight*sizeof(Color));
1391
+
1392
+ // NOTE: Color data is casted to (unsigned char *), there shouldn't been any problem...
1393
+ stbir_resize_uint8((unsigned char *)pixels, image->width, image->height, 0, (unsigned char *)output, newWidth, newHeight, 0, 4);
1394
+
1395
+ int format = image->format;
1396
+
1397
+ UnloadImageColors(pixels);
1398
+ RL_FREE(image->data);
1399
+
1400
+ image->data = output;
1401
+ image->width = newWidth;
1402
+ image->height = newHeight;
1403
+ image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
1404
+
1405
+ ImageFormat(image, format); // Reformat 32bit RGBA image to original format
1406
+ }
1407
+ }
1408
+
1409
+ // Resize and image to new size using Nearest-Neighbor scaling algorithm
1410
+ void ImageResizeNN(Image *image,int newWidth,int newHeight)
1411
+ {
1412
+ // Security check to avoid program crash
1413
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1414
+
1415
+ Color *pixels = LoadImageColors(*image);
1416
+ Color *output = (Color *)RL_MALLOC(newWidth*newHeight*sizeof(Color));
1417
+
1418
+ // EDIT: added +1 to account for an early rounding problem
1419
+ int xRatio = (int)((image->width << 16)/newWidth) + 1;
1420
+ int yRatio = (int)((image->height << 16)/newHeight) + 1;
1421
+
1422
+ int x2, y2;
1423
+ for (int y = 0; y < newHeight; y++)
1424
+ {
1425
+ for (int x = 0; x < newWidth; x++)
1426
+ {
1427
+ x2 = ((x*xRatio) >> 16);
1428
+ y2 = ((y*yRatio) >> 16);
1429
+
1430
+ output[(y*newWidth) + x] = pixels[(y2*image->width) + x2] ;
1431
+ }
1432
+ }
1433
+
1434
+ int format = image->format;
1435
+
1436
+ RL_FREE(image->data);
1437
+
1438
+ image->data = output;
1439
+ image->width = newWidth;
1440
+ image->height = newHeight;
1441
+ image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
1442
+
1443
+ ImageFormat(image, format); // Reformat 32bit RGBA image to original format
1444
+
1445
+ UnloadImageColors(pixels);
1446
+ }
1447
+
1448
+ // Resize canvas and fill with color
1449
+ // NOTE: Resize offset is relative to the top-left corner of the original image
1450
+ void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill)
1451
+ {
1452
+ // Security check to avoid program crash
1453
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1454
+
1455
+ if (image->mipmaps > 1) TRACELOG(LOG_WARNING, "Image manipulation only applied to base mipmap level");
1456
+ if (image->format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "Image manipulation not supported for compressed formats");
1457
+ else if ((newWidth != image->width) || (newHeight != image->height))
1458
+ {
1459
+ Rectangle srcRec = { 0, 0, (float)image->width, (float)image->height };
1460
+ Vector2 dstPos = { (float)offsetX, (float)offsetY };
1461
+
1462
+ if (offsetX < 0)
1463
+ {
1464
+ srcRec.x = (float)-offsetX;
1465
+ srcRec.width += (float)offsetX;
1466
+ dstPos.x = 0;
1467
+ }
1468
+ else if ((offsetX + image->width) > newWidth) srcRec.width = (float)(newWidth - offsetX);
1469
+
1470
+ if (offsetY < 0)
1471
+ {
1472
+ srcRec.y = (float)-offsetY;
1473
+ srcRec.height += (float)offsetY;
1474
+ dstPos.y = 0;
1475
+ }
1476
+ else if ((offsetY + image->height) > newHeight) srcRec.height = (float)(newHeight - offsetY);
1477
+
1478
+ if (newWidth < srcRec.width) srcRec.width = (float)newWidth;
1479
+ if (newHeight < srcRec.height) srcRec.height = (float)newHeight;
1480
+
1481
+ int bytesPerPixel = GetPixelDataSize(1, 1, image->format);
1482
+ unsigned char *resizedData = (unsigned char *)RL_CALLOC(newWidth*newHeight*bytesPerPixel, 1);
1483
+
1484
+ // TODO: Fill resized canvas with fill color (must be formatted to image->format)
1485
+
1486
+ int dstOffsetSize = ((int)dstPos.y*newWidth + (int)dstPos.x)*bytesPerPixel;
1487
+
1488
+ for (int y = 0; y < (int)srcRec.height; y++)
1489
+ {
1490
+ memcpy(resizedData + dstOffsetSize, ((unsigned char *)image->data) + ((y + (int)srcRec.y)*image->width + (int)srcRec.x)*bytesPerPixel, (int)srcRec.width*bytesPerPixel);
1491
+ dstOffsetSize += (newWidth*bytesPerPixel);
1492
+ }
1493
+
1494
+ RL_FREE(image->data);
1495
+ image->data = resizedData;
1496
+ image->width = newWidth;
1497
+ image->height = newHeight;
1498
+ }
1499
+ }
1500
+
1501
+ // Generate all mipmap levels for a provided image
1502
+ // NOTE 1: Supports POT and NPOT images
1503
+ // NOTE 2: image.data is scaled to include mipmap levels
1504
+ // NOTE 3: Mipmaps format is the same as base image
1505
+ void ImageMipmaps(Image *image)
1506
+ {
1507
+ // Security check to avoid program crash
1508
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1509
+
1510
+ int mipCount = 1; // Required mipmap levels count (including base level)
1511
+ int mipWidth = image->width; // Base image width
1512
+ int mipHeight = image->height; // Base image height
1513
+ int mipSize = GetPixelDataSize(mipWidth, mipHeight, image->format); // Image data size (in bytes)
1514
+
1515
+ // Count mipmap levels required
1516
+ while ((mipWidth != 1) || (mipHeight != 1))
1517
+ {
1518
+ if (mipWidth != 1) mipWidth /= 2;
1519
+ if (mipHeight != 1) mipHeight /= 2;
1520
+
1521
+ // Security check for NPOT textures
1522
+ if (mipWidth < 1) mipWidth = 1;
1523
+ if (mipHeight < 1) mipHeight = 1;
1524
+
1525
+ TRACELOGD("IMAGE: Next mipmap level: %i x %i - current size %i", mipWidth, mipHeight, mipSize);
1526
+
1527
+ mipCount++;
1528
+ mipSize += GetPixelDataSize(mipWidth, mipHeight, image->format); // Add mipmap size (in bytes)
1529
+ }
1530
+
1531
+ if (image->mipmaps < mipCount)
1532
+ {
1533
+ void *temp = RL_REALLOC(image->data, mipSize);
1534
+
1535
+ if (temp != NULL) image->data = temp; // Assign new pointer (new size) to store mipmaps data
1536
+ else TRACELOG(LOG_WARNING, "IMAGE: Mipmaps required memory could not be allocated");
1537
+
1538
+ // Pointer to allocated memory point where store next mipmap level data
1539
+ unsigned char *nextmip = (unsigned char *)image->data + GetPixelDataSize(image->width, image->height, image->format);
1540
+
1541
+ mipWidth = image->width/2;
1542
+ mipHeight = image->height/2;
1543
+ mipSize = GetPixelDataSize(mipWidth, mipHeight, image->format);
1544
+ Image imCopy = ImageCopy(*image);
1545
+
1546
+ for (int i = 1; i < mipCount; i++)
1547
+ {
1548
+ TRACELOGD("IMAGE: Generating mipmap level: %i (%i x %i) - size: %i - offset: 0x%x", i, mipWidth, mipHeight, mipSize, nextmip);
1549
+
1550
+ ImageResize(&imCopy, mipWidth, mipHeight); // Uses internally Mitchell cubic downscale filter
1551
+
1552
+ memcpy(nextmip, imCopy.data, mipSize);
1553
+ nextmip += mipSize;
1554
+ image->mipmaps++;
1555
+
1556
+ mipWidth /= 2;
1557
+ mipHeight /= 2;
1558
+
1559
+ // Security check for NPOT textures
1560
+ if (mipWidth < 1) mipWidth = 1;
1561
+ if (mipHeight < 1) mipHeight = 1;
1562
+
1563
+ mipSize = GetPixelDataSize(mipWidth, mipHeight, image->format);
1564
+ }
1565
+
1566
+ UnloadImage(imCopy);
1567
+ }
1568
+ else TRACELOG(LOG_WARNING, "IMAGE: Mipmaps already available");
1569
+ }
1570
+
1571
+ // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
1572
+ // NOTE: In case selected bpp do not represent an known 16bit format,
1573
+ // dithered data is stored in the LSB part of the unsigned short
1574
+ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp)
1575
+ {
1576
+ // Security check to avoid program crash
1577
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1578
+
1579
+ if (image->format >= PIXELFORMAT_COMPRESSED_DXT1_RGB)
1580
+ {
1581
+ TRACELOG(LOG_WARNING, "IMAGE: Compressed data formats can not be dithered");
1582
+ return;
1583
+ }
1584
+
1585
+ if ((rBpp + gBpp + bBpp + aBpp) > 16)
1586
+ {
1587
+ TRACELOG(LOG_WARNING, "IMAGE: Unsupported dithering bpps (%ibpp), only 16bpp or lower modes supported", (rBpp+gBpp+bBpp+aBpp));
1588
+ }
1589
+ else
1590
+ {
1591
+ Color *pixels = LoadImageColors(*image);
1592
+
1593
+ RL_FREE(image->data); // free old image data
1594
+
1595
+ if ((image->format != PIXELFORMAT_UNCOMPRESSED_R8G8B8) && (image->format != PIXELFORMAT_UNCOMPRESSED_R8G8B8A8))
1596
+ {
1597
+ TRACELOG(LOG_WARNING, "IMAGE: Format is already 16bpp or lower, dithering could have no effect");
1598
+ }
1599
+
1600
+ // Define new image format, check if desired bpp match internal known format
1601
+ if ((rBpp == 5) && (gBpp == 6) && (bBpp == 5) && (aBpp == 0)) image->format = PIXELFORMAT_UNCOMPRESSED_R5G6B5;
1602
+ else if ((rBpp == 5) && (gBpp == 5) && (bBpp == 5) && (aBpp == 1)) image->format = PIXELFORMAT_UNCOMPRESSED_R5G5B5A1;
1603
+ else if ((rBpp == 4) && (gBpp == 4) && (bBpp == 4) && (aBpp == 4)) image->format = PIXELFORMAT_UNCOMPRESSED_R4G4B4A4;
1604
+ else
1605
+ {
1606
+ image->format = 0;
1607
+ TRACELOG(LOG_WARNING, "IMAGE: Unsupported dithered OpenGL internal format: %ibpp (R%iG%iB%iA%i)", (rBpp+gBpp+bBpp+aBpp), rBpp, gBpp, bBpp, aBpp);
1608
+ }
1609
+
1610
+ // NOTE: We will store the dithered data as unsigned short (16bpp)
1611
+ image->data = (unsigned short *)RL_MALLOC(image->width*image->height*sizeof(unsigned short));
1612
+
1613
+ Color oldPixel = WHITE;
1614
+ Color newPixel = WHITE;
1615
+
1616
+ int rError, gError, bError;
1617
+ unsigned short rPixel, gPixel, bPixel, aPixel; // Used for 16bit pixel composition
1618
+
1619
+ #define MIN(a,b) (((a)<(b))?(a):(b))
1620
+
1621
+ for (int y = 0; y < image->height; y++)
1622
+ {
1623
+ for (int x = 0; x < image->width; x++)
1624
+ {
1625
+ oldPixel = pixels[y*image->width + x];
1626
+
1627
+ // NOTE: New pixel obtained by bits truncate, it would be better to round values (check ImageFormat())
1628
+ newPixel.r = oldPixel.r >> (8 - rBpp); // R bits
1629
+ newPixel.g = oldPixel.g >> (8 - gBpp); // G bits
1630
+ newPixel.b = oldPixel.b >> (8 - bBpp); // B bits
1631
+ newPixel.a = oldPixel.a >> (8 - aBpp); // A bits (not used on dithering)
1632
+
1633
+ // NOTE: Error must be computed between new and old pixel but using same number of bits!
1634
+ // We want to know how much color precision we have lost...
1635
+ rError = (int)oldPixel.r - (int)(newPixel.r << (8 - rBpp));
1636
+ gError = (int)oldPixel.g - (int)(newPixel.g << (8 - gBpp));
1637
+ bError = (int)oldPixel.b - (int)(newPixel.b << (8 - bBpp));
1638
+
1639
+ pixels[y*image->width + x] = newPixel;
1640
+
1641
+ // NOTE: Some cases are out of the array and should be ignored
1642
+ if (x < (image->width - 1))
1643
+ {
1644
+ pixels[y*image->width + x+1].r = MIN((int)pixels[y*image->width + x+1].r + (int)((float)rError*7.0f/16), 0xff);
1645
+ pixels[y*image->width + x+1].g = MIN((int)pixels[y*image->width + x+1].g + (int)((float)gError*7.0f/16), 0xff);
1646
+ pixels[y*image->width + x+1].b = MIN((int)pixels[y*image->width + x+1].b + (int)((float)bError*7.0f/16), 0xff);
1647
+ }
1648
+
1649
+ if ((x > 0) && (y < (image->height - 1)))
1650
+ {
1651
+ pixels[(y+1)*image->width + x-1].r = MIN((int)pixels[(y+1)*image->width + x-1].r + (int)((float)rError*3.0f/16), 0xff);
1652
+ pixels[(y+1)*image->width + x-1].g = MIN((int)pixels[(y+1)*image->width + x-1].g + (int)((float)gError*3.0f/16), 0xff);
1653
+ pixels[(y+1)*image->width + x-1].b = MIN((int)pixels[(y+1)*image->width + x-1].b + (int)((float)bError*3.0f/16), 0xff);
1654
+ }
1655
+
1656
+ if (y < (image->height - 1))
1657
+ {
1658
+ pixels[(y+1)*image->width + x].r = MIN((int)pixels[(y+1)*image->width + x].r + (int)((float)rError*5.0f/16), 0xff);
1659
+ pixels[(y+1)*image->width + x].g = MIN((int)pixels[(y+1)*image->width + x].g + (int)((float)gError*5.0f/16), 0xff);
1660
+ pixels[(y+1)*image->width + x].b = MIN((int)pixels[(y+1)*image->width + x].b + (int)((float)bError*5.0f/16), 0xff);
1661
+ }
1662
+
1663
+ if ((x < (image->width - 1)) && (y < (image->height - 1)))
1664
+ {
1665
+ pixels[(y+1)*image->width + x+1].r = MIN((int)pixels[(y+1)*image->width + x+1].r + (int)((float)rError*1.0f/16), 0xff);
1666
+ pixels[(y+1)*image->width + x+1].g = MIN((int)pixels[(y+1)*image->width + x+1].g + (int)((float)gError*1.0f/16), 0xff);
1667
+ pixels[(y+1)*image->width + x+1].b = MIN((int)pixels[(y+1)*image->width + x+1].b + (int)((float)bError*1.0f/16), 0xff);
1668
+ }
1669
+
1670
+ rPixel = (unsigned short)newPixel.r;
1671
+ gPixel = (unsigned short)newPixel.g;
1672
+ bPixel = (unsigned short)newPixel.b;
1673
+ aPixel = (unsigned short)newPixel.a;
1674
+
1675
+ ((unsigned short *)image->data)[y*image->width + x] = (rPixel << (gBpp + bBpp + aBpp)) | (gPixel << (bBpp + aBpp)) | (bPixel << aBpp) | aPixel;
1676
+ }
1677
+ }
1678
+
1679
+ UnloadImageColors(pixels);
1680
+ }
1681
+ }
1682
+
1683
+ // Flip image vertically
1684
+ void ImageFlipVertical(Image *image)
1685
+ {
1686
+ // Security check to avoid program crash
1687
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1688
+
1689
+ if (image->mipmaps > 1) TRACELOG(LOG_WARNING, "Image manipulation only applied to base mipmap level");
1690
+ if (image->format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "Image manipulation not supported for compressed formats");
1691
+ else
1692
+ {
1693
+ int bytesPerPixel = GetPixelDataSize(1, 1, image->format);
1694
+ unsigned char *flippedData = (unsigned char *)RL_MALLOC(image->width*image->height*bytesPerPixel);
1695
+
1696
+ for (int i = (image->height - 1), offsetSize = 0; i >= 0; i--)
1697
+ {
1698
+ memcpy(flippedData + offsetSize, ((unsigned char *)image->data) + i*image->width*bytesPerPixel, image->width*bytesPerPixel);
1699
+ offsetSize += image->width*bytesPerPixel;
1700
+ }
1701
+
1702
+ RL_FREE(image->data);
1703
+ image->data = flippedData;
1704
+ }
1705
+ }
1706
+
1707
+ // Flip image horizontally
1708
+ void ImageFlipHorizontal(Image *image)
1709
+ {
1710
+ // Security check to avoid program crash
1711
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1712
+
1713
+ if (image->mipmaps > 1) TRACELOG(LOG_WARNING, "Image manipulation only applied to base mipmap level");
1714
+ if (image->format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "Image manipulation not supported for compressed formats");
1715
+ else
1716
+ {
1717
+ int bytesPerPixel = GetPixelDataSize(1, 1, image->format);
1718
+ unsigned char *flippedData = (unsigned char *)RL_MALLOC(image->width*image->height*bytesPerPixel);
1719
+
1720
+ for (int y = 0; y < image->height; y++)
1721
+ {
1722
+ for (int x = 0; x < image->width; x++)
1723
+ {
1724
+ // OPTION 1: Move pixels with memcopy()
1725
+ //memcpy(flippedData + (y*image->width + x)*bytesPerPixel, ((unsigned char *)image->data) + (y*image->width + (image->width - 1 - x))*bytesPerPixel, bytesPerPixel);
1726
+
1727
+ // OPTION 2: Just copy data pixel by pixel
1728
+ for (int i = 0; i < bytesPerPixel; i++) flippedData[(y*image->width + x)*bytesPerPixel + i] = ((unsigned char *)image->data)[(y*image->width + (image->width - 1 - x))*bytesPerPixel + i];
1729
+ }
1730
+ }
1731
+
1732
+ RL_FREE(image->data);
1733
+ image->data = flippedData;
1734
+
1735
+ /*
1736
+ // OPTION 3: Faster implementation (specific for 32bit pixels)
1737
+ // NOTE: It does not require additional allocations
1738
+ uint32_t *ptr = (uint32_t *)image->data;
1739
+ for (int y = 0; y < image->height; y++)
1740
+ {
1741
+ for (int x = 0; x < image->width/2; x++)
1742
+ {
1743
+ uint32_t backup = ptr[y*image->width + x];
1744
+ ptr[y*image->width + x] = ptr[y*image->width + (image->width - 1 - x)];
1745
+ ptr[y*image->width + (image->width - 1 - x)] = backup;
1746
+ }
1747
+ }
1748
+ */
1749
+ }
1750
+ }
1751
+
1752
+ // Rotate image clockwise 90deg
1753
+ void ImageRotateCW(Image *image)
1754
+ {
1755
+ // Security check to avoid program crash
1756
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1757
+
1758
+ if (image->mipmaps > 1) TRACELOG(LOG_WARNING, "Image manipulation only applied to base mipmap level");
1759
+ if (image->format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "Image manipulation not supported for compressed formats");
1760
+ else
1761
+ {
1762
+ int bytesPerPixel = GetPixelDataSize(1, 1, image->format);
1763
+ unsigned char *rotatedData = (unsigned char *)RL_MALLOC(image->width*image->height*bytesPerPixel);
1764
+
1765
+ for (int y = 0; y < image->height; y++)
1766
+ {
1767
+ for (int x = 0; x < image->width; x++)
1768
+ {
1769
+ //memcpy(rotatedData + (x*image->height + (image->height - y - 1))*bytesPerPixel, ((unsigned char *)image->data) + (y*image->width + x)*bytesPerPixel, bytesPerPixel);
1770
+ for (int i = 0; i < bytesPerPixel; i++) rotatedData[(x*image->height + (image->height - y - 1))*bytesPerPixel + i] = ((unsigned char *)image->data)[(y*image->width + x)*bytesPerPixel + i];
1771
+ }
1772
+ }
1773
+
1774
+ RL_FREE(image->data);
1775
+ image->data = rotatedData;
1776
+ int width = image->width;
1777
+ int height = image-> height;
1778
+
1779
+ image->width = height;
1780
+ image->height = width;
1781
+ }
1782
+ }
1783
+
1784
+ // Rotate image counter-clockwise 90deg
1785
+ void ImageRotateCCW(Image *image)
1786
+ {
1787
+ // Security check to avoid program crash
1788
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1789
+
1790
+ if (image->mipmaps > 1) TRACELOG(LOG_WARNING, "Image manipulation only applied to base mipmap level");
1791
+ if (image->format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "Image manipulation not supported for compressed formats");
1792
+ else
1793
+ {
1794
+ int bytesPerPixel = GetPixelDataSize(1, 1, image->format);
1795
+ unsigned char *rotatedData = (unsigned char *)RL_MALLOC(image->width*image->height*bytesPerPixel);
1796
+
1797
+ for (int y = 0; y < image->height; y++)
1798
+ {
1799
+ for (int x = 0; x < image->width; x++)
1800
+ {
1801
+ //memcpy(rotatedData + (x*image->height + y))*bytesPerPixel, ((unsigned char *)image->data) + (y*image->width + (image->width - x - 1))*bytesPerPixel, bytesPerPixel);
1802
+ for (int i = 0; i < bytesPerPixel; i++) rotatedData[(x*image->height + y)*bytesPerPixel + i] = ((unsigned char *)image->data)[(y*image->width + (image->width - x - 1))*bytesPerPixel + i];
1803
+ }
1804
+ }
1805
+
1806
+ RL_FREE(image->data);
1807
+ image->data = rotatedData;
1808
+ int width = image->width;
1809
+ int height = image-> height;
1810
+
1811
+ image->width = height;
1812
+ image->height = width;
1813
+ }
1814
+ }
1815
+
1816
+ // Modify image color: tint
1817
+ void ImageColorTint(Image *image, Color color)
1818
+ {
1819
+ // Security check to avoid program crash
1820
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1821
+
1822
+ Color *pixels = LoadImageColors(*image);
1823
+
1824
+ float cR = (float)color.r/255;
1825
+ float cG = (float)color.g/255;
1826
+ float cB = (float)color.b/255;
1827
+ float cA = (float)color.a/255;
1828
+
1829
+ for (int y = 0; y < image->height; y++)
1830
+ {
1831
+ for (int x = 0; x < image->width; x++)
1832
+ {
1833
+ int index = y*image->width + x;
1834
+ unsigned char r = (unsigned char)(((float)pixels[index].r/255*cR)*255.0f);
1835
+ unsigned char g = (unsigned char)(((float)pixels[index].g/255*cG)*255.0f);
1836
+ unsigned char b = (unsigned char)(((float)pixels[index].b/255*cB)*255.0f);
1837
+ unsigned char a = (unsigned char)(((float)pixels[index].a/255*cA)*255.0f);
1838
+
1839
+ pixels[y*image->width + x].r = r;
1840
+ pixels[y*image->width + x].g = g;
1841
+ pixels[y*image->width + x].b = b;
1842
+ pixels[y*image->width + x].a = a;
1843
+ }
1844
+ }
1845
+
1846
+ int format = image->format;
1847
+ RL_FREE(image->data);
1848
+
1849
+ image->data = pixels;
1850
+ image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
1851
+
1852
+ ImageFormat(image, format);
1853
+ }
1854
+
1855
+ // Modify image color: invert
1856
+ void ImageColorInvert(Image *image)
1857
+ {
1858
+ // Security check to avoid program crash
1859
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1860
+
1861
+ Color *pixels = LoadImageColors(*image);
1862
+
1863
+ for (int y = 0; y < image->height; y++)
1864
+ {
1865
+ for (int x = 0; x < image->width; x++)
1866
+ {
1867
+ pixels[y*image->width + x].r = 255 - pixels[y*image->width + x].r;
1868
+ pixels[y*image->width + x].g = 255 - pixels[y*image->width + x].g;
1869
+ pixels[y*image->width + x].b = 255 - pixels[y*image->width + x].b;
1870
+ }
1871
+ }
1872
+
1873
+ int format = image->format;
1874
+ RL_FREE(image->data);
1875
+
1876
+ image->data = pixels;
1877
+ image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
1878
+
1879
+ ImageFormat(image, format);
1880
+ }
1881
+
1882
+ // Modify image color: grayscale
1883
+ void ImageColorGrayscale(Image *image)
1884
+ {
1885
+ ImageFormat(image, PIXELFORMAT_UNCOMPRESSED_GRAYSCALE);
1886
+ }
1887
+
1888
+ // Modify image color: contrast
1889
+ // NOTE: Contrast values between -100 and 100
1890
+ void ImageColorContrast(Image *image, float contrast)
1891
+ {
1892
+ // Security check to avoid program crash
1893
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1894
+
1895
+ if (contrast < -100) contrast = -100;
1896
+ if (contrast > 100) contrast = 100;
1897
+
1898
+ contrast = (100.0f + contrast)/100.0f;
1899
+ contrast *= contrast;
1900
+
1901
+ Color *pixels = LoadImageColors(*image);
1902
+
1903
+ for (int y = 0; y < image->height; y++)
1904
+ {
1905
+ for (int x = 0; x < image->width; x++)
1906
+ {
1907
+ float pR = (float)pixels[y*image->width + x].r/255.0f;
1908
+ pR -= 0.5;
1909
+ pR *= contrast;
1910
+ pR += 0.5;
1911
+ pR *= 255;
1912
+ if (pR < 0) pR = 0;
1913
+ if (pR > 255) pR = 255;
1914
+
1915
+ float pG = (float)pixels[y*image->width + x].g/255.0f;
1916
+ pG -= 0.5;
1917
+ pG *= contrast;
1918
+ pG += 0.5;
1919
+ pG *= 255;
1920
+ if (pG < 0) pG = 0;
1921
+ if (pG > 255) pG = 255;
1922
+
1923
+ float pB = (float)pixels[y*image->width + x].b/255.0f;
1924
+ pB -= 0.5;
1925
+ pB *= contrast;
1926
+ pB += 0.5;
1927
+ pB *= 255;
1928
+ if (pB < 0) pB = 0;
1929
+ if (pB > 255) pB = 255;
1930
+
1931
+ pixels[y*image->width + x].r = (unsigned char)pR;
1932
+ pixels[y*image->width + x].g = (unsigned char)pG;
1933
+ pixels[y*image->width + x].b = (unsigned char)pB;
1934
+ }
1935
+ }
1936
+
1937
+ int format = image->format;
1938
+ RL_FREE(image->data);
1939
+
1940
+ image->data = pixels;
1941
+ image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
1942
+
1943
+ ImageFormat(image, format);
1944
+ }
1945
+
1946
+ // Modify image color: brightness
1947
+ // NOTE: Brightness values between -255 and 255
1948
+ void ImageColorBrightness(Image *image, int brightness)
1949
+ {
1950
+ // Security check to avoid program crash
1951
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1952
+
1953
+ if (brightness < -255) brightness = -255;
1954
+ if (brightness > 255) brightness = 255;
1955
+
1956
+ Color *pixels = LoadImageColors(*image);
1957
+
1958
+ for (int y = 0; y < image->height; y++)
1959
+ {
1960
+ for (int x = 0; x < image->width; x++)
1961
+ {
1962
+ int cR = pixels[y*image->width + x].r + brightness;
1963
+ int cG = pixels[y*image->width + x].g + brightness;
1964
+ int cB = pixels[y*image->width + x].b + brightness;
1965
+
1966
+ if (cR < 0) cR = 1;
1967
+ if (cR > 255) cR = 255;
1968
+
1969
+ if (cG < 0) cG = 1;
1970
+ if (cG > 255) cG = 255;
1971
+
1972
+ if (cB < 0) cB = 1;
1973
+ if (cB > 255) cB = 255;
1974
+
1975
+ pixels[y*image->width + x].r = (unsigned char)cR;
1976
+ pixels[y*image->width + x].g = (unsigned char)cG;
1977
+ pixels[y*image->width + x].b = (unsigned char)cB;
1978
+ }
1979
+ }
1980
+
1981
+ int format = image->format;
1982
+ RL_FREE(image->data);
1983
+
1984
+ image->data = pixels;
1985
+ image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
1986
+
1987
+ ImageFormat(image, format);
1988
+ }
1989
+
1990
+ // Modify image color: replace color
1991
+ void ImageColorReplace(Image *image, Color color, Color replace)
1992
+ {
1993
+ // Security check to avoid program crash
1994
+ if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return;
1995
+
1996
+ Color *pixels = LoadImageColors(*image);
1997
+
1998
+ for (int y = 0; y < image->height; y++)
1999
+ {
2000
+ for (int x = 0; x < image->width; x++)
2001
+ {
2002
+ if ((pixels[y*image->width + x].r == color.r) &&
2003
+ (pixels[y*image->width + x].g == color.g) &&
2004
+ (pixels[y*image->width + x].b == color.b) &&
2005
+ (pixels[y*image->width + x].a == color.a))
2006
+ {
2007
+ pixels[y*image->width + x].r = replace.r;
2008
+ pixels[y*image->width + x].g = replace.g;
2009
+ pixels[y*image->width + x].b = replace.b;
2010
+ pixels[y*image->width + x].a = replace.a;
2011
+ }
2012
+ }
2013
+ }
2014
+
2015
+ int format = image->format;
2016
+ RL_FREE(image->data);
2017
+
2018
+ image->data = pixels;
2019
+ image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
2020
+
2021
+ ImageFormat(image, format);
2022
+ }
2023
+ #endif // SUPPORT_IMAGE_MANIPULATION
2024
+
2025
+ // Load color data from image as a Color array (RGBA - 32bit)
2026
+ // NOTE: Memory allocated should be freed using UnloadImageColors();
2027
+ Color *LoadImageColors(Image image)
2028
+ {
2029
+ if ((image.width == 0) || (image.height == 0)) return NULL;
2030
+
2031
+ Color *pixels = (Color *)RL_MALLOC(image.width*image.height*sizeof(Color));
2032
+
2033
+ if (image.format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "IMAGE: Pixel data retrieval not supported for compressed image formats");
2034
+ else
2035
+ {
2036
+ if ((image.format == PIXELFORMAT_UNCOMPRESSED_R32) ||
2037
+ (image.format == PIXELFORMAT_UNCOMPRESSED_R32G32B32) ||
2038
+ (image.format == PIXELFORMAT_UNCOMPRESSED_R32G32B32A32)) TRACELOG(LOG_WARNING, "IMAGE: Pixel format converted from 32bit to 8bit per channel");
2039
+
2040
+ for (int i = 0, k = 0; i < image.width*image.height; i++)
2041
+ {
2042
+ switch (image.format)
2043
+ {
2044
+ case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
2045
+ {
2046
+ pixels[i].r = ((unsigned char *)image.data)[i];
2047
+ pixels[i].g = ((unsigned char *)image.data)[i];
2048
+ pixels[i].b = ((unsigned char *)image.data)[i];
2049
+ pixels[i].a = 255;
2050
+
2051
+ } break;
2052
+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
2053
+ {
2054
+ pixels[i].r = ((unsigned char *)image.data)[k];
2055
+ pixels[i].g = ((unsigned char *)image.data)[k];
2056
+ pixels[i].b = ((unsigned char *)image.data)[k];
2057
+ pixels[i].a = ((unsigned char *)image.data)[k + 1];
2058
+
2059
+ k += 2;
2060
+ } break;
2061
+ case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
2062
+ {
2063
+ unsigned short pixel = ((unsigned short *)image.data)[i];
2064
+
2065
+ pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
2066
+ pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111000000) >> 6)*(255/31));
2067
+ pixels[i].b = (unsigned char)((float)((pixel & 0b0000000000111110) >> 1)*(255/31));
2068
+ pixels[i].a = (unsigned char)((pixel & 0b0000000000000001)*255);
2069
+
2070
+ } break;
2071
+ case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
2072
+ {
2073
+ unsigned short pixel = ((unsigned short *)image.data)[i];
2074
+
2075
+ pixels[i].r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
2076
+ pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111100000) >> 5)*(255/63));
2077
+ pixels[i].b = (unsigned char)((float)(pixel & 0b0000000000011111)*(255/31));
2078
+ pixels[i].a = 255;
2079
+
2080
+ } break;
2081
+ case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
2082
+ {
2083
+ unsigned short pixel = ((unsigned short *)image.data)[i];
2084
+
2085
+ pixels[i].r = (unsigned char)((float)((pixel & 0b1111000000000000) >> 12)*(255/15));
2086
+ pixels[i].g = (unsigned char)((float)((pixel & 0b0000111100000000) >> 8)*(255/15));
2087
+ pixels[i].b = (unsigned char)((float)((pixel & 0b0000000011110000) >> 4)*(255/15));
2088
+ pixels[i].a = (unsigned char)((float)(pixel & 0b0000000000001111)*(255/15));
2089
+
2090
+ } break;
2091
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
2092
+ {
2093
+ pixels[i].r = ((unsigned char *)image.data)[k];
2094
+ pixels[i].g = ((unsigned char *)image.data)[k + 1];
2095
+ pixels[i].b = ((unsigned char *)image.data)[k + 2];
2096
+ pixels[i].a = ((unsigned char *)image.data)[k + 3];
2097
+
2098
+ k += 4;
2099
+ } break;
2100
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8:
2101
+ {
2102
+ pixels[i].r = (unsigned char)((unsigned char *)image.data)[k];
2103
+ pixels[i].g = (unsigned char)((unsigned char *)image.data)[k + 1];
2104
+ pixels[i].b = (unsigned char)((unsigned char *)image.data)[k + 2];
2105
+ pixels[i].a = 255;
2106
+
2107
+ k += 3;
2108
+ } break;
2109
+ case PIXELFORMAT_UNCOMPRESSED_R32:
2110
+ {
2111
+ pixels[i].r = (unsigned char)(((float *)image.data)[k]*255.0f);
2112
+ pixels[i].g = 0;
2113
+ pixels[i].b = 0;
2114
+ pixels[i].a = 255;
2115
+
2116
+ } break;
2117
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
2118
+ {
2119
+ pixels[i].r = (unsigned char)(((float *)image.data)[k]*255.0f);
2120
+ pixels[i].g = (unsigned char)(((float *)image.data)[k + 1]*255.0f);
2121
+ pixels[i].b = (unsigned char)(((float *)image.data)[k + 2]*255.0f);
2122
+ pixels[i].a = 255;
2123
+
2124
+ k += 3;
2125
+ } break;
2126
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
2127
+ {
2128
+ pixels[i].r = (unsigned char)(((float *)image.data)[k]*255.0f);
2129
+ pixels[i].g = (unsigned char)(((float *)image.data)[k]*255.0f);
2130
+ pixels[i].b = (unsigned char)(((float *)image.data)[k]*255.0f);
2131
+ pixels[i].a = (unsigned char)(((float *)image.data)[k]*255.0f);
2132
+
2133
+ k += 4;
2134
+ } break;
2135
+ default: break;
2136
+ }
2137
+ }
2138
+ }
2139
+
2140
+ return pixels;
2141
+ }
2142
+
2143
+ // Load colors palette from image as a Color array (RGBA - 32bit)
2144
+ // NOTE: Memory allocated should be freed using UnloadImagePalette()
2145
+ Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorCount)
2146
+ {
2147
+ #define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
2148
+
2149
+ int palCount = 0;
2150
+ Color *palette = NULL;
2151
+ Color *pixels = LoadImageColors(image);
2152
+
2153
+ if (pixels != NULL)
2154
+ {
2155
+ palette = (Color *)RL_MALLOC(maxPaletteSize*sizeof(Color));
2156
+
2157
+ for (int i = 0; i < maxPaletteSize; i++) palette[i] = BLANK; // Set all colors to BLANK
2158
+
2159
+ for (int i = 0; i < image.width*image.height; i++)
2160
+ {
2161
+ if (pixels[i].a > 0)
2162
+ {
2163
+ bool colorInPalette = false;
2164
+
2165
+ // Check if the color is already on palette
2166
+ for (int j = 0; j < maxPaletteSize; j++)
2167
+ {
2168
+ if (COLOR_EQUAL(pixels[i], palette[j]))
2169
+ {
2170
+ colorInPalette = true;
2171
+ break;
2172
+ }
2173
+ }
2174
+
2175
+ // Store color if not on the palette
2176
+ if (!colorInPalette)
2177
+ {
2178
+ palette[palCount] = pixels[i]; // Add pixels[i] to palette
2179
+ palCount++;
2180
+
2181
+ // We reached the limit of colors supported by palette
2182
+ if (palCount >= maxPaletteSize)
2183
+ {
2184
+ i = image.width*image.height; // Finish palette get
2185
+ TRACELOG(LOG_WARNING, "IMAGE: Palette is greater than %i colors", maxPaletteSize);
2186
+ }
2187
+ }
2188
+ }
2189
+ }
2190
+
2191
+ UnloadImageColors(pixels);
2192
+ }
2193
+
2194
+ *colorCount = palCount;
2195
+
2196
+ return palette;
2197
+ }
2198
+
2199
+ // Unload color data loaded with LoadImageColors()
2200
+ void UnloadImageColors(Color *colors)
2201
+ {
2202
+ RL_FREE(colors);
2203
+ }
2204
+
2205
+ // Unload colors palette loaded with LoadImagePalette()
2206
+ void UnloadImagePalette(Color *colors)
2207
+ {
2208
+ RL_FREE(colors);
2209
+ }
2210
+
2211
+ // Get image alpha border rectangle
2212
+ // NOTE: Threshold is defined as a percentatge: 0.0f -> 1.0f
2213
+ Rectangle GetImageAlphaBorder(Image image, float threshold)
2214
+ {
2215
+ Rectangle crop = { 0 };
2216
+
2217
+ Color *pixels = LoadImageColors(image);
2218
+
2219
+ if (pixels != NULL)
2220
+ {
2221
+ int xMin = 65536; // Define a big enough number
2222
+ int xMax = 0;
2223
+ int yMin = 65536;
2224
+ int yMax = 0;
2225
+
2226
+ for (int y = 0; y < image.height; y++)
2227
+ {
2228
+ for (int x = 0; x < image.width; x++)
2229
+ {
2230
+ if (pixels[y*image.width + x].a > (unsigned char)(threshold*255.0f))
2231
+ {
2232
+ if (x < xMin) xMin = x;
2233
+ if (x > xMax) xMax = x;
2234
+ if (y < yMin) yMin = y;
2235
+ if (y > yMax) yMax = y;
2236
+ }
2237
+ }
2238
+ }
2239
+
2240
+ // Check for empty blank image
2241
+ if ((xMin != 65536) && (xMax != 65536))
2242
+ {
2243
+ crop = (Rectangle){ (float)xMin, (float)yMin, (float)((xMax + 1) - xMin), (float)((yMax + 1) - yMin) };
2244
+ }
2245
+
2246
+ UnloadImageColors(pixels);
2247
+ }
2248
+
2249
+ return crop;
2250
+ }
2251
+
2252
+ // Get image pixel color at (x, y) position
2253
+ Color GetImageColor(Image image, int x, int y)
2254
+ {
2255
+ Color color = { 0 };
2256
+
2257
+ if ((x >=0) && (x < image.width) && (y >= 0) && (y < image.height))
2258
+ {
2259
+ switch (image.format)
2260
+ {
2261
+ case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
2262
+ {
2263
+ color.r = ((unsigned char *)image.data)[y*image.width + x];
2264
+ color.g = ((unsigned char *)image.data)[y*image.width + x];
2265
+ color.b = ((unsigned char *)image.data)[y*image.width + x];
2266
+ color.a = 255;
2267
+
2268
+ } break;
2269
+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
2270
+ {
2271
+ color.r = ((unsigned char *)image.data)[(y*image.width + x)*2];
2272
+ color.g = ((unsigned char *)image.data)[(y*image.width + x)*2];
2273
+ color.b = ((unsigned char *)image.data)[(y*image.width + x)*2];
2274
+ color.a = ((unsigned char *)image.data)[(y*image.width + x)*2 + 1];
2275
+
2276
+ } break;
2277
+ case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
2278
+ {
2279
+ unsigned short pixel = ((unsigned short *)image.data)[y*image.width + x];
2280
+
2281
+ color.r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
2282
+ color.g = (unsigned char)((float)((pixel & 0b0000011111000000) >> 6)*(255/31));
2283
+ color.b = (unsigned char)((float)((pixel & 0b0000000000111110) >> 1)*(255/31));
2284
+ color.a = (unsigned char)((pixel & 0b0000000000000001)*255);
2285
+
2286
+ } break;
2287
+ case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
2288
+ {
2289
+ unsigned short pixel = ((unsigned short *)image.data)[y*image.width + x];
2290
+
2291
+ color.r = (unsigned char)((float)((pixel & 0b1111100000000000) >> 11)*(255/31));
2292
+ color.g = (unsigned char)((float)((pixel & 0b0000011111100000) >> 5)*(255/63));
2293
+ color.b = (unsigned char)((float)(pixel & 0b0000000000011111)*(255/31));
2294
+ color.a = 255;
2295
+
2296
+ } break;
2297
+ case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
2298
+ {
2299
+ unsigned short pixel = ((unsigned short *)image.data)[y*image.width + x];
2300
+
2301
+ color.r = (unsigned char)((float)((pixel & 0b1111000000000000) >> 12)*(255/15));
2302
+ color.g = (unsigned char)((float)((pixel & 0b0000111100000000) >> 8)*(255/15));
2303
+ color.b = (unsigned char)((float)((pixel & 0b0000000011110000) >> 4)*(255/15));
2304
+ color.a = (unsigned char)((float)(pixel & 0b0000000000001111)*(255/15));
2305
+
2306
+ } break;
2307
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
2308
+ {
2309
+ color.r = ((unsigned char *)image.data)[(y*image.width + x)*4];
2310
+ color.g = ((unsigned char *)image.data)[(y*image.width + x)*4 + 1];
2311
+ color.b = ((unsigned char *)image.data)[(y*image.width + x)*4 + 2];
2312
+ color.a = ((unsigned char *)image.data)[(y*image.width + x)*4 + 3];
2313
+
2314
+ } break;
2315
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8:
2316
+ {
2317
+ color.r = (unsigned char)((unsigned char *)image.data)[(y*image.width + x)*3];
2318
+ color.g = (unsigned char)((unsigned char *)image.data)[(y*image.width + x)*3 + 1];
2319
+ color.b = (unsigned char)((unsigned char *)image.data)[(y*image.width + x)*3 + 2];
2320
+ color.a = 255;
2321
+
2322
+ } break;
2323
+ case PIXELFORMAT_UNCOMPRESSED_R32:
2324
+ {
2325
+ color.r = (unsigned char)(((float *)image.data)[y*image.width + x]*255.0f);
2326
+ color.g = 0;
2327
+ color.b = 0;
2328
+ color.a = 255;
2329
+
2330
+ } break;
2331
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
2332
+ {
2333
+ color.r = (unsigned char)(((float *)image.data)[(y*image.width + x)*3]*255.0f);
2334
+ color.g = (unsigned char)(((float *)image.data)[(y*image.width + x)*3 + 1]*255.0f);
2335
+ color.b = (unsigned char)(((float *)image.data)[(y*image.width + x)*3 + 2]*255.0f);
2336
+ color.a = 255;
2337
+
2338
+ } break;
2339
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
2340
+ {
2341
+ color.r = (unsigned char)(((float *)image.data)[(y*image.width + x)*4]*255.0f);
2342
+ color.g = (unsigned char)(((float *)image.data)[(y*image.width + x)*4]*255.0f);
2343
+ color.b = (unsigned char)(((float *)image.data)[(y*image.width + x)*4]*255.0f);
2344
+ color.a = (unsigned char)(((float *)image.data)[(y*image.width + x)*4]*255.0f);
2345
+
2346
+ } break;
2347
+ default: TRACELOG(LOG_WARNING, "Compressed image format does not support color reading"); break;
2348
+ }
2349
+ }
2350
+ else TRACELOG(LOG_WARNING, "Requested image pixel (%i, %i) out of bounds", x, y);
2351
+
2352
+ return color;
2353
+ }
2354
+
2355
+ //------------------------------------------------------------------------------------
2356
+ // Image drawing functions
2357
+ //------------------------------------------------------------------------------------
2358
+ // Clear image background with given color
2359
+ void ImageClearBackground(Image *dst, Color color)
2360
+ {
2361
+ for (int i = 0; i < dst->width*dst->height; ++i) ImageDrawPixel(dst, i%dst->width, i/dst->width, color);
2362
+ }
2363
+
2364
+ // Draw pixel within an image
2365
+ // NOTE: Compressed image formats not supported
2366
+ void ImageDrawPixel(Image *dst, int x, int y, Color color)
2367
+ {
2368
+ // Security check to avoid program crash
2369
+ if ((dst->data == NULL) || (x < 0) || (x >= dst->width) || (y < 0) || (y >= dst->height)) return;
2370
+
2371
+ switch (dst->format)
2372
+ {
2373
+ case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
2374
+ {
2375
+ // NOTE: Calculate grayscale equivalent color
2376
+ Vector3 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
2377
+ unsigned char gray = (unsigned char)((coln.x*0.299f + coln.y*0.587f + coln.z*0.114f)*255.0f);
2378
+
2379
+ ((unsigned char *)dst->data)[y*dst->width + x] = gray;
2380
+
2381
+ } break;
2382
+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
2383
+ {
2384
+ // NOTE: Calculate grayscale equivalent color
2385
+ Vector3 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
2386
+ unsigned char gray = (unsigned char)((coln.x*0.299f + coln.y*0.587f + coln.z*0.114f)*255.0f);
2387
+
2388
+ ((unsigned char *)dst->data)[(y*dst->width + x)*2] = gray;
2389
+ ((unsigned char *)dst->data)[(y*dst->width + x)*2 + 1] = color.a;
2390
+
2391
+ } break;
2392
+ case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
2393
+ {
2394
+ // NOTE: Calculate R5G6B5 equivalent color
2395
+ Vector3 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
2396
+
2397
+ unsigned char r = (unsigned char)(round(coln.x*31.0f));
2398
+ unsigned char g = (unsigned char)(round(coln.y*63.0f));
2399
+ unsigned char b = (unsigned char)(round(coln.z*31.0f));
2400
+
2401
+ ((unsigned short *)dst->data)[y*dst->width + x] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
2402
+
2403
+ } break;
2404
+ case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
2405
+ {
2406
+ // NOTE: Calculate R5G5B5A1 equivalent color
2407
+ Vector4 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f, (float)color.a/255.0f };
2408
+
2409
+ unsigned char r = (unsigned char)(round(coln.x*31.0f));
2410
+ unsigned char g = (unsigned char)(round(coln.y*31.0f));
2411
+ unsigned char b = (unsigned char)(round(coln.z*31.0f));
2412
+ unsigned char a = (coln.w > ((float)PIXELFORMAT_UNCOMPRESSED_R5G5B5A1_ALPHA_THRESHOLD/255.0f))? 1 : 0;
2413
+
2414
+ ((unsigned short *)dst->data)[y*dst->width + x] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1 | (unsigned short)a;
2415
+
2416
+ } break;
2417
+ case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
2418
+ {
2419
+ // NOTE: Calculate R5G5B5A1 equivalent color
2420
+ Vector4 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f, (float)color.a/255.0f };
2421
+
2422
+ unsigned char r = (unsigned char)(round(coln.x*15.0f));
2423
+ unsigned char g = (unsigned char)(round(coln.y*15.0f));
2424
+ unsigned char b = (unsigned char)(round(coln.z*15.0f));
2425
+ unsigned char a = (unsigned char)(round(coln.w*15.0f));
2426
+
2427
+ ((unsigned short *)dst->data)[y*dst->width + x] = (unsigned short)r << 12 | (unsigned short)g << 8 | (unsigned short)b << 4 | (unsigned short)a;
2428
+
2429
+ } break;
2430
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8:
2431
+ {
2432
+ ((unsigned char *)dst->data)[(y*dst->width + x)*3] = color.r;
2433
+ ((unsigned char *)dst->data)[(y*dst->width + x)*3 + 1] = color.g;
2434
+ ((unsigned char *)dst->data)[(y*dst->width + x)*3 + 2] = color.b;
2435
+
2436
+ } break;
2437
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
2438
+ {
2439
+ ((unsigned char *)dst->data)[(y*dst->width + x)*4] = color.r;
2440
+ ((unsigned char *)dst->data)[(y*dst->width + x)*4 + 1] = color.g;
2441
+ ((unsigned char *)dst->data)[(y*dst->width + x)*4 + 2] = color.b;
2442
+ ((unsigned char *)dst->data)[(y*dst->width + x)*4 + 3] = color.a;
2443
+
2444
+ } break;
2445
+ case PIXELFORMAT_UNCOMPRESSED_R32:
2446
+ {
2447
+ // NOTE: Calculate grayscale equivalent color (normalized to 32bit)
2448
+ Vector3 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
2449
+
2450
+ ((float *)dst->data)[y*dst->width + x] = coln.x*0.299f + coln.y*0.587f + coln.z*0.114f;
2451
+
2452
+ } break;
2453
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
2454
+ {
2455
+ // NOTE: Calculate R32G32B32 equivalent color (normalized to 32bit)
2456
+ Vector3 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
2457
+
2458
+ ((float *)dst->data)[(y*dst->width + x)*3] = coln.x;
2459
+ ((float *)dst->data)[(y*dst->width + x)*3 + 1] = coln.y;
2460
+ ((float *)dst->data)[(y*dst->width + x)*3 + 2] = coln.z;
2461
+ } break;
2462
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
2463
+ {
2464
+ // NOTE: Calculate R32G32B32A32 equivalent color (normalized to 32bit)
2465
+ Vector4 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f, (float)color.a/255.0f };
2466
+
2467
+ ((float *)dst->data)[(y*dst->width + x)*4] = coln.x;
2468
+ ((float *)dst->data)[(y*dst->width + x)*4 + 1] = coln.y;
2469
+ ((float *)dst->data)[(y*dst->width + x)*4 + 2] = coln.z;
2470
+ ((float *)dst->data)[(y*dst->width + x)*4 + 3] = coln.w;
2471
+
2472
+ } break;
2473
+ default: break;
2474
+ }
2475
+ }
2476
+
2477
+ // Draw pixel within an image (Vector version)
2478
+ void ImageDrawPixelV(Image *dst, Vector2 position, Color color)
2479
+ {
2480
+ ImageDrawPixel(dst, (int)position.x, (int)position.y, color);
2481
+ }
2482
+
2483
+ // Draw line within an image
2484
+ void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color)
2485
+ {
2486
+ // Using Bresenham's algorithm as described in
2487
+ // Drawing Lines with Pixels - Joshua Scott - March 2012
2488
+ // https://classic.csunplugged.org/wp-content/uploads/2014/12/Lines.pdf
2489
+
2490
+ int changeInX = (endPosX - startPosX);
2491
+ int absChangeInX = (changeInX < 0)? -changeInX : changeInX;
2492
+ int changeInY = (endPosY - startPosY);
2493
+ int absChangeInY = (changeInY < 0)? -changeInY : changeInY;
2494
+
2495
+ int startU, startV, endU, stepV; // Substitutions, either U = X, V = Y or vice versa. See loop at end of function
2496
+ //int endV; // Not needed but left for better understanding, check code below
2497
+ int A, B, P; // See linked paper above, explained down in the main loop
2498
+ int reversedXY = (absChangeInY < absChangeInX);
2499
+
2500
+ if (reversedXY)
2501
+ {
2502
+ A = 2*absChangeInY;
2503
+ B = A - 2*absChangeInX;
2504
+ P = A - absChangeInX;
2505
+
2506
+ if (changeInX > 0)
2507
+ {
2508
+ startU = startPosX;
2509
+ startV = startPosY;
2510
+ endU = endPosX;
2511
+ //endV = endPosY;
2512
+ }
2513
+ else
2514
+ {
2515
+ startU = endPosX;
2516
+ startV = endPosY;
2517
+ endU = startPosX;
2518
+ //endV = startPosY;
2519
+
2520
+ // Since start and end are reversed
2521
+ changeInX = -changeInX;
2522
+ changeInY = -changeInY;
2523
+ }
2524
+
2525
+ stepV = (changeInY < 0)? -1 : 1;
2526
+
2527
+ ImageDrawPixel(dst, startU, startV, color); // At this point they are correctly ordered...
2528
+ }
2529
+ else
2530
+ {
2531
+ A = 2*absChangeInX;
2532
+ B = A - 2*absChangeInY;
2533
+ P = A - absChangeInY;
2534
+
2535
+ if (changeInY > 0)
2536
+ {
2537
+ startU = startPosY;
2538
+ startV = startPosX;
2539
+ endU = endPosY;
2540
+ //endV = endPosX;
2541
+ }
2542
+ else
2543
+ {
2544
+ startU = endPosY;
2545
+ startV = endPosX;
2546
+ endU = startPosY;
2547
+ //endV = startPosX;
2548
+
2549
+ // Since start and end are reversed
2550
+ changeInX = -changeInX;
2551
+ changeInY = -changeInY;
2552
+ }
2553
+
2554
+ stepV = (changeInX < 0)? -1 : 1;
2555
+
2556
+ ImageDrawPixel(dst, startV, startU, color); // ... but need to be reversed here. Repeated in the main loop below
2557
+ }
2558
+
2559
+ // We already drew the start point. If we started at startU + 0, the line would be crooked and too short
2560
+ for (int u = startU + 1, v = startV; u <= endU; u++)
2561
+ {
2562
+ if (P >= 0)
2563
+ {
2564
+ v += stepV; // Adjusts whenever we stray too far from the direct line. Details in the linked paper above
2565
+ P += B; // Remembers that we corrected our path
2566
+ }
2567
+ else P += A; // Remembers how far we are from the direct line
2568
+
2569
+ if (reversedXY) ImageDrawPixel(dst, u, v, color);
2570
+ else ImageDrawPixel(dst, v, u, color);
2571
+ }
2572
+ }
2573
+
2574
+ // Draw line within an image (Vector version)
2575
+ void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color)
2576
+ {
2577
+ ImageDrawLine(dst, (int)start.x, (int)start.y, (int)end.x, (int)end.y, color);
2578
+ }
2579
+
2580
+ // Draw circle within an image
2581
+ void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color)
2582
+ {
2583
+ int x = 0, y = radius;
2584
+ int decesionParameter = 3 - 2*radius;
2585
+
2586
+ while (y >= x)
2587
+ {
2588
+ ImageDrawPixel(dst, centerX + x, centerY + y, color);
2589
+ ImageDrawPixel(dst, centerX - x, centerY + y, color);
2590
+ ImageDrawPixel(dst, centerX + x, centerY - y, color);
2591
+ ImageDrawPixel(dst, centerX - x, centerY - y, color);
2592
+ ImageDrawPixel(dst, centerX + y, centerY + x, color);
2593
+ ImageDrawPixel(dst, centerX - y, centerY + x, color);
2594
+ ImageDrawPixel(dst, centerX + y, centerY - x, color);
2595
+ ImageDrawPixel(dst, centerX - y, centerY - x, color);
2596
+ x++;
2597
+
2598
+ if (decesionParameter > 0)
2599
+ {
2600
+ y--;
2601
+ decesionParameter = decesionParameter + 4*(x - y) + 10;
2602
+ }
2603
+ else decesionParameter = decesionParameter + 4*x + 6;
2604
+ }
2605
+ }
2606
+
2607
+ // Draw circle within an image (Vector version)
2608
+ void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color)
2609
+ {
2610
+ ImageDrawCircle(dst, (int)center.x, (int)center.y, radius, color);
2611
+ }
2612
+
2613
+ // Draw rectangle within an image
2614
+ void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color)
2615
+ {
2616
+ ImageDrawRectangleRec(dst, (Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color);
2617
+ }
2618
+
2619
+ // Draw rectangle within an image (Vector version)
2620
+ void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color)
2621
+ {
2622
+ ImageDrawRectangle(dst, (int)position.x, (int)position.y, (int)size.x, (int)size.y, color);
2623
+ }
2624
+
2625
+ // Draw rectangle within an image
2626
+ void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color)
2627
+ {
2628
+ // Security check to avoid program crash
2629
+ if ((dst->data == NULL) || (dst->width == 0) || (dst->height == 0)) return;
2630
+
2631
+ int sy = (int)rec.y;
2632
+ int ey = sy + (int)rec.height;
2633
+
2634
+ int sx = (int)rec.x;
2635
+ int ex = sx + (int)rec.width;
2636
+
2637
+ for (int y = sy; y < ey; y++)
2638
+ {
2639
+ for (int x = sx; x < ex; x++)
2640
+ {
2641
+ ImageDrawPixel(dst, x, y, color);
2642
+ }
2643
+ }
2644
+ }
2645
+
2646
+ // Draw rectangle lines within an image
2647
+ void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color)
2648
+ {
2649
+ ImageDrawRectangle(dst, (int)rec.x, (int)rec.y, (int)rec.width, thick, color);
2650
+ ImageDrawRectangle(dst, (int)rec.x, (int)(rec.y + thick), thick, (int)(rec.height - thick*2), color);
2651
+ ImageDrawRectangle(dst, (int)(rec.x + rec.width - thick), (int)(rec.y + thick), thick, (int)(rec.height - thick*2), color);
2652
+ ImageDrawRectangle(dst, (int)rec.x, (int)(rec.y + rec.height - thick), (int)rec.width, thick, color);
2653
+ }
2654
+
2655
+ // Draw an image (source) within an image (destination)
2656
+ // NOTE: Color tint is applied to source image
2657
+ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint)
2658
+ {
2659
+ // Security check to avoid program crash
2660
+ if ((dst->data == NULL) || (dst->width == 0) || (dst->height == 0) ||
2661
+ (src.data == NULL) || (src.width == 0) || (src.height == 0)) return;
2662
+
2663
+ if (dst->mipmaps > 1) TRACELOG(LOG_WARNING, "Image drawing only applied to base mipmap level");
2664
+ if (dst->format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "Image drawing not supported for compressed formats");
2665
+ else
2666
+ {
2667
+ Image srcMod = { 0 }; // Source copy (in case it was required)
2668
+ Image *srcPtr = &src; // Pointer to source image
2669
+ bool useSrcMod = false; // Track source copy required
2670
+
2671
+ // Source rectangle out-of-bounds security checks
2672
+ if (srcRec.x < 0) { srcRec.width += srcRec.x; srcRec.x = 0; }
2673
+ if (srcRec.y < 0) { srcRec.height += srcRec.y; srcRec.y = 0; }
2674
+ if ((srcRec.x + srcRec.width) > src.width) srcRec.width = src.width - srcRec.x;
2675
+ if ((srcRec.y + srcRec.height) > src.height) srcRec.height = src.height - srcRec.y;
2676
+
2677
+ // Check if source rectangle needs to be resized to destination rectangle
2678
+ // In that case, we make a copy of source and we apply all required transform
2679
+ if (((int)srcRec.width != (int)dstRec.width) || ((int)srcRec.height != (int)dstRec.height))
2680
+ {
2681
+ srcMod = ImageFromImage(src, srcRec); // Create image from another image
2682
+ ImageResize(&srcMod, (int)dstRec.width, (int)dstRec.height); // Resize to destination rectangle
2683
+ srcRec = (Rectangle){ 0, 0, (float)srcMod.width, (float)srcMod.height };
2684
+
2685
+ srcPtr = &srcMod;
2686
+ useSrcMod = true;
2687
+ }
2688
+
2689
+ // Destination rectangle out-of-bounds security checks
2690
+ if (dstRec.x < 0)
2691
+ {
2692
+ srcRec.x = -dstRec.x;
2693
+ srcRec.width += dstRec.x;
2694
+ dstRec.x = 0;
2695
+ }
2696
+ else if ((dstRec.x + srcRec.width) > dst->width) srcRec.width = dst->width - dstRec.x;
2697
+
2698
+ if (dstRec.y < 0)
2699
+ {
2700
+ srcRec.y = -dstRec.y;
2701
+ srcRec.height += dstRec.y;
2702
+ dstRec.y = 0;
2703
+ }
2704
+ else if ((dstRec.y + srcRec.height) > dst->height) srcRec.height = dst->height - dstRec.y;
2705
+
2706
+ if (dst->width < srcRec.width) srcRec.width = (float)dst->width;
2707
+ if (dst->height < srcRec.height) srcRec.height = (float)dst->height;
2708
+
2709
+ // This blitting method is quite fast! The process followed is:
2710
+ // for every pixel -> [get_src_format/get_dst_format -> blend -> format_to_dst]
2711
+ // Some optimization ideas:
2712
+ // [x] Avoid creating source copy if not required (no resize required)
2713
+ // [x] Optimize ImageResize() for pixel format (alternative: ImageResizeNN())
2714
+ // [x] Optimize ColorAlphaBlend() to avoid processing (alpha = 0) and (alpha = 1)
2715
+ // [x] Optimize ColorAlphaBlend() for faster operations (maybe avoiding divs?)
2716
+ // [x] Consider fast path: no alpha blending required cases (src has no alpha)
2717
+ // [x] Consider fast path: same src/dst format with no alpha -> direct line copy
2718
+ // [-] GetPixelColor(): Get Vector4 instead of Color, easier for ColorAlphaBlend()
2719
+
2720
+ Color colSrc, colDst, blend;
2721
+ bool blendRequired = true;
2722
+
2723
+ // Fast path: Avoid blend if source has no alpha to blend
2724
+ if ((tint.a == 255) && ((srcPtr->format == PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) || (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R8G8B8) || (srcPtr->format == PIXELFORMAT_UNCOMPRESSED_R5G6B5))) blendRequired = false;
2725
+
2726
+ int strideDst = GetPixelDataSize(dst->width, 1, dst->format);
2727
+ int bytesPerPixelDst = strideDst/(dst->width);
2728
+
2729
+ int strideSrc = GetPixelDataSize(srcPtr->width, 1, srcPtr->format);
2730
+ int bytesPerPixelSrc = strideSrc/(srcPtr->width);
2731
+
2732
+ unsigned char *pSrcBase = (unsigned char *)srcPtr->data + ((int)srcRec.y*srcPtr->width + (int)srcRec.x)*bytesPerPixelSrc;
2733
+ unsigned char *pDstBase = (unsigned char *)dst->data + ((int)dstRec.y*dst->width + (int)dstRec.x)*bytesPerPixelDst;
2734
+
2735
+ for (int y = 0; y < (int)srcRec.height; y++)
2736
+ {
2737
+ unsigned char *pSrc = pSrcBase;
2738
+ unsigned char *pDst = pDstBase;
2739
+
2740
+ // Fast path: Avoid moving pixel by pixel if no blend required and same format
2741
+ if (!blendRequired && (srcPtr->format == dst->format)) memcpy(pDst, pSrc, (int)(srcRec.width)*bytesPerPixelSrc);
2742
+ else
2743
+ {
2744
+ for (int x = 0; x < (int)srcRec.width; x++)
2745
+ {
2746
+ colSrc = GetPixelColor(pSrc, srcPtr->format);
2747
+ colDst = GetPixelColor(pDst, dst->format);
2748
+
2749
+ // Fast path: Avoid blend if source has no alpha to blend
2750
+ if (blendRequired) blend = ColorAlphaBlend(colDst, colSrc, tint);
2751
+ else blend = colSrc;
2752
+
2753
+ SetPixelColor(pDst, blend, dst->format);
2754
+
2755
+ pDst += bytesPerPixelDst;
2756
+ pSrc += bytesPerPixelSrc;
2757
+ }
2758
+ }
2759
+
2760
+ pSrcBase += strideSrc;
2761
+ pDstBase += strideDst;
2762
+ }
2763
+
2764
+ if (useSrcMod) UnloadImage(srcMod); // Unload source modified image
2765
+ }
2766
+ }
2767
+
2768
+ // Draw text (default font) within an image (destination)
2769
+ void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color)
2770
+ {
2771
+ Vector2 position = { (float)posX, (float)posY };
2772
+
2773
+ // NOTE: For default font, sapcing is set to desired font size / default font size (10)
2774
+ ImageDrawTextEx(dst, GetFontDefault(), text, position, (float)fontSize, (float)fontSize/10, color);
2775
+ }
2776
+
2777
+ // Draw text (custom sprite font) within an image (destination)
2778
+ void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint)
2779
+ {
2780
+ Image imText = ImageTextEx(font, text, fontSize, spacing, tint);
2781
+
2782
+ Rectangle srcRec = { 0.0f, 0.0f, (float)imText.width, (float)imText.height };
2783
+ Rectangle dstRec = { position.x, position.y, (float)imText.width, (float)imText.height };
2784
+
2785
+ ImageDraw(dst, imText, srcRec, dstRec, WHITE);
2786
+
2787
+ UnloadImage(imText);
2788
+ }
2789
+
2790
+ //------------------------------------------------------------------------------------
2791
+ // Texture loading functions
2792
+ //------------------------------------------------------------------------------------
2793
+ // Load texture from file into GPU memory (VRAM)
2794
+ Texture2D LoadTexture(const char *fileName)
2795
+ {
2796
+ Texture2D texture = { 0 };
2797
+
2798
+ Image image = LoadImage(fileName);
2799
+
2800
+ if (image.data != NULL)
2801
+ {
2802
+ texture = LoadTextureFromImage(image);
2803
+ UnloadImage(image);
2804
+ }
2805
+
2806
+ return texture;
2807
+ }
2808
+
2809
+ // Load a texture from image data
2810
+ // NOTE: image is not unloaded, it must be done manually
2811
+ Texture2D LoadTextureFromImage(Image image)
2812
+ {
2813
+ Texture2D texture = { 0 };
2814
+
2815
+ if ((image.data != NULL) && (image.width != 0) && (image.height != 0))
2816
+ {
2817
+ texture.id = rlLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps);
2818
+ }
2819
+ else TRACELOG(LOG_WARNING, "IMAGE: Data is not valid to load texture");
2820
+
2821
+ texture.width = image.width;
2822
+ texture.height = image.height;
2823
+ texture.mipmaps = image.mipmaps;
2824
+ texture.format = image.format;
2825
+
2826
+ return texture;
2827
+ }
2828
+
2829
+ // Load cubemap from image, multiple image cubemap layouts supported
2830
+ TextureCubemap LoadTextureCubemap(Image image, int layout)
2831
+ {
2832
+ TextureCubemap cubemap = { 0 };
2833
+
2834
+ if (layout == CUBEMAP_LAYOUT_AUTO_DETECT) // Try to automatically guess layout type
2835
+ {
2836
+ // Check image width/height to determine the type of cubemap provided
2837
+ if (image.width > image.height)
2838
+ {
2839
+ if ((image.width/6) == image.height) { layout = CUBEMAP_LAYOUT_LINE_HORIZONTAL; cubemap.width = image.width/6; }
2840
+ else if ((image.width/4) == (image.height/3)) { layout = CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE; cubemap.width = image.width/4; }
2841
+ else if (image.width >= (int)((float)image.height*1.85f)) { layout = CUBEMAP_LAYOUT_PANORAMA; cubemap.width = image.width/4; }
2842
+ }
2843
+ else if (image.height > image.width)
2844
+ {
2845
+ if ((image.height/6) == image.width) { layout = CUBEMAP_LAYOUT_LINE_VERTICAL; cubemap.width = image.height/6; }
2846
+ else if ((image.width/3) == (image.height/4)) { layout = CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR; cubemap.width = image.width/3; }
2847
+ }
2848
+
2849
+ cubemap.height = cubemap.width;
2850
+ }
2851
+
2852
+ if (layout != CUBEMAP_LAYOUT_AUTO_DETECT)
2853
+ {
2854
+ int size = cubemap.width;
2855
+
2856
+ Image faces = { 0 }; // Vertical column image
2857
+ Rectangle faceRecs[6] = { 0 }; // Face source rectangles
2858
+ for (int i = 0; i < 6; i++) faceRecs[i] = (Rectangle){ 0, 0, (float)size, (float)size };
2859
+
2860
+ if (layout == CUBEMAP_LAYOUT_LINE_VERTICAL)
2861
+ {
2862
+ faces = image;
2863
+ for (int i = 0; i < 6; i++) faceRecs[i].y = (float)size*i;
2864
+ }
2865
+ else if (layout == CUBEMAP_LAYOUT_PANORAMA)
2866
+ {
2867
+ // TODO: Convert panorama image to square faces...
2868
+ // Ref: https://github.com/denivip/panorama/blob/master/panorama.cpp
2869
+ }
2870
+ else
2871
+ {
2872
+ if (layout == CUBEMAP_LAYOUT_LINE_HORIZONTAL) for (int i = 0; i < 6; i++) faceRecs[i].x = (float)size*i;
2873
+ else if (layout == CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR)
2874
+ {
2875
+ faceRecs[0].x = (float)size; faceRecs[0].y = (float)size;
2876
+ faceRecs[1].x = (float)size; faceRecs[1].y = (float)size*3;
2877
+ faceRecs[2].x = (float)size; faceRecs[2].y = 0;
2878
+ faceRecs[3].x = (float)size; faceRecs[3].y = (float)size*2;
2879
+ faceRecs[4].x = 0; faceRecs[4].y = (float)size;
2880
+ faceRecs[5].x = (float)size*2; faceRecs[5].y = (float)size;
2881
+ }
2882
+ else if (layout == CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE)
2883
+ {
2884
+ faceRecs[0].x = (float)size*2; faceRecs[0].y = (float)size;
2885
+ faceRecs[1].x = 0; faceRecs[1].y = (float)size;
2886
+ faceRecs[2].x = (float)size; faceRecs[2].y = 0;
2887
+ faceRecs[3].x = (float)size; faceRecs[3].y = (float)size*2;
2888
+ faceRecs[4].x = (float)size; faceRecs[4].y = (float)size;
2889
+ faceRecs[5].x = (float)size*3; faceRecs[5].y = (float)size;
2890
+ }
2891
+
2892
+ // Convert image data to 6 faces in a vertical column, that's the optimum layout for loading
2893
+ faces = GenImageColor(size, size*6, MAGENTA);
2894
+ ImageFormat(&faces, image.format);
2895
+
2896
+ // NOTE: Image formating does not work with compressed textures
2897
+ }
2898
+
2899
+ for (int i = 0; i < 6; i++) ImageDraw(&faces, image, faceRecs[i], (Rectangle){ 0, (float)size*i, (float)size, (float)size }, WHITE);
2900
+
2901
+ cubemap.id = rlLoadTextureCubemap(faces.data, size, faces.format);
2902
+ if (cubemap.id == 0) TRACELOG(LOG_WARNING, "IMAGE: Failed to load cubemap image");
2903
+
2904
+ UnloadImage(faces);
2905
+ }
2906
+ else TRACELOG(LOG_WARNING, "IMAGE: Failed to detect cubemap image layout");
2907
+
2908
+ return cubemap;
2909
+ }
2910
+
2911
+ // Load texture for rendering (framebuffer)
2912
+ // NOTE: Render texture is loaded by default with RGBA color attachment and depth RenderBuffer
2913
+ RenderTexture2D LoadRenderTexture(int width, int height)
2914
+ {
2915
+ RenderTexture2D target = { 0 };
2916
+
2917
+ target.id = rlLoadFramebuffer(width, height); // Load an empty framebuffer
2918
+
2919
+ if (target.id > 0)
2920
+ {
2921
+ rlEnableFramebuffer(target.id);
2922
+
2923
+ // Create color texture (default to RGBA)
2924
+ target.texture.id = rlLoadTexture(NULL, width, height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
2925
+ target.texture.width = width;
2926
+ target.texture.height = height;
2927
+ target.texture.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
2928
+ target.texture.mipmaps = 1;
2929
+
2930
+ // Create depth renderbuffer/texture
2931
+ target.depth.id = rlLoadTextureDepth(width, height, true);
2932
+ target.depth.width = width;
2933
+ target.depth.height = height;
2934
+ target.depth.format = 19; //DEPTH_COMPONENT_24BIT?
2935
+ target.depth.mipmaps = 1;
2936
+
2937
+ // Attach color texture and depth renderbuffer/texture to FBO
2938
+ rlFramebufferAttach(target.id, target.texture.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0);
2939
+ rlFramebufferAttach(target.id, target.depth.id, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0);
2940
+
2941
+ // Check if fbo is complete with attachments (valid)
2942
+ if (rlFramebufferComplete(target.id)) TRACELOG(LOG_INFO, "FBO: [ID %i] Framebuffer object created successfully", target.id);
2943
+
2944
+ rlDisableFramebuffer();
2945
+ }
2946
+ else TRACELOG(LOG_WARNING, "FBO: Framebuffer object can not be created");
2947
+
2948
+ return target;
2949
+ }
2950
+
2951
+ // Unload texture from GPU memory (VRAM)
2952
+ void UnloadTexture(Texture2D texture)
2953
+ {
2954
+ if (texture.id > 0)
2955
+ {
2956
+ rlUnloadTexture(texture.id);
2957
+
2958
+ TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Unloaded texture data from VRAM (GPU)", texture.id);
2959
+ }
2960
+ }
2961
+
2962
+ // Unload render texture from GPU memory (VRAM)
2963
+ void UnloadRenderTexture(RenderTexture2D target)
2964
+ {
2965
+ if (target.id > 0)
2966
+ {
2967
+ // Color texture attached to FBO is deleted
2968
+ rlUnloadTexture(target.texture.id);
2969
+
2970
+ // NOTE: Depth texture/renderbuffer is automatically
2971
+ // queried and deleted before deleting framebuffer
2972
+ rlUnloadFramebuffer(target.id);
2973
+ }
2974
+ }
2975
+
2976
+ // Update GPU texture with new data
2977
+ // NOTE: pixels data must match texture.format
2978
+ void UpdateTexture(Texture2D texture, const void *pixels)
2979
+ {
2980
+ rlUpdateTexture(texture.id, 0, 0, texture.width, texture.height, texture.format, pixels);
2981
+ }
2982
+
2983
+ // Update GPU texture rectangle with new data
2984
+ // NOTE: pixels data must match texture.format
2985
+ void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels)
2986
+ {
2987
+ rlUpdateTexture(texture.id, (int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, texture.format, pixels);
2988
+ }
2989
+
2990
+ //------------------------------------------------------------------------------------
2991
+ // Texture configuration functions
2992
+ //------------------------------------------------------------------------------------
2993
+ // Generate GPU mipmaps for a texture
2994
+ void GenTextureMipmaps(Texture2D *texture)
2995
+ {
2996
+ // NOTE: NPOT textures support check inside function
2997
+ // On WebGL (OpenGL ES 2.0) NPOT textures support is limited
2998
+ rlGenTextureMipmaps(texture->id, texture->width, texture->height, texture->format, &texture->mipmaps);
2999
+ }
3000
+
3001
+ // Set texture scaling filter mode
3002
+ void SetTextureFilter(Texture2D texture, int filter)
3003
+ {
3004
+ switch (filter)
3005
+ {
3006
+ case TEXTURE_FILTER_POINT:
3007
+ {
3008
+ if (texture.mipmaps > 1)
3009
+ {
3010
+ // RL_TEXTURE_FILTER_MIP_NEAREST - tex filter: POINT, mipmaps filter: POINT (sharp switching between mipmaps)
3011
+ rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_MIP_NEAREST);
3012
+
3013
+ // RL_TEXTURE_FILTER_NEAREST - tex filter: POINT (no filter), no mipmaps
3014
+ rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_NEAREST);
3015
+ }
3016
+ else
3017
+ {
3018
+ // RL_TEXTURE_FILTER_NEAREST - tex filter: POINT (no filter), no mipmaps
3019
+ rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_NEAREST);
3020
+ rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_NEAREST);
3021
+ }
3022
+ } break;
3023
+ case TEXTURE_FILTER_BILINEAR:
3024
+ {
3025
+ if (texture.mipmaps > 1)
3026
+ {
3027
+ // RL_TEXTURE_FILTER_LINEAR_MIP_NEAREST - tex filter: BILINEAR, mipmaps filter: POINT (sharp switching between mipmaps)
3028
+ // Alternative: RL_TEXTURE_FILTER_NEAREST_MIP_LINEAR - tex filter: POINT, mipmaps filter: BILINEAR (smooth transition between mipmaps)
3029
+ rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_LINEAR_MIP_NEAREST);
3030
+
3031
+ // RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
3032
+ rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR);
3033
+ }
3034
+ else
3035
+ {
3036
+ // RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
3037
+ rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_LINEAR);
3038
+ rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR);
3039
+ }
3040
+ } break;
3041
+ case TEXTURE_FILTER_TRILINEAR:
3042
+ {
3043
+ if (texture.mipmaps > 1)
3044
+ {
3045
+ // RL_TEXTURE_FILTER_MIP_LINEAR - tex filter: BILINEAR, mipmaps filter: BILINEAR (smooth transition between mipmaps)
3046
+ rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_MIP_LINEAR);
3047
+
3048
+ // RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
3049
+ rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR);
3050
+ }
3051
+ else
3052
+ {
3053
+ TRACELOG(LOG_WARNING, "TEXTURE: [ID %i] No mipmaps available for TRILINEAR texture filtering", texture.id);
3054
+
3055
+ // RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps
3056
+ rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_LINEAR);
3057
+ rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR);
3058
+ }
3059
+ } break;
3060
+ case TEXTURE_FILTER_ANISOTROPIC_4X: rlTextureParameters(texture.id, RL_TEXTURE_FILTER_ANISOTROPIC, 4); break;
3061
+ case TEXTURE_FILTER_ANISOTROPIC_8X: rlTextureParameters(texture.id, RL_TEXTURE_FILTER_ANISOTROPIC, 8); break;
3062
+ case TEXTURE_FILTER_ANISOTROPIC_16X: rlTextureParameters(texture.id, RL_TEXTURE_FILTER_ANISOTROPIC, 16); break;
3063
+ default: break;
3064
+ }
3065
+ }
3066
+
3067
+ // Set texture wrapping mode
3068
+ void SetTextureWrap(Texture2D texture, int wrap)
3069
+ {
3070
+ switch (wrap)
3071
+ {
3072
+ case TEXTURE_WRAP_REPEAT:
3073
+ {
3074
+ rlTextureParameters(texture.id, RL_TEXTURE_WRAP_S, RL_TEXTURE_WRAP_REPEAT);
3075
+ rlTextureParameters(texture.id, RL_TEXTURE_WRAP_T, RL_TEXTURE_WRAP_REPEAT);
3076
+ } break;
3077
+ case TEXTURE_WRAP_CLAMP:
3078
+ {
3079
+ rlTextureParameters(texture.id, RL_TEXTURE_WRAP_S, RL_TEXTURE_WRAP_CLAMP);
3080
+ rlTextureParameters(texture.id, RL_TEXTURE_WRAP_T, RL_TEXTURE_WRAP_CLAMP);
3081
+ } break;
3082
+ case TEXTURE_WRAP_MIRROR_REPEAT:
3083
+ {
3084
+ rlTextureParameters(texture.id, RL_TEXTURE_WRAP_S, RL_TEXTURE_WRAP_MIRROR_REPEAT);
3085
+ rlTextureParameters(texture.id, RL_TEXTURE_WRAP_T, RL_TEXTURE_WRAP_MIRROR_REPEAT);
3086
+ } break;
3087
+ case TEXTURE_WRAP_MIRROR_CLAMP:
3088
+ {
3089
+ rlTextureParameters(texture.id, RL_TEXTURE_WRAP_S, RL_TEXTURE_WRAP_MIRROR_CLAMP);
3090
+ rlTextureParameters(texture.id, RL_TEXTURE_WRAP_T, RL_TEXTURE_WRAP_MIRROR_CLAMP);
3091
+ } break;
3092
+ default: break;
3093
+ }
3094
+ }
3095
+
3096
+ //------------------------------------------------------------------------------------
3097
+ // Texture drawing functions
3098
+ //------------------------------------------------------------------------------------
3099
+ // Draw a Texture2D
3100
+ void DrawTexture(Texture2D texture, int posX, int posY, Color tint)
3101
+ {
3102
+ DrawTextureEx(texture, (Vector2){ (float)posX, (float)posY }, 0.0f, 1.0f, tint);
3103
+ }
3104
+
3105
+ // Draw a Texture2D with position defined as Vector2
3106
+ void DrawTextureV(Texture2D texture, Vector2 position, Color tint)
3107
+ {
3108
+ DrawTextureEx(texture, position, 0, 1.0f, tint);
3109
+ }
3110
+
3111
+ // Draw a Texture2D with extended parameters
3112
+ void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint)
3113
+ {
3114
+ Rectangle source = { 0.0f, 0.0f, (float)texture.width, (float)texture.height };
3115
+ Rectangle dest = { position.x, position.y, (float)texture.width*scale, (float)texture.height*scale };
3116
+ Vector2 origin = { 0.0f, 0.0f };
3117
+
3118
+ DrawTexturePro(texture, source, dest, origin, rotation, tint);
3119
+ }
3120
+
3121
+ // Draw a part of a texture (defined by a rectangle)
3122
+ void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint)
3123
+ {
3124
+ Rectangle dest = { position.x, position.y, fabsf(source.width), fabsf(source.height) };
3125
+ Vector2 origin = { 0.0f, 0.0f };
3126
+
3127
+ DrawTexturePro(texture, source, dest, origin, 0.0f, tint);
3128
+ }
3129
+
3130
+ // Draw texture quad with tiling and offset parameters
3131
+ // NOTE: Tiling and offset should be provided considering normalized texture values [0..1]
3132
+ // i.e tiling = { 1.0f, 1.0f } refers to all texture, offset = { 0.5f, 0.5f } moves texture origin to center
3133
+ void DrawTextureQuad(Texture2D texture, Vector2 tiling, Vector2 offset, Rectangle quad, Color tint)
3134
+ {
3135
+ Rectangle source = { offset.x*texture.width, offset.y*texture.height, tiling.x*texture.width, tiling.y*texture.height };
3136
+ Vector2 origin = { 0.0f, 0.0f };
3137
+
3138
+ DrawTexturePro(texture, source, quad, origin, 0.0f, tint);
3139
+ }
3140
+
3141
+ // Draw part of a texture (defined by a rectangle) with rotation and scale tiled into dest.
3142
+ // NOTE: For tilling a whole texture DrawTextureQuad() is better
3143
+ void DrawTextureTiled(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint)
3144
+ {
3145
+ if ((texture.id <= 0) || (scale <= 0.0f)) return; // Wanna see a infinite loop?!...just delete this line!
3146
+
3147
+ int tileWidth = (int)(source.width*scale), tileHeight = (int)(source.height*scale);
3148
+ if ((dest.width < tileWidth) && (dest.height < tileHeight))
3149
+ {
3150
+ // Can fit only one tile
3151
+ DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)dest.width/tileWidth)*source.width, ((float)dest.height/tileHeight)*source.height},
3152
+ (Rectangle){dest.x, dest.y, dest.width, dest.height}, origin, rotation, tint);
3153
+ }
3154
+ else if (dest.width <= tileWidth)
3155
+ {
3156
+ // Tiled vertically (one column)
3157
+ int dy = 0;
3158
+ for (;dy+tileHeight < dest.height; dy += tileHeight)
3159
+ {
3160
+ DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)dest.width/tileWidth)*source.width, source.height}, (Rectangle){dest.x, dest.y + dy, dest.width, (float)tileHeight}, origin, rotation, tint);
3161
+ }
3162
+
3163
+ // Fit last tile
3164
+ if (dy < dest.height)
3165
+ {
3166
+ DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)dest.width/tileWidth)*source.width, ((float)(dest.height - dy)/tileHeight)*source.height},
3167
+ (Rectangle){dest.x, dest.y + dy, dest.width, dest.height - dy}, origin, rotation, tint);
3168
+ }
3169
+ }
3170
+ else if (dest.height <= tileHeight)
3171
+ {
3172
+ // Tiled horizontally (one row)
3173
+ int dx = 0;
3174
+ for (;dx+tileWidth < dest.width; dx += tileWidth)
3175
+ {
3176
+ DrawTexturePro(texture, (Rectangle){source.x, source.y, source.width, ((float)dest.height/tileHeight)*source.height}, (Rectangle){dest.x + dx, dest.y, (float)tileWidth, dest.height}, origin, rotation, tint);
3177
+ }
3178
+
3179
+ // Fit last tile
3180
+ if (dx < dest.width)
3181
+ {
3182
+ DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)(dest.width - dx)/tileWidth)*source.width, ((float)dest.height/tileHeight)*source.height},
3183
+ (Rectangle){dest.x + dx, dest.y, dest.width - dx, dest.height}, origin, rotation, tint);
3184
+ }
3185
+ }
3186
+ else
3187
+ {
3188
+ // Tiled both horizontally and vertically (rows and columns)
3189
+ int dx = 0;
3190
+ for (;dx+tileWidth < dest.width; dx += tileWidth)
3191
+ {
3192
+ int dy = 0;
3193
+ for (;dy+tileHeight < dest.height; dy += tileHeight)
3194
+ {
3195
+ DrawTexturePro(texture, source, (Rectangle){dest.x + dx, dest.y + dy, (float)tileWidth, (float)tileHeight}, origin, rotation, tint);
3196
+ }
3197
+
3198
+ if (dy < dest.height)
3199
+ {
3200
+ DrawTexturePro(texture, (Rectangle){source.x, source.y, source.width, ((float)(dest.height - dy)/tileHeight)*source.height},
3201
+ (Rectangle){dest.x + dx, dest.y + dy, (float)tileWidth, dest.height - dy}, origin, rotation, tint);
3202
+ }
3203
+ }
3204
+
3205
+ // Fit last column of tiles
3206
+ if (dx < dest.width)
3207
+ {
3208
+ int dy = 0;
3209
+ for (;dy+tileHeight < dest.height; dy += tileHeight)
3210
+ {
3211
+ DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)(dest.width - dx)/tileWidth)*source.width, source.height},
3212
+ (Rectangle){dest.x + dx, dest.y + dy, dest.width - dx, (float)tileHeight}, origin, rotation, tint);
3213
+ }
3214
+
3215
+ // Draw final tile in the bottom right corner
3216
+ if (dy < dest.height)
3217
+ {
3218
+ DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)(dest.width - dx)/tileWidth)*source.width, ((float)(dest.height - dy)/tileHeight)*source.height},
3219
+ (Rectangle){dest.x + dx, dest.y + dy, dest.width - dx, dest.height - dy}, origin, rotation, tint);
3220
+ }
3221
+ }
3222
+ }
3223
+ }
3224
+
3225
+ // Draw a part of a texture (defined by a rectangle) with 'pro' parameters
3226
+ // NOTE: origin is relative to destination rectangle size
3227
+ void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint)
3228
+ {
3229
+ // Check if texture is valid
3230
+ if (texture.id > 0)
3231
+ {
3232
+ float width = (float)texture.width;
3233
+ float height = (float)texture.height;
3234
+
3235
+ bool flipX = false;
3236
+
3237
+ if (source.width < 0) { flipX = true; source.width *= -1; }
3238
+ if (source.height < 0) source.y -= source.height;
3239
+
3240
+ Vector2 topLeft = { 0 };
3241
+ Vector2 topRight = { 0 };
3242
+ Vector2 bottomLeft = { 0 };
3243
+ Vector2 bottomRight = { 0 };
3244
+
3245
+ // Only calculate rotation if needed
3246
+ if (rotation == 0.0f)
3247
+ {
3248
+ float x = dest.x - origin.x;
3249
+ float y = dest.y - origin.y;
3250
+ topLeft = (Vector2){ x, y };
3251
+ topRight = (Vector2){ x + dest.width, y };
3252
+ bottomLeft = (Vector2){ x, y + dest.height };
3253
+ bottomRight = (Vector2){ x + dest.width, y + dest.height };
3254
+ }
3255
+ else
3256
+ {
3257
+ float sinRotation = sinf(rotation*DEG2RAD);
3258
+ float cosRotation = cosf(rotation*DEG2RAD);
3259
+ float x = dest.x;
3260
+ float y = dest.y;
3261
+ float dx = -origin.x;
3262
+ float dy = -origin.y;
3263
+
3264
+ topLeft.x = x + dx*cosRotation - dy*sinRotation;
3265
+ topLeft.y = y + dx*sinRotation + dy*cosRotation;
3266
+
3267
+ topRight.x = x + (dx + dest.width)*cosRotation - dy*sinRotation;
3268
+ topRight.y = y + (dx + dest.width)*sinRotation + dy*cosRotation;
3269
+
3270
+ bottomLeft.x = x + dx*cosRotation - (dy + dest.height)*sinRotation;
3271
+ bottomLeft.y = y + dx*sinRotation + (dy + dest.height)*cosRotation;
3272
+
3273
+ bottomRight.x = x + (dx + dest.width)*cosRotation - (dy + dest.height)*sinRotation;
3274
+ bottomRight.y = y + (dx + dest.width)*sinRotation + (dy + dest.height)*cosRotation;
3275
+ }
3276
+
3277
+ rlCheckRenderBatchLimit(4); // Make sure there is enough free space on the batch buffer
3278
+
3279
+ rlSetTexture(texture.id);
3280
+ rlBegin(RL_QUADS);
3281
+
3282
+ rlColor4ub(tint.r, tint.g, tint.b, tint.a);
3283
+ rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
3284
+
3285
+ // Top-left corner for texture and quad
3286
+ if (flipX) rlTexCoord2f((source.x + source.width)/width, source.y/height);
3287
+ else rlTexCoord2f(source.x/width, source.y/height);
3288
+ rlVertex2f(topLeft.x, topLeft.y);
3289
+
3290
+ // Bottom-left corner for texture and quad
3291
+ if (flipX) rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
3292
+ else rlTexCoord2f(source.x/width, (source.y + source.height)/height);
3293
+ rlVertex2f(bottomLeft.x, bottomLeft.y);
3294
+
3295
+ // Bottom-right corner for texture and quad
3296
+ if (flipX) rlTexCoord2f(source.x/width, (source.y + source.height)/height);
3297
+ else rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
3298
+ rlVertex2f(bottomRight.x, bottomRight.y);
3299
+
3300
+ // Top-right corner for texture and quad
3301
+ if (flipX) rlTexCoord2f(source.x/width, source.y/height);
3302
+ else rlTexCoord2f((source.x + source.width)/width, source.y/height);
3303
+ rlVertex2f(topRight.x, topRight.y);
3304
+
3305
+ rlEnd();
3306
+ rlSetTexture(0);
3307
+
3308
+ // NOTE: Vertex position can be transformed using matrices
3309
+ // but the process is way more costly than just calculating
3310
+ // the vertex positions manually, like done above.
3311
+ // I leave here the old implementation for educational pourposes,
3312
+ // just in case someone wants to do some performance test
3313
+ /*
3314
+ rlSetTexture(texture.id);
3315
+ rlPushMatrix();
3316
+ rlTranslatef(dest.x, dest.y, 0.0f);
3317
+ if (rotation != 0.0f) rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
3318
+ rlTranslatef(-origin.x, -origin.y, 0.0f);
3319
+
3320
+ rlBegin(RL_QUADS);
3321
+ rlColor4ub(tint.r, tint.g, tint.b, tint.a);
3322
+ rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
3323
+
3324
+ // Bottom-left corner for texture and quad
3325
+ if (flipX) rlTexCoord2f((source.x + source.width)/width, source.y/height);
3326
+ else rlTexCoord2f(source.x/width, source.y/height);
3327
+ rlVertex2f(0.0f, 0.0f);
3328
+
3329
+ // Bottom-right corner for texture and quad
3330
+ if (flipX) rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
3331
+ else rlTexCoord2f(source.x/width, (source.y + source.height)/height);
3332
+ rlVertex2f(0.0f, dest.height);
3333
+
3334
+ // Top-right corner for texture and quad
3335
+ if (flipX) rlTexCoord2f(source.x/width, (source.y + source.height)/height);
3336
+ else rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
3337
+ rlVertex2f(dest.width, dest.height);
3338
+
3339
+ // Top-left corner for texture and quad
3340
+ if (flipX) rlTexCoord2f(source.x/width, source.y/height);
3341
+ else rlTexCoord2f((source.x + source.width)/width, source.y/height);
3342
+ rlVertex2f(dest.width, 0.0f);
3343
+ rlEnd();
3344
+ rlPopMatrix();
3345
+ rlSetTexture(0);
3346
+ */
3347
+ }
3348
+ }
3349
+
3350
+ // Draws a texture (or part of it) that stretches or shrinks nicely using n-patch info
3351
+ void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint)
3352
+ {
3353
+ if (texture.id > 0)
3354
+ {
3355
+ float width = (float)texture.width;
3356
+ float height = (float)texture.height;
3357
+
3358
+ float patchWidth = ((int)dest.width <= 0)? 0.0f : dest.width;
3359
+ float patchHeight = ((int)dest.height <= 0)? 0.0f : dest.height;
3360
+
3361
+ if (nPatchInfo.source.width < 0) nPatchInfo.source.x -= nPatchInfo.source.width;
3362
+ if (nPatchInfo.source.height < 0) nPatchInfo.source.y -= nPatchInfo.source.height;
3363
+ if (nPatchInfo.layout == NPATCH_THREE_PATCH_HORIZONTAL) patchHeight = nPatchInfo.source.height;
3364
+ if (nPatchInfo.layout == NPATCH_THREE_PATCH_VERTICAL) patchWidth = nPatchInfo.source.width;
3365
+
3366
+ bool drawCenter = true;
3367
+ bool drawMiddle = true;
3368
+ float leftBorder = (float)nPatchInfo.left;
3369
+ float topBorder = (float)nPatchInfo.top;
3370
+ float rightBorder = (float)nPatchInfo.right;
3371
+ float bottomBorder = (float)nPatchInfo.bottom;
3372
+
3373
+ // Adjust the lateral (left and right) border widths in case patchWidth < texture.width
3374
+ if (patchWidth <= (leftBorder + rightBorder) && nPatchInfo.layout != NPATCH_THREE_PATCH_VERTICAL)
3375
+ {
3376
+ drawCenter = false;
3377
+ leftBorder = (leftBorder/(leftBorder + rightBorder))*patchWidth;
3378
+ rightBorder = patchWidth - leftBorder;
3379
+ }
3380
+
3381
+ // Adjust the lateral (top and bottom) border heights in case patchHeight < texture.height
3382
+ if (patchHeight <= (topBorder + bottomBorder) && nPatchInfo.layout != NPATCH_THREE_PATCH_HORIZONTAL)
3383
+ {
3384
+ drawMiddle = false;
3385
+ topBorder = (topBorder/(topBorder + bottomBorder))*patchHeight;
3386
+ bottomBorder = patchHeight - topBorder;
3387
+ }
3388
+
3389
+ Vector2 vertA, vertB, vertC, vertD;
3390
+ vertA.x = 0.0f; // outer left
3391
+ vertA.y = 0.0f; // outer top
3392
+ vertB.x = leftBorder; // inner left
3393
+ vertB.y = topBorder; // inner top
3394
+ vertC.x = patchWidth - rightBorder; // inner right
3395
+ vertC.y = patchHeight - bottomBorder; // inner bottom
3396
+ vertD.x = patchWidth; // outer right
3397
+ vertD.y = patchHeight; // outer bottom
3398
+
3399
+ Vector2 coordA, coordB, coordC, coordD;
3400
+ coordA.x = nPatchInfo.source.x/width;
3401
+ coordA.y = nPatchInfo.source.y/height;
3402
+ coordB.x = (nPatchInfo.source.x + leftBorder)/width;
3403
+ coordB.y = (nPatchInfo.source.y + topBorder)/height;
3404
+ coordC.x = (nPatchInfo.source.x + nPatchInfo.source.width - rightBorder)/width;
3405
+ coordC.y = (nPatchInfo.source.y + nPatchInfo.source.height - bottomBorder)/height;
3406
+ coordD.x = (nPatchInfo.source.x + nPatchInfo.source.width)/width;
3407
+ coordD.y = (nPatchInfo.source.y + nPatchInfo.source.height)/height;
3408
+
3409
+ rlSetTexture(texture.id);
3410
+
3411
+ rlPushMatrix();
3412
+ rlTranslatef(dest.x, dest.y, 0.0f);
3413
+ rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
3414
+ rlTranslatef(-origin.x, -origin.y, 0.0f);
3415
+
3416
+ rlBegin(RL_QUADS);
3417
+ rlColor4ub(tint.r, tint.g, tint.b, tint.a);
3418
+ rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
3419
+
3420
+ if (nPatchInfo.layout == NPATCH_NINE_PATCH)
3421
+ {
3422
+ // ------------------------------------------------------------
3423
+ // TOP-LEFT QUAD
3424
+ rlTexCoord2f(coordA.x, coordB.y); rlVertex2f(vertA.x, vertB.y); // Bottom-left corner for texture and quad
3425
+ rlTexCoord2f(coordB.x, coordB.y); rlVertex2f(vertB.x, vertB.y); // Bottom-right corner for texture and quad
3426
+ rlTexCoord2f(coordB.x, coordA.y); rlVertex2f(vertB.x, vertA.y); // Top-right corner for texture and quad
3427
+ rlTexCoord2f(coordA.x, coordA.y); rlVertex2f(vertA.x, vertA.y); // Top-left corner for texture and quad
3428
+ if (drawCenter)
3429
+ {
3430
+ // TOP-CENTER QUAD
3431
+ rlTexCoord2f(coordB.x, coordB.y); rlVertex2f(vertB.x, vertB.y); // Bottom-left corner for texture and quad
3432
+ rlTexCoord2f(coordC.x, coordB.y); rlVertex2f(vertC.x, vertB.y); // Bottom-right corner for texture and quad
3433
+ rlTexCoord2f(coordC.x, coordA.y); rlVertex2f(vertC.x, vertA.y); // Top-right corner for texture and quad
3434
+ rlTexCoord2f(coordB.x, coordA.y); rlVertex2f(vertB.x, vertA.y); // Top-left corner for texture and quad
3435
+ }
3436
+ // TOP-RIGHT QUAD
3437
+ rlTexCoord2f(coordC.x, coordB.y); rlVertex2f(vertC.x, vertB.y); // Bottom-left corner for texture and quad
3438
+ rlTexCoord2f(coordD.x, coordB.y); rlVertex2f(vertD.x, vertB.y); // Bottom-right corner for texture and quad
3439
+ rlTexCoord2f(coordD.x, coordA.y); rlVertex2f(vertD.x, vertA.y); // Top-right corner for texture and quad
3440
+ rlTexCoord2f(coordC.x, coordA.y); rlVertex2f(vertC.x, vertA.y); // Top-left corner for texture and quad
3441
+ if (drawMiddle)
3442
+ {
3443
+ // ------------------------------------------------------------
3444
+ // MIDDLE-LEFT QUAD
3445
+ rlTexCoord2f(coordA.x, coordC.y); rlVertex2f(vertA.x, vertC.y); // Bottom-left corner for texture and quad
3446
+ rlTexCoord2f(coordB.x, coordC.y); rlVertex2f(vertB.x, vertC.y); // Bottom-right corner for texture and quad
3447
+ rlTexCoord2f(coordB.x, coordB.y); rlVertex2f(vertB.x, vertB.y); // Top-right corner for texture and quad
3448
+ rlTexCoord2f(coordA.x, coordB.y); rlVertex2f(vertA.x, vertB.y); // Top-left corner for texture and quad
3449
+ if (drawCenter)
3450
+ {
3451
+ // MIDDLE-CENTER QUAD
3452
+ rlTexCoord2f(coordB.x, coordC.y); rlVertex2f(vertB.x, vertC.y); // Bottom-left corner for texture and quad
3453
+ rlTexCoord2f(coordC.x, coordC.y); rlVertex2f(vertC.x, vertC.y); // Bottom-right corner for texture and quad
3454
+ rlTexCoord2f(coordC.x, coordB.y); rlVertex2f(vertC.x, vertB.y); // Top-right corner for texture and quad
3455
+ rlTexCoord2f(coordB.x, coordB.y); rlVertex2f(vertB.x, vertB.y); // Top-left corner for texture and quad
3456
+ }
3457
+
3458
+ // MIDDLE-RIGHT QUAD
3459
+ rlTexCoord2f(coordC.x, coordC.y); rlVertex2f(vertC.x, vertC.y); // Bottom-left corner for texture and quad
3460
+ rlTexCoord2f(coordD.x, coordC.y); rlVertex2f(vertD.x, vertC.y); // Bottom-right corner for texture and quad
3461
+ rlTexCoord2f(coordD.x, coordB.y); rlVertex2f(vertD.x, vertB.y); // Top-right corner for texture and quad
3462
+ rlTexCoord2f(coordC.x, coordB.y); rlVertex2f(vertC.x, vertB.y); // Top-left corner for texture and quad
3463
+ }
3464
+
3465
+ // ------------------------------------------------------------
3466
+ // BOTTOM-LEFT QUAD
3467
+ rlTexCoord2f(coordA.x, coordD.y); rlVertex2f(vertA.x, vertD.y); // Bottom-left corner for texture and quad
3468
+ rlTexCoord2f(coordB.x, coordD.y); rlVertex2f(vertB.x, vertD.y); // Bottom-right corner for texture and quad
3469
+ rlTexCoord2f(coordB.x, coordC.y); rlVertex2f(vertB.x, vertC.y); // Top-right corner for texture and quad
3470
+ rlTexCoord2f(coordA.x, coordC.y); rlVertex2f(vertA.x, vertC.y); // Top-left corner for texture and quad
3471
+ if (drawCenter)
3472
+ {
3473
+ // BOTTOM-CENTER QUAD
3474
+ rlTexCoord2f(coordB.x, coordD.y); rlVertex2f(vertB.x, vertD.y); // Bottom-left corner for texture and quad
3475
+ rlTexCoord2f(coordC.x, coordD.y); rlVertex2f(vertC.x, vertD.y); // Bottom-right corner for texture and quad
3476
+ rlTexCoord2f(coordC.x, coordC.y); rlVertex2f(vertC.x, vertC.y); // Top-right corner for texture and quad
3477
+ rlTexCoord2f(coordB.x, coordC.y); rlVertex2f(vertB.x, vertC.y); // Top-left corner for texture and quad
3478
+ }
3479
+
3480
+ // BOTTOM-RIGHT QUAD
3481
+ rlTexCoord2f(coordC.x, coordD.y); rlVertex2f(vertC.x, vertD.y); // Bottom-left corner for texture and quad
3482
+ rlTexCoord2f(coordD.x, coordD.y); rlVertex2f(vertD.x, vertD.y); // Bottom-right corner for texture and quad
3483
+ rlTexCoord2f(coordD.x, coordC.y); rlVertex2f(vertD.x, vertC.y); // Top-right corner for texture and quad
3484
+ rlTexCoord2f(coordC.x, coordC.y); rlVertex2f(vertC.x, vertC.y); // Top-left corner for texture and quad
3485
+ }
3486
+ else if (nPatchInfo.layout == NPATCH_THREE_PATCH_VERTICAL)
3487
+ {
3488
+ // TOP QUAD
3489
+ // -----------------------------------------------------------
3490
+ // Texture coords Vertices
3491
+ rlTexCoord2f(coordA.x, coordB.y); rlVertex2f(vertA.x, vertB.y); // Bottom-left corner for texture and quad
3492
+ rlTexCoord2f(coordD.x, coordB.y); rlVertex2f(vertD.x, vertB.y); // Bottom-right corner for texture and quad
3493
+ rlTexCoord2f(coordD.x, coordA.y); rlVertex2f(vertD.x, vertA.y); // Top-right corner for texture and quad
3494
+ rlTexCoord2f(coordA.x, coordA.y); rlVertex2f(vertA.x, vertA.y); // Top-left corner for texture and quad
3495
+ if (drawCenter)
3496
+ {
3497
+ // MIDDLE QUAD
3498
+ // -----------------------------------------------------------
3499
+ // Texture coords Vertices
3500
+ rlTexCoord2f(coordA.x, coordC.y); rlVertex2f(vertA.x, vertC.y); // Bottom-left corner for texture and quad
3501
+ rlTexCoord2f(coordD.x, coordC.y); rlVertex2f(vertD.x, vertC.y); // Bottom-right corner for texture and quad
3502
+ rlTexCoord2f(coordD.x, coordB.y); rlVertex2f(vertD.x, vertB.y); // Top-right corner for texture and quad
3503
+ rlTexCoord2f(coordA.x, coordB.y); rlVertex2f(vertA.x, vertB.y); // Top-left corner for texture and quad
3504
+ }
3505
+ // BOTTOM QUAD
3506
+ // -----------------------------------------------------------
3507
+ // Texture coords Vertices
3508
+ rlTexCoord2f(coordA.x, coordD.y); rlVertex2f(vertA.x, vertD.y); // Bottom-left corner for texture and quad
3509
+ rlTexCoord2f(coordD.x, coordD.y); rlVertex2f(vertD.x, vertD.y); // Bottom-right corner for texture and quad
3510
+ rlTexCoord2f(coordD.x, coordC.y); rlVertex2f(vertD.x, vertC.y); // Top-right corner for texture and quad
3511
+ rlTexCoord2f(coordA.x, coordC.y); rlVertex2f(vertA.x, vertC.y); // Top-left corner for texture and quad
3512
+ }
3513
+ else if (nPatchInfo.layout == NPATCH_THREE_PATCH_HORIZONTAL)
3514
+ {
3515
+ // LEFT QUAD
3516
+ // -----------------------------------------------------------
3517
+ // Texture coords Vertices
3518
+ rlTexCoord2f(coordA.x, coordD.y); rlVertex2f(vertA.x, vertD.y); // Bottom-left corner for texture and quad
3519
+ rlTexCoord2f(coordB.x, coordD.y); rlVertex2f(vertB.x, vertD.y); // Bottom-right corner for texture and quad
3520
+ rlTexCoord2f(coordB.x, coordA.y); rlVertex2f(vertB.x, vertA.y); // Top-right corner for texture and quad
3521
+ rlTexCoord2f(coordA.x, coordA.y); rlVertex2f(vertA.x, vertA.y); // Top-left corner for texture and quad
3522
+ if (drawCenter)
3523
+ {
3524
+ // CENTER QUAD
3525
+ // -----------------------------------------------------------
3526
+ // Texture coords Vertices
3527
+ rlTexCoord2f(coordB.x, coordD.y); rlVertex2f(vertB.x, vertD.y); // Bottom-left corner for texture and quad
3528
+ rlTexCoord2f(coordC.x, coordD.y); rlVertex2f(vertC.x, vertD.y); // Bottom-right corner for texture and quad
3529
+ rlTexCoord2f(coordC.x, coordA.y); rlVertex2f(vertC.x, vertA.y); // Top-right corner for texture and quad
3530
+ rlTexCoord2f(coordB.x, coordA.y); rlVertex2f(vertB.x, vertA.y); // Top-left corner for texture and quad
3531
+ }
3532
+ // RIGHT QUAD
3533
+ // -----------------------------------------------------------
3534
+ // Texture coords Vertices
3535
+ rlTexCoord2f(coordC.x, coordD.y); rlVertex2f(vertC.x, vertD.y); // Bottom-left corner for texture and quad
3536
+ rlTexCoord2f(coordD.x, coordD.y); rlVertex2f(vertD.x, vertD.y); // Bottom-right corner for texture and quad
3537
+ rlTexCoord2f(coordD.x, coordA.y); rlVertex2f(vertD.x, vertA.y); // Top-right corner for texture and quad
3538
+ rlTexCoord2f(coordC.x, coordA.y); rlVertex2f(vertC.x, vertA.y); // Top-left corner for texture and quad
3539
+ }
3540
+ rlEnd();
3541
+ rlPopMatrix();
3542
+
3543
+ rlSetTexture(0);
3544
+ }
3545
+ }
3546
+
3547
+ // Draw textured polygon, defined by vertex and texturecoordinates
3548
+ // NOTE: Polygon center must have straight line path to all points
3549
+ // without crossing perimeter, points must be in anticlockwise order
3550
+ void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointCount, Color tint)
3551
+ {
3552
+ rlCheckRenderBatchLimit((pointCount - 1)*4);
3553
+
3554
+ rlSetTexture(texture.id);
3555
+
3556
+ // Texturing is only supported on QUADs
3557
+ rlBegin(RL_QUADS);
3558
+
3559
+ rlColor4ub(tint.r, tint.g, tint.b, tint.a);
3560
+
3561
+ for (int i = 0; i < pointCount - 1; i++)
3562
+ {
3563
+ rlTexCoord2f(0.5f, 0.5f);
3564
+ rlVertex2f(center.x, center.y);
3565
+
3566
+ rlTexCoord2f(texcoords[i].x, texcoords[i].y);
3567
+ rlVertex2f(points[i].x + center.x, points[i].y + center.y);
3568
+
3569
+ rlTexCoord2f(texcoords[i + 1].x, texcoords[i + 1].y);
3570
+ rlVertex2f(points[i + 1].x + center.x, points[i + 1].y + center.y);
3571
+
3572
+ rlTexCoord2f(texcoords[i + 1].x, texcoords[i + 1].y);
3573
+ rlVertex2f(points[i + 1].x + center.x, points[i + 1].y + center.y);
3574
+ }
3575
+ rlEnd();
3576
+
3577
+ rlSetTexture(0);
3578
+ }
3579
+
3580
+ // Get color with alpha applied, alpha goes from 0.0f to 1.0f
3581
+ Color Fade(Color color, float alpha)
3582
+ {
3583
+ if (alpha < 0.0f) alpha = 0.0f;
3584
+ else if (alpha > 1.0f) alpha = 1.0f;
3585
+
3586
+ return (Color){color.r, color.g, color.b, (unsigned char)(255.0f*alpha)};
3587
+ }
3588
+
3589
+ // Get hexadecimal value for a Color
3590
+ int ColorToInt(Color color)
3591
+ {
3592
+ return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
3593
+ }
3594
+
3595
+ // Get color normalized as float [0..1]
3596
+ Vector4 ColorNormalize(Color color)
3597
+ {
3598
+ Vector4 result;
3599
+
3600
+ result.x = (float)color.r/255.0f;
3601
+ result.y = (float)color.g/255.0f;
3602
+ result.z = (float)color.b/255.0f;
3603
+ result.w = (float)color.a/255.0f;
3604
+
3605
+ return result;
3606
+ }
3607
+
3608
+ // Get color from normalized values [0..1]
3609
+ Color ColorFromNormalized(Vector4 normalized)
3610
+ {
3611
+ Color result;
3612
+
3613
+ result.r = (unsigned char)(normalized.x*255.0f);
3614
+ result.g = (unsigned char)(normalized.y*255.0f);
3615
+ result.b = (unsigned char)(normalized.z*255.0f);
3616
+ result.a = (unsigned char)(normalized.w*255.0f);
3617
+
3618
+ return result;
3619
+ }
3620
+
3621
+ // Get HSV values for a Color
3622
+ // NOTE: Hue is returned as degrees [0..360]
3623
+ Vector3 ColorToHSV(Color color)
3624
+ {
3625
+ Vector3 hsv = { 0 };
3626
+ Vector3 rgb = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
3627
+ float min, max, delta;
3628
+
3629
+ min = rgb.x < rgb.y? rgb.x : rgb.y;
3630
+ min = min < rgb.z? min : rgb.z;
3631
+
3632
+ max = rgb.x > rgb.y? rgb.x : rgb.y;
3633
+ max = max > rgb.z? max : rgb.z;
3634
+
3635
+ hsv.z = max; // Value
3636
+ delta = max - min;
3637
+
3638
+ if (delta < 0.00001f)
3639
+ {
3640
+ hsv.y = 0.0f;
3641
+ hsv.x = 0.0f; // Undefined, maybe NAN?
3642
+ return hsv;
3643
+ }
3644
+
3645
+ if (max > 0.0f)
3646
+ {
3647
+ // NOTE: If max is 0, this divide would cause a crash
3648
+ hsv.y = (delta/max); // Saturation
3649
+ }
3650
+ else
3651
+ {
3652
+ // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
3653
+ hsv.y = 0.0f;
3654
+ hsv.x = NAN; // Undefined
3655
+ return hsv;
3656
+ }
3657
+
3658
+ // NOTE: Comparing float values could not work properly
3659
+ if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta
3660
+ else
3661
+ {
3662
+ if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow
3663
+ else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan
3664
+ }
3665
+
3666
+ hsv.x *= 60.0f; // Convert to degrees
3667
+
3668
+ if (hsv.x < 0.0f) hsv.x += 360.0f;
3669
+
3670
+ return hsv;
3671
+ }
3672
+
3673
+ // Get a Color from HSV values
3674
+ // Implementation reference: https://en.wikipedia.org/wiki/HSL_and_HSV#Alternative_HSV_conversion
3675
+ // NOTE: Color->HSV->Color conversion will not yield exactly the same color due to rounding errors
3676
+ // Hue is provided in degrees: [0..360]
3677
+ // Saturation/Value are provided normalized: [0.0f..1.0f]
3678
+ Color ColorFromHSV(float hue, float saturation, float value)
3679
+ {
3680
+ Color color = { 0, 0, 0, 255 };
3681
+
3682
+ // Red channel
3683
+ float k = fmodf((5.0f + hue/60.0f), 6);
3684
+ float t = 4.0f - k;
3685
+ k = (t < k)? t : k;
3686
+ k = (k < 1)? k : 1;
3687
+ k = (k > 0)? k : 0;
3688
+ color.r = (unsigned char)((value - value*saturation*k)*255.0f);
3689
+
3690
+ // Green channel
3691
+ k = fmodf((3.0f + hue/60.0f), 6);
3692
+ t = 4.0f - k;
3693
+ k = (t < k)? t : k;
3694
+ k = (k < 1)? k : 1;
3695
+ k = (k > 0)? k : 0;
3696
+ color.g = (unsigned char)((value - value*saturation*k)*255.0f);
3697
+
3698
+ // Blue channel
3699
+ k = fmodf((1.0f + hue/60.0f), 6);
3700
+ t = 4.0f - k;
3701
+ k = (t < k)? t : k;
3702
+ k = (k < 1)? k : 1;
3703
+ k = (k > 0)? k : 0;
3704
+ color.b = (unsigned char)((value - value*saturation*k)*255.0f);
3705
+
3706
+ return color;
3707
+ }
3708
+
3709
+ // Get color with alpha applied, alpha goes from 0.0f to 1.0f
3710
+ Color ColorAlpha(Color color, float alpha)
3711
+ {
3712
+ if (alpha < 0.0f) alpha = 0.0f;
3713
+ else if (alpha > 1.0f) alpha = 1.0f;
3714
+
3715
+ return (Color){color.r, color.g, color.b, (unsigned char)(255.0f*alpha)};
3716
+ }
3717
+
3718
+ // Get src alpha-blended into dst color with tint
3719
+ Color ColorAlphaBlend(Color dst, Color src, Color tint)
3720
+ {
3721
+ Color out = WHITE;
3722
+
3723
+ // Apply color tint to source color
3724
+ src.r = (unsigned char)(((unsigned int)src.r*(unsigned int)tint.r) >> 8);
3725
+ src.g = (unsigned char)(((unsigned int)src.g*(unsigned int)tint.g) >> 8);
3726
+ src.b = (unsigned char)(((unsigned int)src.b*(unsigned int)tint.b) >> 8);
3727
+ src.a = (unsigned char)(((unsigned int)src.a*(unsigned int)tint.a) >> 8);
3728
+
3729
+ //#define COLORALPHABLEND_FLOAT
3730
+ #define COLORALPHABLEND_INTEGERS
3731
+ #if defined(COLORALPHABLEND_INTEGERS)
3732
+ if (src.a == 0) out = dst;
3733
+ else if (src.a == 255) out = src;
3734
+ else
3735
+ {
3736
+ unsigned int alpha = (unsigned int)src.a + 1; // We are shifting by 8 (dividing by 256), so we need to take that excess into account
3737
+ out.a = (unsigned char)(((unsigned int)alpha*256 + (unsigned int)dst.a*(256 - alpha)) >> 8);
3738
+
3739
+ if (out.a > 0)
3740
+ {
3741
+ out.r = (unsigned char)((((unsigned int)src.r*alpha*256 + (unsigned int)dst.r*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
3742
+ out.g = (unsigned char)((((unsigned int)src.g*alpha*256 + (unsigned int)dst.g*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
3743
+ out.b = (unsigned char)((((unsigned int)src.b*alpha*256 + (unsigned int)dst.b*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
3744
+ }
3745
+ }
3746
+ #endif
3747
+ #if defined(COLORALPHABLEND_FLOAT)
3748
+ if (src.a == 0) out = dst;
3749
+ else if (src.a == 255) out = src;
3750
+ else
3751
+ {
3752
+ Vector4 fdst = ColorNormalize(dst);
3753
+ Vector4 fsrc = ColorNormalize(src);
3754
+ Vector4 ftint = ColorNormalize(tint);
3755
+ Vector4 fout = { 0 };
3756
+
3757
+ fout.w = fsrc.w + fdst.w*(1.0f - fsrc.w);
3758
+
3759
+ if (fout.w > 0.0f)
3760
+ {
3761
+ fout.x = (fsrc.x*fsrc.w + fdst.x*fdst.w*(1 - fsrc.w))/fout.w;
3762
+ fout.y = (fsrc.y*fsrc.w + fdst.y*fdst.w*(1 - fsrc.w))/fout.w;
3763
+ fout.z = (fsrc.z*fsrc.w + fdst.z*fdst.w*(1 - fsrc.w))/fout.w;
3764
+ }
3765
+
3766
+ out = (Color){ (unsigned char)(fout.x*255.0f), (unsigned char)(fout.y*255.0f), (unsigned char)(fout.z*255.0f), (unsigned char)(fout.w*255.0f) };
3767
+ }
3768
+ #endif
3769
+
3770
+ return out;
3771
+ }
3772
+
3773
+ // Get a Color struct from hexadecimal value
3774
+ Color GetColor(unsigned int hexValue)
3775
+ {
3776
+ Color color;
3777
+
3778
+ color.r = (unsigned char)(hexValue >> 24) & 0xFF;
3779
+ color.g = (unsigned char)(hexValue >> 16) & 0xFF;
3780
+ color.b = (unsigned char)(hexValue >> 8) & 0xFF;
3781
+ color.a = (unsigned char)hexValue & 0xFF;
3782
+
3783
+ return color;
3784
+ }
3785
+
3786
+ // Get color from a pixel from certain format
3787
+ Color GetPixelColor(void *srcPtr, int format)
3788
+ {
3789
+ Color color = { 0 };
3790
+
3791
+ switch (format)
3792
+ {
3793
+ case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: color = (Color){ ((unsigned char *)srcPtr)[0], ((unsigned char *)srcPtr)[0], ((unsigned char *)srcPtr)[0], 255 }; break;
3794
+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: color = (Color){ ((unsigned char *)srcPtr)[0], ((unsigned char *)srcPtr)[0], ((unsigned char *)srcPtr)[0], ((unsigned char *)srcPtr)[1] }; break;
3795
+ case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
3796
+ {
3797
+ color.r = (unsigned char)((((unsigned short *)srcPtr)[0] >> 11)*255/31);
3798
+ color.g = (unsigned char)(((((unsigned short *)srcPtr)[0] >> 5) & 0b0000000000111111)*255/63);
3799
+ color.b = (unsigned char)((((unsigned short *)srcPtr)[0] & 0b0000000000011111)*255/31);
3800
+ color.a = 255;
3801
+
3802
+ } break;
3803
+ case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
3804
+ {
3805
+ color.r = (unsigned char)((((unsigned short *)srcPtr)[0] >> 11)*255/31);
3806
+ color.g = (unsigned char)(((((unsigned short *)srcPtr)[0] >> 6) & 0b0000000000011111)*255/31);
3807
+ color.b = (unsigned char)((((unsigned short *)srcPtr)[0] & 0b0000000000011111)*255/31);
3808
+ color.a = (((unsigned short *)srcPtr)[0] & 0b0000000000000001)? 255 : 0;
3809
+
3810
+ } break;
3811
+ case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
3812
+ {
3813
+ color.r = (unsigned char)((((unsigned short *)srcPtr)[0] >> 12)*255/15);
3814
+ color.g = (unsigned char)(((((unsigned short *)srcPtr)[0] >> 8) & 0b0000000000001111)*255/15);
3815
+ color.b = (unsigned char)(((((unsigned short *)srcPtr)[0] >> 4) & 0b0000000000001111)*255/15);
3816
+ color.a = (unsigned char)((((unsigned short *)srcPtr)[0] & 0b0000000000001111)*255/15);
3817
+
3818
+ } break;
3819
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: color = (Color){ ((unsigned char *)srcPtr)[0], ((unsigned char *)srcPtr)[1], ((unsigned char *)srcPtr)[2], ((unsigned char *)srcPtr)[3] }; break;
3820
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8: color = (Color){ ((unsigned char *)srcPtr)[0], ((unsigned char *)srcPtr)[1], ((unsigned char *)srcPtr)[2], 255 }; break;
3821
+ case PIXELFORMAT_UNCOMPRESSED_R32:
3822
+ {
3823
+ // NOTE: Pixel normalized float value is converted to [0..255]
3824
+ color.r = (unsigned char)(((float *)srcPtr)[0]*255.0f);
3825
+ color.g = (unsigned char)(((float *)srcPtr)[0]*255.0f);
3826
+ color.b = (unsigned char)(((float *)srcPtr)[0]*255.0f);
3827
+ color.a = 255;
3828
+
3829
+ } break;
3830
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
3831
+ {
3832
+ // NOTE: Pixel normalized float value is converted to [0..255]
3833
+ color.r = (unsigned char)(((float *)srcPtr)[0]*255.0f);
3834
+ color.g = (unsigned char)(((float *)srcPtr)[1]*255.0f);
3835
+ color.b = (unsigned char)(((float *)srcPtr)[2]*255.0f);
3836
+ color.a = 255;
3837
+
3838
+ } break;
3839
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
3840
+ {
3841
+ // NOTE: Pixel normalized float value is converted to [0..255]
3842
+ color.r = (unsigned char)(((float *)srcPtr)[0]*255.0f);
3843
+ color.g = (unsigned char)(((float *)srcPtr)[1]*255.0f);
3844
+ color.b = (unsigned char)(((float *)srcPtr)[2]*255.0f);
3845
+ color.a = (unsigned char)(((float *)srcPtr)[3]*255.0f);
3846
+
3847
+ } break;
3848
+ default: break;
3849
+ }
3850
+
3851
+ return color;
3852
+ }
3853
+
3854
+ // Set pixel color formatted into destination pointer
3855
+ void SetPixelColor(void *dstPtr, Color color, int format)
3856
+ {
3857
+ switch (format)
3858
+ {
3859
+ case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
3860
+ {
3861
+ // NOTE: Calculate grayscale equivalent color
3862
+ Vector3 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
3863
+ unsigned char gray = (unsigned char)((coln.x*0.299f + coln.y*0.587f + coln.z*0.114f)*255.0f);
3864
+
3865
+ ((unsigned char *)dstPtr)[0] = gray;
3866
+
3867
+ } break;
3868
+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
3869
+ {
3870
+ // NOTE: Calculate grayscale equivalent color
3871
+ Vector3 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
3872
+ unsigned char gray = (unsigned char)((coln.x*0.299f + coln.y*0.587f + coln.z*0.114f)*255.0f);
3873
+
3874
+ ((unsigned char *)dstPtr)[0] = gray;
3875
+ ((unsigned char *)dstPtr)[1] = color.a;
3876
+
3877
+ } break;
3878
+ case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
3879
+ {
3880
+ // NOTE: Calculate R5G6B5 equivalent color
3881
+ Vector3 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f };
3882
+
3883
+ unsigned char r = (unsigned char)(round(coln.x*31.0f));
3884
+ unsigned char g = (unsigned char)(round(coln.y*63.0f));
3885
+ unsigned char b = (unsigned char)(round(coln.z*31.0f));
3886
+
3887
+ ((unsigned short *)dstPtr)[0] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
3888
+
3889
+ } break;
3890
+ case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
3891
+ {
3892
+ // NOTE: Calculate R5G5B5A1 equivalent color
3893
+ Vector4 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f, (float)color.a/255.0f };
3894
+
3895
+ unsigned char r = (unsigned char)(round(coln.x*31.0f));
3896
+ unsigned char g = (unsigned char)(round(coln.y*31.0f));
3897
+ unsigned char b = (unsigned char)(round(coln.z*31.0f));
3898
+ unsigned char a = (coln.w > ((float)PIXELFORMAT_UNCOMPRESSED_R5G5B5A1_ALPHA_THRESHOLD/255.0f))? 1 : 0;
3899
+
3900
+ ((unsigned short *)dstPtr)[0] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1 | (unsigned short)a;
3901
+
3902
+ } break;
3903
+ case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
3904
+ {
3905
+ // NOTE: Calculate R5G5B5A1 equivalent color
3906
+ Vector4 coln = { (float)color.r/255.0f, (float)color.g/255.0f, (float)color.b/255.0f, (float)color.a/255.0f };
3907
+
3908
+ unsigned char r = (unsigned char)(round(coln.x*15.0f));
3909
+ unsigned char g = (unsigned char)(round(coln.y*15.0f));
3910
+ unsigned char b = (unsigned char)(round(coln.z*15.0f));
3911
+ unsigned char a = (unsigned char)(round(coln.w*15.0f));
3912
+
3913
+ ((unsigned short *)dstPtr)[0] = (unsigned short)r << 12 | (unsigned short)g << 8 | (unsigned short)b << 4 | (unsigned short)a;
3914
+
3915
+ } break;
3916
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8:
3917
+ {
3918
+ ((unsigned char *)dstPtr)[0] = color.r;
3919
+ ((unsigned char *)dstPtr)[1] = color.g;
3920
+ ((unsigned char *)dstPtr)[2] = color.b;
3921
+
3922
+ } break;
3923
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
3924
+ {
3925
+ ((unsigned char *)dstPtr)[0] = color.r;
3926
+ ((unsigned char *)dstPtr)[1] = color.g;
3927
+ ((unsigned char *)dstPtr)[2] = color.b;
3928
+ ((unsigned char *)dstPtr)[3] = color.a;
3929
+
3930
+ } break;
3931
+ default: break;
3932
+ }
3933
+ }
3934
+
3935
+ // Get pixel data size in bytes for certain format
3936
+ // NOTE: Size can be requested for Image or Texture data
3937
+ int GetPixelDataSize(int width, int height, int format)
3938
+ {
3939
+ int dataSize = 0; // Size in bytes
3940
+ int bpp = 0; // Bits per pixel
3941
+
3942
+ switch (format)
3943
+ {
3944
+ case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break;
3945
+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
3946
+ case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
3947
+ case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
3948
+ case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
3949
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
3950
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break;
3951
+ case PIXELFORMAT_UNCOMPRESSED_R32: bpp = 32; break;
3952
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 32*3; break;
3953
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 32*4; break;
3954
+ case PIXELFORMAT_COMPRESSED_DXT1_RGB:
3955
+ case PIXELFORMAT_COMPRESSED_DXT1_RGBA:
3956
+ case PIXELFORMAT_COMPRESSED_ETC1_RGB:
3957
+ case PIXELFORMAT_COMPRESSED_ETC2_RGB:
3958
+ case PIXELFORMAT_COMPRESSED_PVRT_RGB:
3959
+ case PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break;
3960
+ case PIXELFORMAT_COMPRESSED_DXT3_RGBA:
3961
+ case PIXELFORMAT_COMPRESSED_DXT5_RGBA:
3962
+ case PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA:
3963
+ case PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: bpp = 8; break;
3964
+ case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break;
3965
+ default: break;
3966
+ }
3967
+
3968
+ dataSize = width*height*bpp/8; // Total data size in bytes
3969
+
3970
+ // Most compressed formats works on 4x4 blocks,
3971
+ // if texture is smaller, minimum dataSize is 8 or 16
3972
+ if ((width < 4) && (height < 4))
3973
+ {
3974
+ if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8;
3975
+ else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
3976
+ }
3977
+
3978
+ return dataSize;
3979
+ }
3980
+
3981
+ //----------------------------------------------------------------------------------
3982
+ // Module specific Functions Definition
3983
+ //----------------------------------------------------------------------------------
3984
+ #if defined(SUPPORT_FILEFORMAT_DDS)
3985
+ // Loading DDS image data (compressed or uncompressed)
3986
+ static Image LoadDDS(const unsigned char *fileData, unsigned int fileSize)
3987
+ {
3988
+ unsigned char *fileDataPtr = (unsigned char *)fileData;
3989
+
3990
+ // Required extension:
3991
+ // GL_EXT_texture_compression_s3tc
3992
+
3993
+ // Supported tokens (defined by extensions)
3994
+ // GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
3995
+ // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
3996
+ // GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
3997
+ // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
3998
+
3999
+ #define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
4000
+ #define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
4001
+ #define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII
4002
+
4003
+ // DDS Pixel Format
4004
+ typedef struct {
4005
+ unsigned int size;
4006
+ unsigned int flags;
4007
+ unsigned int fourCC;
4008
+ unsigned int rgbBitCount;
4009
+ unsigned int rBitMask;
4010
+ unsigned int gBitMask;
4011
+ unsigned int bBitMask;
4012
+ unsigned int aBitMask;
4013
+ } DDSPixelFormat;
4014
+
4015
+ // DDS Header (124 bytes)
4016
+ typedef struct {
4017
+ unsigned int size;
4018
+ unsigned int flags;
4019
+ unsigned int height;
4020
+ unsigned int width;
4021
+ unsigned int pitchOrLinearSize;
4022
+ unsigned int depth;
4023
+ unsigned int mipmapCount;
4024
+ unsigned int reserved1[11];
4025
+ DDSPixelFormat ddspf;
4026
+ unsigned int caps;
4027
+ unsigned int caps2;
4028
+ unsigned int caps3;
4029
+ unsigned int caps4;
4030
+ unsigned int reserved2;
4031
+ } DDSHeader;
4032
+
4033
+ Image image = { 0 };
4034
+
4035
+ if (fileDataPtr != NULL)
4036
+ {
4037
+ // Verify the type of file
4038
+ unsigned char *ddsHeaderId = fileDataPtr;
4039
+ fileDataPtr += 4;
4040
+
4041
+ if ((ddsHeaderId[0] != 'D') || (ddsHeaderId[1] != 'D') || (ddsHeaderId[2] != 'S') || (ddsHeaderId[3] != ' '))
4042
+ {
4043
+ TRACELOG(LOG_WARNING, "IMAGE: DDS file data not valid");
4044
+ }
4045
+ else
4046
+ {
4047
+ DDSHeader *ddsHeader = (DDSHeader *)fileDataPtr;
4048
+
4049
+ TRACELOGD("IMAGE: DDS file data info:");
4050
+ TRACELOGD(" > Header size: %i", sizeof(DDSHeader));
4051
+ TRACELOGD(" > Pixel format size: %i", ddsHeader->ddspf.size);
4052
+ TRACELOGD(" > Pixel format flags: 0x%x", ddsHeader->ddspf.flags);
4053
+ TRACELOGD(" > File format: 0x%x", ddsHeader->ddspf.fourCC);
4054
+ TRACELOGD(" > File bit count: 0x%x", ddsHeader->ddspf.rgbBitCount);
4055
+
4056
+ fileDataPtr += sizeof(DDSHeader); // Skip header
4057
+
4058
+ image.width = ddsHeader->width;
4059
+ image.height = ddsHeader->height;
4060
+
4061
+ if (ddsHeader->mipmapCount == 0) image.mipmaps = 1; // Parameter not used
4062
+ else image.mipmaps = ddsHeader->mipmapCount;
4063
+
4064
+ if (ddsHeader->ddspf.rgbBitCount == 16) // 16bit mode, no compressed
4065
+ {
4066
+ if (ddsHeader->ddspf.flags == 0x40) // no alpha channel
4067
+ {
4068
+ int dataSize = image.width*image.height*sizeof(unsigned short);
4069
+ image.data = (unsigned short *)RL_MALLOC(dataSize);
4070
+
4071
+ memcpy(image.data, fileDataPtr, dataSize);
4072
+
4073
+ image.format = PIXELFORMAT_UNCOMPRESSED_R5G6B5;
4074
+ }
4075
+ else if (ddsHeader->ddspf.flags == 0x41) // with alpha channel
4076
+ {
4077
+ if (ddsHeader->ddspf.aBitMask == 0x8000) // 1bit alpha
4078
+ {
4079
+ int dataSize = image.width*image.height*sizeof(unsigned short);
4080
+ image.data = (unsigned short *)RL_MALLOC(dataSize);
4081
+
4082
+ memcpy(image.data, fileDataPtr, dataSize);
4083
+
4084
+ unsigned char alpha = 0;
4085
+
4086
+ // NOTE: Data comes as A1R5G5B5, it must be reordered to R5G5B5A1
4087
+ for (int i = 0; i < image.width*image.height; i++)
4088
+ {
4089
+ alpha = ((unsigned short *)image.data)[i] >> 15;
4090
+ ((unsigned short *)image.data)[i] = ((unsigned short *)image.data)[i] << 1;
4091
+ ((unsigned short *)image.data)[i] += alpha;
4092
+ }
4093
+
4094
+ image.format = PIXELFORMAT_UNCOMPRESSED_R5G5B5A1;
4095
+ }
4096
+ else if (ddsHeader->ddspf.aBitMask == 0xf000) // 4bit alpha
4097
+ {
4098
+ int dataSize = image.width*image.height*sizeof(unsigned short);
4099
+ image.data = (unsigned short *)RL_MALLOC(dataSize);
4100
+
4101
+ memcpy(image.data, fileDataPtr, dataSize);
4102
+
4103
+ unsigned char alpha = 0;
4104
+
4105
+ // NOTE: Data comes as A4R4G4B4, it must be reordered R4G4B4A4
4106
+ for (int i = 0; i < image.width*image.height; i++)
4107
+ {
4108
+ alpha = ((unsigned short *)image.data)[i] >> 12;
4109
+ ((unsigned short *)image.data)[i] = ((unsigned short *)image.data)[i] << 4;
4110
+ ((unsigned short *)image.data)[i] += alpha;
4111
+ }
4112
+
4113
+ image.format = PIXELFORMAT_UNCOMPRESSED_R4G4B4A4;
4114
+ }
4115
+ }
4116
+ }
4117
+ else if (ddsHeader->ddspf.flags == 0x40 && ddsHeader->ddspf.rgbBitCount == 24) // DDS_RGB, no compressed
4118
+ {
4119
+ int dataSize = image.width*image.height*3*sizeof(unsigned char);
4120
+ image.data = (unsigned short *)RL_MALLOC(dataSize);
4121
+
4122
+ memcpy(image.data, fileDataPtr, dataSize);
4123
+
4124
+ image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8;
4125
+ }
4126
+ else if (ddsHeader->ddspf.flags == 0x41 && ddsHeader->ddspf.rgbBitCount == 32) // DDS_RGBA, no compressed
4127
+ {
4128
+ int dataSize = image.width*image.height*4*sizeof(unsigned char);
4129
+ image.data = (unsigned short *)RL_MALLOC(dataSize);
4130
+
4131
+ memcpy(image.data, fileDataPtr, dataSize);
4132
+
4133
+ unsigned char blue = 0;
4134
+
4135
+ // NOTE: Data comes as A8R8G8B8, it must be reordered R8G8B8A8 (view next comment)
4136
+ // DirecX understand ARGB as a 32bit DWORD but the actual memory byte alignment is BGRA
4137
+ // So, we must realign B8G8R8A8 to R8G8B8A8
4138
+ for (int i = 0; i < image.width*image.height*4; i += 4)
4139
+ {
4140
+ blue = ((unsigned char *)image.data)[i];
4141
+ ((unsigned char *)image.data)[i] = ((unsigned char *)image.data)[i + 2];
4142
+ ((unsigned char *)image.data)[i + 2] = blue;
4143
+ }
4144
+
4145
+ image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
4146
+ }
4147
+ else if (((ddsHeader->ddspf.flags == 0x04) || (ddsHeader->ddspf.flags == 0x05)) && (ddsHeader->ddspf.fourCC > 0)) // Compressed
4148
+ {
4149
+ int dataSize = 0;
4150
+
4151
+ // Calculate data size, including all mipmaps
4152
+ if (ddsHeader->mipmapCount > 1) dataSize = ddsHeader->pitchOrLinearSize*2;
4153
+ else dataSize = ddsHeader->pitchOrLinearSize;
4154
+
4155
+ image.data = (unsigned char *)RL_MALLOC(dataSize*sizeof(unsigned char));
4156
+
4157
+ memcpy(image.data, fileDataPtr, dataSize);
4158
+
4159
+ switch (ddsHeader->ddspf.fourCC)
4160
+ {
4161
+ case FOURCC_DXT1:
4162
+ {
4163
+ if (ddsHeader->ddspf.flags == 0x04) image.format = PIXELFORMAT_COMPRESSED_DXT1_RGB;
4164
+ else image.format = PIXELFORMAT_COMPRESSED_DXT1_RGBA;
4165
+ } break;
4166
+ case FOURCC_DXT3: image.format = PIXELFORMAT_COMPRESSED_DXT3_RGBA; break;
4167
+ case FOURCC_DXT5: image.format = PIXELFORMAT_COMPRESSED_DXT5_RGBA; break;
4168
+ default: break;
4169
+ }
4170
+ }
4171
+ }
4172
+ }
4173
+
4174
+ return image;
4175
+ }
4176
+ #endif
4177
+
4178
+ #if defined(SUPPORT_FILEFORMAT_PKM)
4179
+ // Loading PKM image data (ETC1/ETC2 compression)
4180
+ // NOTE: KTX is the standard Khronos Group compression format (ETC1/ETC2, mipmaps)
4181
+ // PKM is a much simpler file format used mainly to contain a single ETC1/ETC2 compressed image (no mipmaps)
4182
+ static Image LoadPKM(const unsigned char *fileData, unsigned int fileSize)
4183
+ {
4184
+ unsigned char *fileDataPtr = (unsigned char *)fileData;
4185
+
4186
+ // Required extensions:
4187
+ // GL_OES_compressed_ETC1_RGB8_texture (ETC1) (OpenGL ES 2.0)
4188
+ // GL_ARB_ES3_compatibility (ETC2/EAC) (OpenGL ES 3.0)
4189
+
4190
+ // Supported tokens (defined by extensions)
4191
+ // GL_ETC1_RGB8_OES 0x8D64
4192
+ // GL_COMPRESSED_RGB8_ETC2 0x9274
4193
+ // GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
4194
+
4195
+ // PKM file (ETC1) Header (16 bytes)
4196
+ typedef struct {
4197
+ char id[4]; // "PKM "
4198
+ char version[2]; // "10" or "20"
4199
+ unsigned short format; // Data format (big-endian) (Check list below)
4200
+ unsigned short width; // Texture width (big-endian) (origWidth rounded to multiple of 4)
4201
+ unsigned short height; // Texture height (big-endian) (origHeight rounded to multiple of 4)
4202
+ unsigned short origWidth; // Original width (big-endian)
4203
+ unsigned short origHeight; // Original height (big-endian)
4204
+ } PKMHeader;
4205
+
4206
+ // Formats list
4207
+ // version 10: format: 0=ETC1_RGB, [1=ETC1_RGBA, 2=ETC1_RGB_MIP, 3=ETC1_RGBA_MIP] (not used)
4208
+ // version 20: format: 0=ETC1_RGB, 1=ETC2_RGB, 2=ETC2_RGBA_OLD, 3=ETC2_RGBA, 4=ETC2_RGBA1, 5=ETC2_R, 6=ETC2_RG, 7=ETC2_SIGNED_R, 8=ETC2_SIGNED_R
4209
+
4210
+ // NOTE: The extended width and height are the widths rounded up to a multiple of 4.
4211
+ // NOTE: ETC is always 4bit per pixel (64 bit for each 4x4 block of pixels)
4212
+
4213
+ Image image = { 0 };
4214
+
4215
+ if (fileDataPtr != NULL)
4216
+ {
4217
+ PKMHeader *pkmHeader = (PKMHeader *)fileDataPtr;
4218
+
4219
+ if ((pkmHeader->id[0] != 'P') || (pkmHeader->id[1] != 'K') || (pkmHeader->id[2] != 'M') || (pkmHeader->id[3] != ' '))
4220
+ {
4221
+ TRACELOG(LOG_WARNING, "IMAGE: PKM file data not valid");
4222
+ }
4223
+ else
4224
+ {
4225
+ fileDataPtr += sizeof(PKMHeader); // Skip header
4226
+
4227
+ // NOTE: format, width and height come as big-endian, data must be swapped to little-endian
4228
+ pkmHeader->format = ((pkmHeader->format & 0x00FF) << 8) | ((pkmHeader->format & 0xFF00) >> 8);
4229
+ pkmHeader->width = ((pkmHeader->width & 0x00FF) << 8) | ((pkmHeader->width & 0xFF00) >> 8);
4230
+ pkmHeader->height = ((pkmHeader->height & 0x00FF) << 8) | ((pkmHeader->height & 0xFF00) >> 8);
4231
+
4232
+ TRACELOGD("IMAGE: PKM file data info:");
4233
+ TRACELOGD(" > Image width: %i", pkmHeader->width);
4234
+ TRACELOGD(" > Image height: %i", pkmHeader->height);
4235
+ TRACELOGD(" > Image format: %i", pkmHeader->format);
4236
+
4237
+ image.width = pkmHeader->width;
4238
+ image.height = pkmHeader->height;
4239
+ image.mipmaps = 1;
4240
+
4241
+ int bpp = 4;
4242
+ if (pkmHeader->format == 3) bpp = 8;
4243
+
4244
+ int dataSize = image.width*image.height*bpp/8; // Total data size in bytes
4245
+
4246
+ image.data = (unsigned char *)RL_MALLOC(dataSize*sizeof(unsigned char));
4247
+
4248
+ memcpy(image.data, fileDataPtr, dataSize);
4249
+
4250
+ if (pkmHeader->format == 0) image.format = PIXELFORMAT_COMPRESSED_ETC1_RGB;
4251
+ else if (pkmHeader->format == 1) image.format = PIXELFORMAT_COMPRESSED_ETC2_RGB;
4252
+ else if (pkmHeader->format == 3) image.format = PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA;
4253
+ }
4254
+ }
4255
+
4256
+ return image;
4257
+ }
4258
+ #endif
4259
+
4260
+ #if defined(SUPPORT_FILEFORMAT_KTX)
4261
+ // Load KTX compressed image data (ETC1/ETC2 compression)
4262
+ static Image LoadKTX(const unsigned char *fileData, unsigned int fileSize)
4263
+ {
4264
+ unsigned char *fileDataPtr = (unsigned char *)fileData;
4265
+
4266
+ // Required extensions:
4267
+ // GL_OES_compressed_ETC1_RGB8_texture (ETC1)
4268
+ // GL_ARB_ES3_compatibility (ETC2/EAC)
4269
+
4270
+ // Supported tokens (defined by extensions)
4271
+ // GL_ETC1_RGB8_OES 0x8D64
4272
+ // GL_COMPRESSED_RGB8_ETC2 0x9274
4273
+ // GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
4274
+
4275
+ // KTX file Header (64 bytes)
4276
+ // v1.1 - https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
4277
+ // v2.0 - http://github.khronos.org/KTX-Specification/
4278
+
4279
+ // TODO: Support KTX 2.2 specs!
4280
+
4281
+ typedef struct {
4282
+ char id[12]; // Identifier: "«KTX 11»\r\n\x1A\n"
4283
+ unsigned int endianness; // Little endian: 0x01 0x02 0x03 0x04
4284
+ unsigned int glType; // For compressed textures, glType must equal 0
4285
+ unsigned int glTypeSize; // For compressed texture data, usually 1
4286
+ unsigned int glFormat; // For compressed textures is 0
4287
+ unsigned int glInternalFormat; // Compressed internal format
4288
+ unsigned int glBaseInternalFormat; // Same as glFormat (RGB, RGBA, ALPHA...)
4289
+ unsigned int width; // Texture image width in pixels
4290
+ unsigned int height; // Texture image height in pixels
4291
+ unsigned int depth; // For 2D textures is 0
4292
+ unsigned int elements; // Number of array elements, usually 0
4293
+ unsigned int faces; // Cubemap faces, for no-cubemap = 1
4294
+ unsigned int mipmapLevels; // Non-mipmapped textures = 1
4295
+ unsigned int keyValueDataSize; // Used to encode any arbitrary data...
4296
+ } KTXHeader;
4297
+
4298
+ // NOTE: Before start of every mipmap data block, we have: unsigned int dataSize
4299
+
4300
+ Image image = { 0 };
4301
+
4302
+ if (fileDataPtr != NULL)
4303
+ {
4304
+ KTXHeader *ktxHeader = (KTXHeader *)fileDataPtr;
4305
+
4306
+ if ((ktxHeader->id[1] != 'K') || (ktxHeader->id[2] != 'T') || (ktxHeader->id[3] != 'X') ||
4307
+ (ktxHeader->id[4] != ' ') || (ktxHeader->id[5] != '1') || (ktxHeader->id[6] != '1'))
4308
+ {
4309
+ TRACELOG(LOG_WARNING, "IMAGE: KTX file data not valid");
4310
+ }
4311
+ else
4312
+ {
4313
+ fileDataPtr += sizeof(KTXHeader); // Move file data pointer
4314
+
4315
+ image.width = ktxHeader->width;
4316
+ image.height = ktxHeader->height;
4317
+ image.mipmaps = ktxHeader->mipmapLevels;
4318
+
4319
+ TRACELOGD("IMAGE: KTX file data info:");
4320
+ TRACELOGD(" > Image width: %i", ktxHeader->width);
4321
+ TRACELOGD(" > Image height: %i", ktxHeader->height);
4322
+ TRACELOGD(" > Image format: 0x%x", ktxHeader->glInternalFormat);
4323
+
4324
+ fileDataPtr += ktxHeader->keyValueDataSize; // Skip value data size
4325
+
4326
+ int dataSize = ((int *)fileDataPtr)[0];
4327
+ fileDataPtr += sizeof(int);
4328
+
4329
+ image.data = (unsigned char *)RL_MALLOC(dataSize*sizeof(unsigned char));
4330
+
4331
+ memcpy(image.data, fileDataPtr, dataSize);
4332
+
4333
+ if (ktxHeader->glInternalFormat == 0x8D64) image.format = PIXELFORMAT_COMPRESSED_ETC1_RGB;
4334
+ else if (ktxHeader->glInternalFormat == 0x9274) image.format = PIXELFORMAT_COMPRESSED_ETC2_RGB;
4335
+ else if (ktxHeader->glInternalFormat == 0x9278) image.format = PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA;
4336
+ }
4337
+ }
4338
+
4339
+ return image;
4340
+ }
4341
+
4342
+ // Save image data as KTX file
4343
+ // NOTE: By default KTX 1.1 spec is used, 2.0 is still on draft (01Oct2018)
4344
+ static int SaveKTX(Image image, const char *fileName)
4345
+ {
4346
+ // KTX file Header (64 bytes)
4347
+ // v1.1 - https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
4348
+ // v2.0 - http://github.khronos.org/KTX-Specification/ - still on draft, not ready for implementation
4349
+ typedef struct {
4350
+ char id[12]; // Identifier: "«KTX 11»\r\n\x1A\n" // KTX 2.0: "«KTX 22»\r\n\x1A\n"
4351
+ unsigned int endianness; // Little endian: 0x01 0x02 0x03 0x04
4352
+ unsigned int glType; // For compressed textures, glType must equal 0
4353
+ unsigned int glTypeSize; // For compressed texture data, usually 1
4354
+ unsigned int glFormat; // For compressed textures is 0
4355
+ unsigned int glInternalFormat; // Compressed internal format
4356
+ unsigned int glBaseInternalFormat; // Same as glFormat (RGB, RGBA, ALPHA...) // KTX 2.0: UInt32 vkFormat
4357
+ unsigned int width; // Texture image width in pixels
4358
+ unsigned int height; // Texture image height in pixels
4359
+ unsigned int depth; // For 2D textures is 0
4360
+ unsigned int elements; // Number of array elements, usually 0
4361
+ unsigned int faces; // Cubemap faces, for no-cubemap = 1
4362
+ unsigned int mipmapLevels; // Non-mipmapped textures = 1
4363
+ unsigned int keyValueDataSize; // Used to encode any arbitrary data... // KTX 2.0: UInt32 levelOrder - ordering of the mipmap levels, usually 0
4364
+ // KTX 2.0: UInt32 supercompressionScheme - 0 (None), 1 (Crunch CRN), 2 (Zlib DEFLATE)...
4365
+ // KTX 2.0 defines additional header elements...
4366
+ } KTXHeader;
4367
+
4368
+ // Calculate file dataSize required
4369
+ int dataSize = sizeof(KTXHeader);
4370
+
4371
+ for (int i = 0, width = image.width, height = image.height; i < image.mipmaps; i++)
4372
+ {
4373
+ dataSize += GetPixelDataSize(width, height, image.format);
4374
+ width /= 2; height /= 2;
4375
+ }
4376
+
4377
+ unsigned char *fileData = RL_CALLOC(dataSize, 1);
4378
+ unsigned char *fileDataPtr = fileData;
4379
+
4380
+ KTXHeader ktxHeader = { 0 };
4381
+
4382
+ // KTX identifier (v1.1)
4383
+ //unsigned char id[12] = { '«', 'K', 'T', 'X', ' ', '1', '1', '»', '\r', '\n', '\x1A', '\n' };
4384
+ //unsigned char id[12] = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
4385
+
4386
+ const char ktxIdentifier[12] = { 0xAB, 'K', 'T', 'X', ' ', '1', '1', 0xBB, '\r', '\n', 0x1A, '\n' };
4387
+
4388
+ // Get the image header
4389
+ memcpy(ktxHeader.id, ktxIdentifier, 12); // KTX 1.1 signature
4390
+ ktxHeader.endianness = 0;
4391
+ ktxHeader.glType = 0; // Obtained from image.format
4392
+ ktxHeader.glTypeSize = 1;
4393
+ ktxHeader.glFormat = 0; // Obtained from image.format
4394
+ ktxHeader.glInternalFormat = 0; // Obtained from image.format
4395
+ ktxHeader.glBaseInternalFormat = 0;
4396
+ ktxHeader.width = image.width;
4397
+ ktxHeader.height = image.height;
4398
+ ktxHeader.depth = 0;
4399
+ ktxHeader.elements = 0;
4400
+ ktxHeader.faces = 1;
4401
+ ktxHeader.mipmapLevels = image.mipmaps; // If it was 0, it means mipmaps should be generated on loading (not for compressed formats)
4402
+ ktxHeader.keyValueDataSize = 0; // No extra data after the header
4403
+
4404
+ rlGetGlTextureFormats(image.format, &ktxHeader.glInternalFormat, &ktxHeader.glFormat, &ktxHeader.glType); // rlgl module function
4405
+ ktxHeader.glBaseInternalFormat = ktxHeader.glFormat; // KTX 1.1 only
4406
+
4407
+ // NOTE: We can save into a .ktx all PixelFormats supported by raylib, including compressed formats like DXT, ETC or ASTC
4408
+
4409
+ if (ktxHeader.glFormat == -1) TRACELOG(LOG_WARNING, "IMAGE: GL format not supported for KTX export (%i)", ktxHeader.glFormat);
4410
+ else
4411
+ {
4412
+ memcpy(fileDataPtr, &ktxHeader, sizeof(KTXHeader));
4413
+ fileDataPtr += sizeof(KTXHeader);
4414
+
4415
+ int width = image.width;
4416
+ int height = image.height;
4417
+ int dataOffset = 0;
4418
+
4419
+ // Save all mipmaps data
4420
+ for (int i = 0; i < image.mipmaps; i++)
4421
+ {
4422
+ unsigned int dataSize = GetPixelDataSize(width, height, image.format);
4423
+
4424
+ memcpy(fileDataPtr, &dataSize, sizeof(unsigned int));
4425
+ memcpy(fileDataPtr + 4, (unsigned char *)image.data + dataOffset, dataSize);
4426
+
4427
+ width /= 2;
4428
+ height /= 2;
4429
+ dataOffset += dataSize;
4430
+ fileDataPtr += (4 + dataSize);
4431
+ }
4432
+ }
4433
+
4434
+ int success = SaveFileData(fileName, fileData, dataSize);
4435
+
4436
+ RL_FREE(fileData); // Free file data buffer
4437
+
4438
+ // If all data has been written correctly to file, success = 1
4439
+ return success;
4440
+ }
4441
+ #endif
4442
+
4443
+ #if defined(SUPPORT_FILEFORMAT_PVR)
4444
+ // Loading PVR image data (uncompressed or PVRT compression)
4445
+ // NOTE: PVR v2 not supported, use PVR v3 instead
4446
+ static Image LoadPVR(const unsigned char *fileData, unsigned int fileSize)
4447
+ {
4448
+ unsigned char *fileDataPtr = (unsigned char *)fileData;
4449
+
4450
+ // Required extension:
4451
+ // GL_IMG_texture_compression_pvrtc
4452
+
4453
+ // Supported tokens (defined by extensions)
4454
+ // GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
4455
+ // GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
4456
+
4457
+ #if 0 // Not used...
4458
+ // PVR file v2 Header (52 bytes)
4459
+ typedef struct {
4460
+ unsigned int headerLength;
4461
+ unsigned int height;
4462
+ unsigned int width;
4463
+ unsigned int numMipmaps;
4464
+ unsigned int flags;
4465
+ unsigned int dataLength;
4466
+ unsigned int bpp;
4467
+ unsigned int bitmaskRed;
4468
+ unsigned int bitmaskGreen;
4469
+ unsigned int bitmaskBlue;
4470
+ unsigned int bitmaskAlpha;
4471
+ unsigned int pvrTag;
4472
+ unsigned int numSurfs;
4473
+ } PVRHeaderV2;
4474
+ #endif
4475
+
4476
+ // PVR file v3 Header (52 bytes)
4477
+ // NOTE: After it could be metadata (15 bytes?)
4478
+ typedef struct {
4479
+ char id[4];
4480
+ unsigned int flags;
4481
+ unsigned char channels[4]; // pixelFormat high part
4482
+ unsigned char channelDepth[4]; // pixelFormat low part
4483
+ unsigned int colourSpace;
4484
+ unsigned int channelType;
4485
+ unsigned int height;
4486
+ unsigned int width;
4487
+ unsigned int depth;
4488
+ unsigned int numSurfaces;
4489
+ unsigned int numFaces;
4490
+ unsigned int numMipmaps;
4491
+ unsigned int metaDataSize;
4492
+ } PVRHeaderV3;
4493
+
4494
+ #if 0 // Not used...
4495
+ // Metadata (usually 15 bytes)
4496
+ typedef struct {
4497
+ unsigned int devFOURCC;
4498
+ unsigned int key;
4499
+ unsigned int dataSize; // Not used?
4500
+ unsigned char *data; // Not used?
4501
+ } PVRMetadata;
4502
+ #endif
4503
+
4504
+ Image image = { 0 };
4505
+
4506
+ if (fileDataPtr != NULL)
4507
+ {
4508
+ // Check PVR image version
4509
+ unsigned char pvrVersion = fileDataPtr[0];
4510
+
4511
+ // Load different PVR data formats
4512
+ if (pvrVersion == 0x50)
4513
+ {
4514
+ PVRHeaderV3 *pvrHeader = (PVRHeaderV3 *)fileDataPtr;
4515
+
4516
+ if ((pvrHeader->id[0] != 'P') || (pvrHeader->id[1] != 'V') || (pvrHeader->id[2] != 'R') || (pvrHeader->id[3] != 3))
4517
+ {
4518
+ TRACELOG(LOG_WARNING, "IMAGE: PVR file data not valid");
4519
+ }
4520
+ else
4521
+ {
4522
+ fileDataPtr += sizeof(PVRHeaderV3); // Skip header
4523
+
4524
+ image.width = pvrHeader->width;
4525
+ image.height = pvrHeader->height;
4526
+ image.mipmaps = pvrHeader->numMipmaps;
4527
+
4528
+ // Check data format
4529
+ if (((pvrHeader->channels[0] == 'l') && (pvrHeader->channels[1] == 0)) && (pvrHeader->channelDepth[0] == 8)) image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
4530
+ else if (((pvrHeader->channels[0] == 'l') && (pvrHeader->channels[1] == 'a')) && ((pvrHeader->channelDepth[0] == 8) && (pvrHeader->channelDepth[1] == 8))) image.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
4531
+ else if ((pvrHeader->channels[0] == 'r') && (pvrHeader->channels[1] == 'g') && (pvrHeader->channels[2] == 'b'))
4532
+ {
4533
+ if (pvrHeader->channels[3] == 'a')
4534
+ {
4535
+ if ((pvrHeader->channelDepth[0] == 5) && (pvrHeader->channelDepth[1] == 5) && (pvrHeader->channelDepth[2] == 5) && (pvrHeader->channelDepth[3] == 1)) image.format = PIXELFORMAT_UNCOMPRESSED_R5G5B5A1;
4536
+ else if ((pvrHeader->channelDepth[0] == 4) && (pvrHeader->channelDepth[1] == 4) && (pvrHeader->channelDepth[2] == 4) && (pvrHeader->channelDepth[3] == 4)) image.format = PIXELFORMAT_UNCOMPRESSED_R4G4B4A4;
4537
+ else if ((pvrHeader->channelDepth[0] == 8) && (pvrHeader->channelDepth[1] == 8) && (pvrHeader->channelDepth[2] == 8) && (pvrHeader->channelDepth[3] == 8)) image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
4538
+ }
4539
+ else if (pvrHeader->channels[3] == 0)
4540
+ {
4541
+ if ((pvrHeader->channelDepth[0] == 5) && (pvrHeader->channelDepth[1] == 6) && (pvrHeader->channelDepth[2] == 5)) image.format = PIXELFORMAT_UNCOMPRESSED_R5G6B5;
4542
+ else if ((pvrHeader->channelDepth[0] == 8) && (pvrHeader->channelDepth[1] == 8) && (pvrHeader->channelDepth[2] == 8)) image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8;
4543
+ }
4544
+ }
4545
+ else if (pvrHeader->channels[0] == 2) image.format = PIXELFORMAT_COMPRESSED_PVRT_RGB;
4546
+ else if (pvrHeader->channels[0] == 3) image.format = PIXELFORMAT_COMPRESSED_PVRT_RGBA;
4547
+
4548
+ fileDataPtr += pvrHeader->metaDataSize; // Skip meta data header
4549
+
4550
+ // Calculate data size (depends on format)
4551
+ int bpp = 0;
4552
+ switch (image.format)
4553
+ {
4554
+ case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 8; break;
4555
+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
4556
+ case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
4557
+ case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
4558
+ case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 16; break;
4559
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 32; break;
4560
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 24; break;
4561
+ case PIXELFORMAT_COMPRESSED_PVRT_RGB:
4562
+ case PIXELFORMAT_COMPRESSED_PVRT_RGBA: bpp = 4; break;
4563
+ default: break;
4564
+ }
4565
+
4566
+ int dataSize = image.width*image.height*bpp/8; // Total data size in bytes
4567
+ image.data = (unsigned char *)RL_MALLOC(dataSize*sizeof(unsigned char));
4568
+
4569
+ memcpy(image.data, fileDataPtr, dataSize);
4570
+ }
4571
+ }
4572
+ else if (pvrVersion == 52) TRACELOG(LOG_INFO, "IMAGE: PVRv2 format not supported, update your files to PVRv3");
4573
+ }
4574
+
4575
+ return image;
4576
+ }
4577
+ #endif
4578
+
4579
+ #if defined(SUPPORT_FILEFORMAT_ASTC)
4580
+ // Load ASTC compressed image data (ASTC compression)
4581
+ static Image LoadASTC(const unsigned char *fileData, unsigned int fileSize)
4582
+ {
4583
+ unsigned char *fileDataPtr = (unsigned char *)fileData;
4584
+
4585
+ // Required extensions:
4586
+ // GL_KHR_texture_compression_astc_hdr
4587
+ // GL_KHR_texture_compression_astc_ldr
4588
+
4589
+ // Supported tokens (defined by extensions)
4590
+ // GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93b0
4591
+ // GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93b7
4592
+
4593
+ // ASTC file Header (16 bytes)
4594
+ typedef struct {
4595
+ unsigned char id[4]; // Signature: 0x13 0xAB 0xA1 0x5C
4596
+ unsigned char blockX; // Block X dimensions
4597
+ unsigned char blockY; // Block Y dimensions
4598
+ unsigned char blockZ; // Block Z dimensions (1 for 2D images)
4599
+ unsigned char width[3]; // Image width in pixels (24bit value)
4600
+ unsigned char height[3]; // Image height in pixels (24bit value)
4601
+ unsigned char length[3]; // Image Z-size (1 for 2D images)
4602
+ } ASTCHeader;
4603
+
4604
+ Image image = { 0 };
4605
+
4606
+ if (fileDataPtr != NULL)
4607
+ {
4608
+ ASTCHeader *astcHeader = (ASTCHeader *)fileDataPtr;
4609
+
4610
+ if ((astcHeader->id[3] != 0x5c) || (astcHeader->id[2] != 0xa1) || (astcHeader->id[1] != 0xab) || (astcHeader->id[0] != 0x13))
4611
+ {
4612
+ TRACELOG(LOG_WARNING, "IMAGE: ASTC file data not valid");
4613
+ }
4614
+ else
4615
+ {
4616
+ fileDataPtr += sizeof(ASTCHeader); // Skip header
4617
+
4618
+ // NOTE: Assuming Little Endian (could it be wrong?)
4619
+ image.width = 0x00000000 | ((int)astcHeader->width[2] << 16) | ((int)astcHeader->width[1] << 8) | ((int)astcHeader->width[0]);
4620
+ image.height = 0x00000000 | ((int)astcHeader->height[2] << 16) | ((int)astcHeader->height[1] << 8) | ((int)astcHeader->height[0]);
4621
+
4622
+ TRACELOGD("IMAGE: ASTC file data info:");
4623
+ TRACELOGD(" > Image width: %i", image.width);
4624
+ TRACELOGD(" > Image height: %i", image.height);
4625
+ TRACELOGD(" > Image blocks: %ix%i", astcHeader->blockX, astcHeader->blockY);
4626
+
4627
+ image.mipmaps = 1; // NOTE: ASTC format only contains one mipmap level
4628
+
4629
+ // NOTE: Each block is always stored in 128bit so we can calculate the bpp
4630
+ int bpp = 128/(astcHeader->blockX*astcHeader->blockY);
4631
+
4632
+ // NOTE: Currently we only support 2 blocks configurations: 4x4 and 8x8
4633
+ if ((bpp == 8) || (bpp == 2))
4634
+ {
4635
+ int dataSize = image.width*image.height*bpp/8; // Data size in bytes
4636
+
4637
+ image.data = (unsigned char *)RL_MALLOC(dataSize*sizeof(unsigned char));
4638
+
4639
+ memcpy(image.data, fileDataPtr, dataSize);
4640
+
4641
+ if (bpp == 8) image.format = PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA;
4642
+ else if (bpp == 2) image.format = PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA;
4643
+ }
4644
+ else TRACELOG(LOG_WARNING, "IMAGE: ASTC block size configuration not supported");
4645
+ }
4646
+ }
4647
+
4648
+ return image;
4649
+ }
4650
+ #endif
4651
+
4652
+ // Get pixel data from image as Vector4 array (float normalized)
4653
+ static Vector4 *LoadImageDataNormalized(Image image)
4654
+ {
4655
+ Vector4 *pixels = (Vector4 *)RL_MALLOC(image.width*image.height*sizeof(Vector4));
4656
+
4657
+ if (image.format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) TRACELOG(LOG_WARNING, "IMAGE: Pixel data retrieval not supported for compressed image formats");
4658
+ else
4659
+ {
4660
+ for (int i = 0, k = 0; i < image.width*image.height; i++)
4661
+ {
4662
+ switch (image.format)
4663
+ {
4664
+ case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
4665
+ {
4666
+ pixels[i].x = (float)((unsigned char *)image.data)[i]/255.0f;
4667
+ pixels[i].y = (float)((unsigned char *)image.data)[i]/255.0f;
4668
+ pixels[i].z = (float)((unsigned char *)image.data)[i]/255.0f;
4669
+ pixels[i].w = 1.0f;
4670
+
4671
+ } break;
4672
+ case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
4673
+ {
4674
+ pixels[i].x = (float)((unsigned char *)image.data)[k]/255.0f;
4675
+ pixels[i].y = (float)((unsigned char *)image.data)[k]/255.0f;
4676
+ pixels[i].z = (float)((unsigned char *)image.data)[k]/255.0f;
4677
+ pixels[i].w = (float)((unsigned char *)image.data)[k + 1]/255.0f;
4678
+
4679
+ k += 2;
4680
+ } break;
4681
+ case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
4682
+ {
4683
+ unsigned short pixel = ((unsigned short *)image.data)[i];
4684
+
4685
+ pixels[i].x = (float)((pixel & 0b1111100000000000) >> 11)*(1.0f/31);
4686
+ pixels[i].y = (float)((pixel & 0b0000011111000000) >> 6)*(1.0f/31);
4687
+ pixels[i].z = (float)((pixel & 0b0000000000111110) >> 1)*(1.0f/31);
4688
+ pixels[i].w = ((pixel & 0b0000000000000001) == 0)? 0.0f : 1.0f;
4689
+
4690
+ } break;
4691
+ case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
4692
+ {
4693
+ unsigned short pixel = ((unsigned short *)image.data)[i];
4694
+
4695
+ pixels[i].x = (float)((pixel & 0b1111100000000000) >> 11)*(1.0f/31);
4696
+ pixels[i].y = (float)((pixel & 0b0000011111100000) >> 5)*(1.0f/63);
4697
+ pixels[i].z = (float)(pixel & 0b0000000000011111)*(1.0f/31);
4698
+ pixels[i].w = 1.0f;
4699
+
4700
+ } break;
4701
+ case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
4702
+ {
4703
+ unsigned short pixel = ((unsigned short *)image.data)[i];
4704
+
4705
+ pixels[i].x = (float)((pixel & 0b1111000000000000) >> 12)*(1.0f/15);
4706
+ pixels[i].y = (float)((pixel & 0b0000111100000000) >> 8)*(1.0f/15);
4707
+ pixels[i].z = (float)((pixel & 0b0000000011110000) >> 4)*(1.0f/15);
4708
+ pixels[i].w = (float)(pixel & 0b0000000000001111)*(1.0f/15);
4709
+
4710
+ } break;
4711
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
4712
+ {
4713
+ pixels[i].x = (float)((unsigned char *)image.data)[k]/255.0f;
4714
+ pixels[i].y = (float)((unsigned char *)image.data)[k + 1]/255.0f;
4715
+ pixels[i].z = (float)((unsigned char *)image.data)[k + 2]/255.0f;
4716
+ pixels[i].w = (float)((unsigned char *)image.data)[k + 3]/255.0f;
4717
+
4718
+ k += 4;
4719
+ } break;
4720
+ case PIXELFORMAT_UNCOMPRESSED_R8G8B8:
4721
+ {
4722
+ pixels[i].x = (float)((unsigned char *)image.data)[k]/255.0f;
4723
+ pixels[i].y = (float)((unsigned char *)image.data)[k + 1]/255.0f;
4724
+ pixels[i].z = (float)((unsigned char *)image.data)[k + 2]/255.0f;
4725
+ pixels[i].w = 1.0f;
4726
+
4727
+ k += 3;
4728
+ } break;
4729
+ case PIXELFORMAT_UNCOMPRESSED_R32:
4730
+ {
4731
+ pixels[i].x = ((float *)image.data)[k];
4732
+ pixels[i].y = 0.0f;
4733
+ pixels[i].z = 0.0f;
4734
+ pixels[i].w = 1.0f;
4735
+
4736
+ } break;
4737
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
4738
+ {
4739
+ pixels[i].x = ((float *)image.data)[k];
4740
+ pixels[i].y = ((float *)image.data)[k + 1];
4741
+ pixels[i].z = ((float *)image.data)[k + 2];
4742
+ pixels[i].w = 1.0f;
4743
+
4744
+ k += 3;
4745
+ } break;
4746
+ case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
4747
+ {
4748
+ pixels[i].x = ((float *)image.data)[k];
4749
+ pixels[i].y = ((float *)image.data)[k + 1];
4750
+ pixels[i].z = ((float *)image.data)[k + 2];
4751
+ pixels[i].w = ((float *)image.data)[k + 3];
4752
+
4753
+ k += 4;
4754
+ }
4755
+ default: break;
4756
+ }
4757
+ }
4758
+ }
4759
+
4760
+ return pixels;
4761
+ }