Как использовать ползунок для регулировки яркости растрового изображения?

Я пытаюсь настроить значения RGB, чтобы существенно затемнить или осветлить изображение в моем проекте процессора изображений. Было бы неплохо включить как затемнение, так и осветление в один элемент управления TrackBar, при этом нейтральное, неизменное изображение будет, когда ползунок установлен на 0 посередине.
Однако в настоящее время я все еще пытаюсь понять, как это сделать. только одна функция, например затемнение, на одном трекбаре.

После добавления элемента управления TrackBar (Min 0, Max 10) в свой проект я использую событие trackbar_scroll, чтобы определить, когда прокручивается TrackBar.
Я также закодировал его для затемнения изображения, вычитая определенное значение байта из RGB каждого пикселя image.
Полоса прокрутки успешно затемняет изображение, когда вы перемещаете его вправо, однако я хочу также отменить его затемнение, когда вы перемещаете TrackBar влево, возвращая его в исходное положение.

private void trbBrightness_Scroll(object sender, EventArgs e)
{
    if (bitmapImage == null) return; 

    Byte Red, Green, Blue;
    int iWidth = 320;
    int iHeight = 240;

    for (int i = 0; i < iWidth; i++)
    {
        for (int j = 0; j < iHeight; j++)
        {
            Color pixel = ImageArray[i, j];

            Red = pixel.R;
            Green = pixel.G;
            Blue = pixel.B;

            Color newColor = 
                Color.FromArgb(255, 
                               Red - Convert.ToByte(Red * (trbBrightness.Value * 0.1)), 
                               Green - Convert.ToByte(Green * (trbBrightness.Value * 0.1)), 
                               Blue - Convert.ToByte(Blue * (trbBrightness.Value * 0.1)));
            ImageArray[i, j] = newColor;

Прямо сейчас он просто затемняет изображение, как я этого хочу, однако я ожидаю, что при сдвиге влево ползунок в основном отменяет затемнение, когда вы перемещаете его вправо.

Есть ли способ определить, когда значение ползунка увеличивается, сделать это, а когда значение ползунка уменьшается, сделать это?
Я предполагаю, что мне нужно каким-то образом сохранить старое значение трекбара, чтобы я мог сравнить с новым?


где я могу получить:

if (trackbar value is increasing) 
{

} 
else if (trackbar value is decreasing)
{

}

person Community    schedule 12.04.2019    source источник
comment
Вы уменьшаете на процентную величину, поэтому для отмены изменения потребуется большее число. Если у вас есть 100 яблок и вы теряете 20%, у вас осталось 80 яблок. Если вы увеличите на 20%, у вас будет 96. Ваши 80 яблок нужно увеличить на 25%, чтобы вернуться к исходным значениям.   -  person Ňɏssa Pøngjǣrdenlarp    schedule 13.04.2019
comment
@MakeStackOverflowGoodAgain Это имеет смысл, но куда бы я это поместил? Мы бы хотели, чтобы добавление происходило только в том случае, если значение ползунка уменьшается, так как же мне обнаружить это?   -  person    schedule 13.04.2019
comment
Не используйте свойство Image, вместо этого используйте событие Paint. Нарисуйте растровое изображение с помощью e.Graphics.DrawImage(), используя ColorMatrix для настройки яркости. Вызовите его метод Invalidate(), когда значение полосы прокрутки изменится, и Paint снова запустится. Ключевое отличие, помимо значительного повышения эффективности, заключается в том, что вы всегда сохраняете исходное растровое изображение.   -  person Hans Passant    schedule 13.04.2019


Ответы (1)


Вам просто нужно сохранить исходное растровое изображение в безопасности и применить ColorMatrix в исходное растровое изображение ImageAttributes при корректировке значений.
Конечно, вы не корректируете то, что уже было настроено, иначе вы никогда не вернетесь к исходным значениям яркости/контрастности исходного растрового изображения.
Установите новые значения в исходное растровое изображение, затем отобразите только результаты, сохранив оригинал.

Для компонента "Контрастность" можно установить значение в диапазоне от -1.00f до 2.00f.
Когда значения контрастности опускаются ниже 0, вы инвертируете цвета, создавая негатив. Вам нужно решить, позволяете ли вы такое поведение. В противном случае вы можете ограничить контраст до минимума 0.00f: применительно ко всем цветовым компонентам создается серая клякса (полностью отсутствует контраст).

Значения компонента «Яркость» могут быть установлены в диапазоне от -1.00f до +1.00f. Выше и ниже у вас есть полностью белые и полностью черные результаты.

Используя Матрицу идентичности в качестве эталона:

C = Contrast = 1 : B = Brightness = 0

    C, 0, 0, 0, 0        1, 0, 0, 0, 0
    0, C, 0, 0, 0        0, 1, 0, 0, 0
    0, 0, C, 0, 0        0, 0, 1, 0, 0
    0, 0, 0, 1, 0        0, 0, 0, 1, 0
    B, B, B, 1, 1        0, 0, 0, 1, 1

(Если вы привыкли к математическому определению Matrix или тому, как его определяют другие платформы, вы можете подумать, что это неправильно. Именно так ColorMatrix определяется в .Net/GDI диалект).

Пример кода, необходимого для настройки яркости и контрастности растрового изображения с использованием ColorMatrix и стандартного элемента управления PictureBox для представления результатов.

Пример результата:

Настройка яркости и контрастности растрового изображения

Процедура:
Назначьте изображение элементу управления PictureBox, затем назначьте то же изображение объекту Bitmap, здесь поле с именем adjustBitmap:

Bitmap adjustBitmap = null; 

Где-нибудь (возможно, Form.Load()) назначьте изображение PicureBox и копию того же изображения в поле adjustBitmap, что сохранит исходные значения цвета изображения.
Примечание: Dispose() из adjustBitmap при закрытии формы (Form.FormClosed) событие.

Добавьте 2 элемента управления TrackBar: один для настройки яркости и один для контраста (здесь они называются trkContrast и trkBrightness).

Полоса управления Яркость будет иметь: Minimum = -100, Maximum = 100, Value = 0
Полоса управления Контрастность будет иметь: Minimum = -100, Maximum = 200, Value = 100

Подпишитесь на один и тот же обработчик события Scroll и назначьте его обоим.
Код обработчика вызывает метод, отвечающий за настройку яркости и контрастности растрового изображения, используя текущие значения двух элементов управления TrackBar. и ссылка на исходное растровое изображение:

// Somewhere... assign the Bitmap to be altered to the Field
adjustBitmap = [Some Bitmap];
// Use a copy of the above as the PictureBox image
pictureBox1.Image = [A copy of the above];

private void trackBar_Scroll(object sender, EventArgs e)
{
    pictureBox1.Image?.Dispose();
    pictureBox1.Image = AdjustBrightnessContrast(adjustBitmap, trkContrast.Value, trkBrightness.Value);
}

Основной метод преобразует int значения TrackBars в числа с плавающей запятой в диапазонах, описанных ранее, и присваивает их массиву Matrix:
Новый ColorMatrix назначается ImageAttribute. strong>, который используется в качестве параметра в Graphics.DrawImage, которая принимает ImageAttribute.

public Bitmap AdjustBrightnessContrast(Image image, int contrastValue, int brightnessValue)
{
    float brightness = -(brightnessValue / 100.0f);
    float contrast = contrastValue / 100.0f;
    var bitmap = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb));

    using (var g = Graphics.FromImage(bitmap))
    using (var attributes = new ImageAttributes())
    {
        float[][] matrix = {
            new float[] { contrast, 0, 0, 0, 0},
            new float[] {0, contrast, 0, 0, 0},
            new float[] {0, 0, contrast, 0, 0},
            new float[] {0, 0, 0, 1, 0},
            new float[] {brightness, brightness, brightness, 1, 1}
        };

        ColorMatrix colorMatrix = new ColorMatrix(matrix);
        attributes.SetColorMatrix(colorMatrix);
        g.DrawImage(image, new Rectangle(0, 0, bitmap.Width, bitmap.Height),
            0, 0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel, attributes);
        return bitmap;
    }
}
person Jimi    schedule 13.04.2019
comment
Спасибо за решение. Я получаю утечку памяти при реализации этого. Каждый раз, когда я делаю корректировку, использование моей памяти увеличивается, несмотря на операторы использования. Вы тоже это видите? - person user2188329; 07.07.2020
comment
@ user2188329 Вы совершенно правы! Я корректировал код прямо здесь. Плохая ошибка. Спасибо, что заметили. Я добавил пару заметок и исправил код. - person Jimi; 07.07.2020