Skip to content

Conversation

@ChocolateChipKookie
Copy link
Contributor

Background

I use the ImageDraw* functions in a slightly unconventional way, and while doing so I noticed that ImageClearBackground is over an order of magnitude slower than simply calling ImageDrawRectangle over the entire image.

Issue

ImageClearBackground calls memcpy once per pixel and doesn’t take advantage of the fact that memcpy is very fast when copying large contiguous blocks of memory. As a result, it incurs the overhead of a function call for every pixel.

Fix

Instead of copying one pixel at a time, we can iteratively copy the data that has already been written to the image buffer, effectively doubling the amount of initialized data with each iteration. This reduces the number of memcpy calls from O(N) to O(log N).

I applied the same optimization to ImageDrawRectangleRec. The improvement there is smaller because only the first row is written pixel-by-pixel.

Result

15-20 times faster execution times on my PC.

Before change:
Image Size: 1024x1024 (1048576 pixels)
--------------------------------------------------------------------------------
  GRAYSCALE                     :  3.615 ms/call,      276.65 MB/s
  GRAY_ALPHA                    :  3.323 ms/call,      601.83 MB/s
  R5G6B5                        :  3.323 ms/call,      601.79 MB/s
  R8G8B8                        :  3.335 ms/call,      899.66 MB/s
  R5G5B5A1                      :  3.324 ms/call,      601.67 MB/s
  R4G4B4A4                      :  3.324 ms/call,      601.67 MB/s
  R8G8B8A8                      :  3.646 ms/call,     1097.08 MB/s
  R32                           :  3.646 ms/call,     1097.15 MB/s
  R32G32B32                     :  3.395 ms/call,     3535.04 MB/s
  R32G32B32A32                  :  3.403 ms/call,     4701.50 MB/s
  R16                           :  3.318 ms/call,      602.84 MB/s
  R16G16B16                     :  3.661 ms/call,     1638.94 MB/s
  R16G16B16A16                  :  3.355 ms/call,     2384.82 MB/s

After change:
Image Size: 1024x1024 (1048576 pixels)
--------------------------------------------------------------------------------
  GRAYSCALE                     :  0.038 ms/call,    26481.94 MB/s
  GRAY_ALPHA                    :  0.074 ms/call,    26984.73 MB/s
  R5G6B5                        :  0.075 ms/call,    26812.89 MB/s
  R8G8B8                        :  0.126 ms/call,    23838.65 MB/s
  R5G5B5A1                      :  0.074 ms/call,    26926.22 MB/s
  R4G4B4A4                      :  0.074 ms/call,    26945.42 MB/s
  R8G8B8A8                      :  0.172 ms/call,    23277.30 MB/s
  R32                           :  0.172 ms/call,    23304.70 MB/s
  R32G32B32                     :  0.492 ms/call,    24401.23 MB/s
  R32G32B32A32                  :  0.715 ms/call,    22390.98 MB/s
  R16                           :  0.074 ms/call,    27102.76 MB/s
  R16G16B16                     :  0.255 ms/call,    23522.38 MB/s
  R16G16B16A16                  :  0.338 ms/call,    23692.66 MB/s

@ChocolateChipKookie ChocolateChipKookie changed the title feat: Optimize ImageClearBackground and ImageDrawRectangleRec with doubling strategy [rtextures] Optimize ImageClearBackground and ImageDrawRectangleRec with doubling strategy Nov 18, 2025
@raysan5 raysan5 merged commit e2233ac into raysan5:master Nov 19, 2025
@raysan5
Copy link
Owner

raysan5 commented Nov 19, 2025

@ChocolateChipKookie Nice improvement! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants