Home > Back-end >  Win32 C effective storage or creation of bitmaps used for colour picker background
Win32 C effective storage or creation of bitmaps used for colour picker background

Time:01-22

I am writing an HSV colour picker in plain win32 c .

I have a Sat/Val box and a Hue slider exactly like the image on the left here:

enter image description here

Up until now I was just generating the background of the Sat-Val box whenever I needed it.

But now that I have a simple prototype and I am circling around to refactor and clean up I have realized that it actually takes a sizeable amount of time to generate the background bitmap for the sat-val box.

Since scrolling the hue slider should update the sat-val box with the appropriate hue, and it should be responsive and fast, I guess I cannot generate the background on the fly because it's too costly.

I have been using a very simple function like this:

HBITMAP ColorPicker::genSVBackground(uint32_t hue)
{
  uint32_t width = 256;
  uint32_t height = 256;
  HDC hDC = GetDC(hwnd);
  HDC memDC = CreateCompatibleDC(hDC);
  HBITMAP bitmap = CreateCompatibleBitmap(hDC, width, height);
  HGDIOBJ oldObj = SelectObject(memDC, bitmap);
  for (uint32_t y = 0; y < height;   y) {
    for (uint32_t x = 0; x < width;   x) {
      RGBColor rgbCol = hsv_to_rgb(HSVColor(hue, x, 255 - y));
      COLORREF col = (rgbCol.blue << 16) | (rgbCol.green << 8) | (rgbCol.red);
      SetPixel(memDC, x, y, col);
    }
  }
  SelectObject(memDC, oldObj);
  DeleteDC(memDC);
  return bitmap;
}

So the first question is:

Can I make this faster? Fast enough that I can still generate it on the fly? Should I?

And if I cannot make it faster, or if there's really no point and I might as well just use an external resource instead.

What is the best approach to go about storing this in an external resource?

Should I create one giant array that describes a 'cube' of hue x sat x val (my hue, sat and val system is 0-255 each) so I can just load the entire thing into memory and index certain positions to read out an entire background slice?

I know how to do the specifics of the resource storage/loading I'm just not sure if I'm approaching this problem the right way.

Should I store each slice as a separate resource? 256 of them?

Is there a standard way to solving this kind of thing?

CodePudding user response:

I think the source of your slowness is writing one pixel at a time to the memory DC.

Instead of calling SetPixel 256x256 times in a loop, blast an entire matrix of pixels to the DC at once. At the very least, that's 64K function invocations.

I used to do this kind of buffering with GDI all the time. I'd create a Bitmap object and then call the LockBits method on it. Do my rendering directly on the returned pointer, and then UnlockBits. It's been a while since I've done the pure Win32 variations of this, but I'm sure it's possible.

  • Related