Поясните, как работать с LockBits классом

196
29 мая 2022, 12:00

В своём проекте я использую изображения большого разрешения, из-за чего методы getpixel/setpixel работают очень медленно, то-есть програма лагает, но работает, ошибок нет. Погуглил, что есть много способов их ускорить, но мне они не понятны. Может кто-то предложить способ ускорить работу методов getpixel/setpixel и подробно объяснить его?

    //объявление битмапов
    public static Bitmap myBitmap = new Bitmap("img\\BigMap.png");
    public static Bitmap myBitmapScale1 = new Bitmap("img\\BigMap.png");
    public static Bitmap myBitmapScale2 = new Bitmap("img\\BigMapScale2.png");

   public void pictureBox1_Click(object sender, EventArgs e)
       {
           //получение цвета нажатого пикселя
           MouseEventArgs rato = e as MouseEventArgs;
           int x = rato.X * myBitmap.Width / pictureBox1.ClientSize.Width;
           int y = rato.Y * myBitmap.Height / pictureBox1.ClientSize.Height;
           Color backColor = myBitmap.GetPixel(x, y);
           string hex = backColor.R.ToString("X2") + backColor.G.ToString("X2") + backColor.B.ToString("X2");
         }
//поиск всех пикселей определённого цвета и замена на DarkGray
    private void darkmode_Click(object sender, EventArgs e)
        {
            for (var x = 0; x < myBitmap.Width; x++)
                for (var y = 0; y < myBitmap.Height; y++)
                {
                    var pixel = myBitmap.GetPixel(x, y);
                    if (pixel.R == 176 && pixel.G == 244 && pixel.B == 254)
                        myBitmap.SetPixel(x, y, Color.DarkGray);
 
                }
            
        }
Answer 1

Код скопирован из документации: Bitmap.LockBits Метод, очищен от комментариев и пространств имён. В итоге он становится компактным и понятным.

Единственно, что может потребовать изменения - шаг изменения переменной counter. Если пиксельный формат изображения равен 32bpp (bit per pixel), этот шаг равен 4 байтам. Если формат 24 бита на пиксель, то шаг нужно изменить на 3, соответственно. И т. п.

Как узнать, какой формат у вашего изображения? Смотрите свойство PixelFormat. Например, просто выведите его куда-нибудь: this.Text = myBitmap.PixelFormat.ToString();.
Конечно же, следует предусмотреть в коде изменение шага в зависимости от этого свойства (надеюсь сообразите как добавить if).

private void darkmode_Click(object sender, EventArgs e)
{
    Rectangle rect = new Rectangle(0, 0, myBitmap.Width, myBitmap.Height);
    BitmapData bmpData = myBitmap.LockBits(
        rect, ImageLockMode.ReadWrite, myBitmap.PixelFormat);
    IntPtr ptr = bmpData.Scan0;
    int bytes = Math.Abs(bmpData.Stride) * myBitmap.Height;
    byte[] rgbValues = new byte[bytes];
    Marshal.Copy(ptr, rgbValues, 0, bytes);
    for (int counter = 0; counter < rgbValues.Length; counter += 4)
    {
        if (
            rgbValues[counter] == 254 && // blue
            rgbValues[counter + 1] == 244 && // green
            rgbValues[counter + 2] == 176 // red
            )
        {
            rgbValues[counter] = Color.DarkGray.B;
            rgbValues[counter + 1] = Color.DarkGray.G;
            rgbValues[counter + 2] = Color.DarkGray.R;
        }
    }
    Marshal.Copy(rgbValues, 0, ptr, bytes);
    myBitmap.UnlockBits(bmpData);
}

Используемые пространства имён:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;

Можно ещё ускорить код, используя указатели - это избавит от копирования массива. См. https://ru.stackoverflow.com/a/549857/184217

Также весьма быстрые преобразования цвета позволяет класс ColorMatrix. Обратите на него внимание.

READ ALSO
Создание объекта при помощи Instantiate в update в unity

Создание объекта при помощи Instantiate в update в unity

Делаю игру, столкнулся с проблемой - мне нужно, чтобы объект создался всего один раз при помощи instantiate в void UpdateПробовал использовать bool, но не получилось

244
BmpBitmapEncoder сохранение в 24 битном формате

BmpBitmapEncoder сохранение в 24 битном формате

есть вот такой код, в wpf, выводит изображение и сохраняет его в bmpНо bmp сохраняется в 32-ух битном формате, как можно сохранять в 24х битном?

148
elm.Attribute(&quot;&quot;).Value не равно

elm.Attribute("").Value не равно

Объясните, пожалуйста, почему не работает:

248
вывод данных form data

вывод данных form data

как вытащить значение с form data ? пытаюсь так if ($_POST['r1'] == 1) не получается

231