5
votes

I have been experimenting with the Change HUE/Saturation example found on the EFG website: http://www.efg2.com/Lab/Library/Delphi/Graphics/Color.htm

enter image description here

I want to use the techniques found in that example to change the color values of some bitmaps (to be used on a TImage). There is one problem I am facing, and that is with TImages that have transparent bitmaps; I don't want the background color to change its HUE but rather just the actual image data.

Take this sample image we can work with (though any image with transparency can be used):

enter image description here

  • Download the Change HUE/Saturation demo from the link at the top.
  • Now Load the button image above into the ImageOriginal.
  • Set the Delta Saturation to 1.
  • Run the Project.

Some output results:

enter image description hereenter image description here

What I would like to happen here is keep the original background color (defined by the bottom left most pixel) and only adjust the hue for the rest of the image. So, the output results would actually look like this (edited in Paint.NET):

enter image description hereenter image description here

Allow me to use another sample image to test with that contains more image data:

enter image description here

As before with the first image sample, the results could be something like:

enter image description hereenter image description here

When the results I desire should be like so:

enter image description hereenter image description here

One idea I had was after the HUE change, replace the bottom left most color with the color from the original, but I am not sure if this is the correct approach or not, and even if it is I am not sure how to replace color X for another color. (Graphics and Math is beyond me).

For example, if I drew two blue color circles on Mickey's ear (the blue been the original transparent color from bottom left most pixel) and also colored his eyes:

enter image description here

Changing the HUE again may look like:

enter image description here

when in fact it should like this:

enter image description here

Simply put I would like to change the HUE of an image whether it be by the methods used from the EFG demo or another solution. The transparent color as defined by the bottom most left pixel should not be changed when the HUE is changed, this should remain the same as demonstrated in the sample images.

How can I change the HUE of a bitmap whilst retaining the background color?

2

2 Answers

5
votes

The code you refer walks all pixels on the image to change hue/saturation. You can modify the code so that it does not interfere if a pixel has a specific color:

PROCEDURE TFormChangeHS.UpdateBitmap;
    ..
    S              :  TReal;
    V              :  TReal;

    FixColor: TRGBTriple;                            // New variable
BEGIN
  DeltaSaturation := SpinEditDeltaSaturation.Value;
  NewHue := TrackBarHue.Position;

  Bitmap := TBitmap.Create;
  TRY
    Bitmap.Width  := ImageOriginal.Width;
    Bitmap.Height := ImageOriginal.Height;
    Bitmap.PixelFormat := ImageOriginal.Picture.Bitmap.PixelFormat;
    ASSERT(Bitmap.PixelFormat = pf24bit);

    // save bottom left color
    FixColor := PRGBTripleArray(
                  ImageOriginal.Picture.Bitmap.ScanLine[Bitmap.Height - 1])^[0];
    //--

    FOR j := 0 TO Bitmap.Height-1 DO
    BEGIN
      RowIn  := ImageOriginal.Picture.Bitmap.Scanline[j];
      RowOut := Bitmap.Scanline[j];
      FOR i := 0 TO Bitmap.Width-1 DO
      BEGIN
        WITH RowIn[i] DO
        BEGIN

          // copy the color to target and continue with next iteration
          if (RowIn[i].rgbtBlue = FixColor.rgbtBlue) and
              (RowIn[i].rgbtGreen = FixColor.rgbtGreen) and
              (RowIn[i].rgbtRed = FixColor.rgbtRed) then begin
            RowOut[i] := FixColor;
            Continue;
          end;
          //--

          // convert pixel coordinates to HSV
          RGBtoHSV(rgbtRed, rgbtGreen, rgbtBlue, H, S, V);
        END;
        ..
        ..


Output:  

enter code here

2
votes

In theory, you can for example:

First, you have to determine what is the background... (probably picking the color of a specific pixel like delphi does...)

Then, with this background color, you can create a mask based on this color...

You duplicate the image... apply the hue...

You merge your 2 bitmaps using the mask...