开发者

Faster method of changing an image hue?

Is there a better method to change the hue of an image smoothly as I slide through a trackbar? What I'm doing is getting the RGB value per pixel, calculating the saturation and brightness then putting the values in. The size of the image affects the speed the hue is updated. Photoshop's image hue function changes the hue from 0 to 360 smoothly which is what I want to try and get to.

data = editImage.LockBits(new Rectangle(0, 0, editWidth, editHeight), 
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
byte* dataPtr = (byte*)data.Scan0;
h = track开发者_JAVA技巧Bar1.Value / 60.0;
D = 1 - Math.Abs((h % 2) - 1);

if (h >= 0 && h < 1)
{
    for (int i = 0; i < editHeight; i++)
    {
        offsetStride = i * data.Stride;
        for (int j = 0; j < editWidth; j++)
        {
            blue = dataPtr[(j * 3) + offsetStride];
            green = dataPtr[(j * 3) + offsetStride + 1];
            red = dataPtr[(j * 3) + offsetStride + 2];

            if (green > blue) max = green;
            else max = blue;
            if (red > max) max = red;

            if (green < blue) min = green;
            else min = blue;
            if (red < min) min = red;

            s = (max == 0) ? 0 : 1d - (1d * min / max);
            v = max / 255d;

            C = v * s;
            X = C * D;
            E = v - C;

            dataPtr[(j * 3) + offsetStride] = (byte)(min);
            dataPtr[(j * 3) + offsetStride + 1] = (byte)((X + E) * 255);
            dataPtr[(j * 3) + offsetStride + 2] = (byte)(max);
        }
    }
}


If you want a monochrome image that changes hue then the most efficient method would be to generate red, yellow, green, cyan, blue and magenta images and interpolate between them as necessary.

So to generate an image at 10% rotation you would add 50/60 * red + 10/60 * yellow and display that.

In fact, you don't really need to generate all 6 images. It would be enough to generate the red and yellow images. The others you can generate on the fly, because, for example, the blue image is just the red image, but with the red and blue pixels swapped (and you could even derive the yellow from the red). But it's perhaps simplest to start with 6 images and then add that optimisation later.

The code to generate one of the initial coloured images is similar to what you have above (at first glance), but your final step from HSV to RGB looks a little suspect - the wikipedia pages are good at explaining this (and it's possible C# contains a library function to do this conversion).

[Given your clarification, below is not relevant to what you are doing]

If you want to shift the hue, pixel by pixel (so reds move to yellow as greens move to cyan) then you would save some time by first converting the entire image to HSV, and then working from that.

You might save more time (when shifting hue) by generating multiple images (say every 10 degrees rotated in hue) and then interpolating between them. But it's more complex than the monochrome case, because some pixels (those for which hue moves through a multiple of 60 degrees during the interpolation) need special treatment. So you also need to pre-detect those and then calculate them on the fly. There's a trade-off, in that the more intermediate images you have, the less pixels you need to special-case. And in practice generating the separate images lazily (on demand) is going to give quicker startup, because typically people only make small changes.


You could try using a lookup table to get rid of the calculation of 's', since min and max can only range from 0 to 255. So you'd have s = getS(min, max). The values of C and E could probably also be held in this table (but it's late and I haven't looked that hard).

Each element of the getS table would be precomputed like

for (int min = 0; min < 255; min++)
{
    for (int max = 0; max < 255; max++)
    {
        tableS[min, max] = (max == 0) ? 0 : 1d - (1d * min / max);
    }
}

Photoshop's code is probably written in assembler too to get maximum performance.

In order to see if this will have much effect you could comment out all the Hue calculation code and see how it performs just by copying fake data. If it's as zippy as Photoshop then you know these calculations are your bottleneck.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜