更快的算法改变色相/饱和度/亮度位图 [英] Faster algorithm to change Hue/Saturation/Lightness in a bitmap

查看:195
本文介绍了更快的算法改变色相/饱和度/亮度位图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想过滤的位图图像来增加或减少色相,饱和度和亮度值。

I am trying to filter a Bitmap image to increase or decrease Hue, Saturation, and Lightness values.

我的code的工作完美,但它是缓慢

My code is working perfectly, but it is slow.

我锁定两个位图存储器,原始源和当前目的地。用户可以将不同的的TrackBar 控制修改每个值,然后被转换为HSL值。例如,上的TrackBar的值对应于范围-1.0到1.0。

I am locking two bitmaps in memory, the original source and the current destination. The user can move various trackbar controls to modify each value which is then converted to an HSL value. For example, the values on the trackbar correspond to a range of -1.0 to 1.0.

每当一个事件被抛出的的TrackBar值改变,我运行一个函数,它锁定的目标位图和源位应用HSL值,然后将结果存储在目标位图。完成后,我解开了目标位图和绘制图像在屏幕上。

Each time an event is thrown that the trackbar value changed, I run a function which locks the destination bitmap and applies the HSL values with the source bitmap and then stores the result in the destination bitmap. Once finished, I unlock the destination bitmap and paint the image on the screen.

previously我为我的其他过滤器使用的查找表,因为我在做每字节操作。不过,我不知道如何,使用HSL,而不是申请。这里是code我使用的:

Previously I used a lookup table for my other filters since I was doing per-byte operations. However I do not know how to apply that using HSL instead. Here is the code I am using:

byte red, green, blue;

for (int i = 0; i < sourceBytes.Length; i += 3)
{
    blue = sourceBytes[i];
    green = sourceBytes[i + 1];
    red = sourceBytes[i + 2];

    Color newColor = Color.FromArgb(red, green, blue);

    if (ModifyHue)
        newColor = HSL.ModifyHue(newColor, Hue);

    if (ModifySaturation)
        newColor = HSL.ModifySaturation(newColor, Saturation);

    if (ModifyLightness)
        newColor = HSL.ModifyBrightness(newColor, Lightness);

    destBytes[i] = newColor.B;
    destBytes[i + 1] = newColor.G;
    destBytes[i + 2] = newColor.R;
}

这是我的ModifyBrightness功能:

And here's my ModifyBrightness function:

public static Color ModifyBrightness(Color color, double brightness)
{
    HSL hsl = FromRGB(color);
    hsl.L *= brightness;
    return hsl.ToRGB();
}

因此​​,基本上,如果它们的亮度滑块在正中央,它的价值将是0,我将转换为1.0当我将它传递给函数,因此它被乘以1.0的亮度,这意味着它不会更改。如果他们一路拖动滑块向右则其值为100,这将导致2.0修改器,所以我会以2.0乘以亮度值加倍。

So basically if their brightness slider is in the very middle, its value will be 0 which I will convert to "1.0" when I pass it in to the function, so it multiplies the brightness by 1.0 which means it won't change. If they drag the slider all the way to the right it will have a value of 100 which will result in a modifier of 2.0, so I'll multiply the lightness value by 2.0 to double it.

推荐答案

我结束了研究ImageAttributes和嘉洛斯,发现性能优良。

I ended up researching ImageAttributes and ColorMatrix and found the performance was excellent.

下面是我是如何实现它的饱和度和亮度过滤器:

Here is how I implemented it for a Saturation and Brightness filter:

// Luminance vector for linear RGB
const float rwgt = 0.3086f;
const float gwgt = 0.6094f;
const float bwgt = 0.0820f;

private ImageAttributes imageAttributes = new ImageAttributes();
private ColorMatrix colorMatrix = new ColorMatrix();
private float saturation = 1.0f;
private float brightness = 1.0f;

protected override void OnPaint(object sender, PaintEventArgs e)
{
    base.OnPaint(sender, e);

    e.Graphics.DrawImage(_bitmap, BitmapRect, BitmapRect.X, BitmapRect.Y, BitmapRect.Width, BitmapRect.Height, GraphicsUnit.Pixel, imageAttributes);
}

private void saturationTrackBar_ValueChanged(object sender, EventArgs e)
{
    saturation = 1f - (saturationTrackBar.Value / 100f);

    float baseSat = 1.0f - saturation;

    colorMatrix[0, 0] = baseSat * rwgt + saturation;
    colorMatrix[0, 1] = baseSat * rwgt;
    colorMatrix[0, 2] = baseSat * rwgt;
    colorMatrix[1, 0] = baseSat * gwgt;
    colorMatrix[1, 1] = baseSat * gwgt + saturation;
    colorMatrix[1, 2] = baseSat * gwgt;
    colorMatrix[2, 0] = baseSat * bwgt;
    colorMatrix[2, 1] = baseSat * bwgt;
    colorMatrix[2, 2] = baseSat * bwgt + saturation;

    imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

    Invalidate();
}

private void brightnessTrackBar_ValueChanged(object sender, EventArgs e)
{
    brightness = 1f + (brightnessTrackBar.Value / 100f);

    float adjustedBrightness = brightness - 1f;

    colorMatrix[4, 0] = adjustedBrightness;
    colorMatrix[4, 1] = adjustedBrightness;
    colorMatrix[4, 2] = adjustedBrightness;

    imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

    Invalidate();
}

这篇关于更快的算法改变色相/饱和度/亮度位图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆