В своём проекте я использую изображения большого разрешения, из-за чего методы 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);
}
}
Код скопирован из документации: 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. Обратите на него внимание.
Делаю игру, столкнулся с проблемой - мне нужно, чтобы объект создался всего один раз при помощи instantiate в void UpdateПробовал использовать bool, но не получилось
есть вот такой код, в wpf, выводит изображение и сохраняет его в bmpНо bmp сохраняется в 32-ух битном формате, как можно сохранять в 24х битном?
как вытащить значение с form data ? пытаюсь так if ($_POST['r1'] == 1) не получается