#c# #performance #bitmap #pixel
#c# #Производительность #растровое изображение #пиксель
Вопрос:
Каков самый быстрый способ получить столбец пикселей из растрового изображения? Я не рассматриваю два цикла, потому что это может занять много времени. Я буду признателен за любую идею. Спасибо!
Комментарии:
1. Вы просто хотите получить массив пикселей для одного столбца в растровом изображении?
2. @ChrisTaylor что угодно, но это должен быть столбец растрового изображения с пикселями, как указано выше 🙂 вау, так быстро
Ответ №1:
Я бы предложил преобразовать ваше растровое изображение в вектор байтов, используя следующий код:
Bitmpa myImage=new Bitmap("myImage.bmp");
BitmapData bmpData1=myImage.LockBits(new Rectangle(0,0,myImage.Width,myImage.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite, myImage.PixelFormat);
byte[] myImageData = new byte[bmpData1.Stride * bmpData1.Height];
System.Runtime.InteropServices.Marshal.Copy(bmpData1.Scan0,myImageData,0
,myImageData.Length);
myImgage.UnlockBits(bmpData1);
Тогда становится легко получить пиксели в нужном столбце. Просто перебирайте вектор myImageData
с шагом, равным количеству пикселей в строках * количеству байтов на пиксель.
Просто будьте осторожны с количеством байтов на пиксель, используемых для представления вашего растрового изображения. Это зависит от PixelFormat
.
Комментарии:
1. когда я перечислил значения всех пикселей, можно ли их изменить и сохранить в новом растровом изображении? я изучил ваш код и понимаю, что marshal.copy сохраняет значения в массив байтов, верно?
2. Я обнаружил, что это возможно, просто измените элементы в массиве байтов, а затем снова используйте marschall copy. Проверьте библиотеку ms
3. Небольшое замечание: в первой строке «Bitmpa» должно быть «Bitmap»
Ответ №2:
Предполагая, что вам нужен только один столбец, следующие процедуры должны вам помочь.
Во-первых, вот стандартное решение, использующее проверяемый код C #
static Color[] GetPixelColumn(Bitmap bmp, int x)
{
Color[] pixelColumn = new Color[bmp.Height];
for (int i = 0; i < bmp.Height; i)
{
pixelColumn[i] = bmp.GetPixel(x, i);
}
return pixelColumn;
}
Вот более быстрая альтернатива, но для этого требуется включить unsafe
поддержку компилятора C #
static Color[] GetPixelColumnFast(Bitmap bmp, int x)
{
Color[] pixelColumn = new Color[bmp.Height];
BitmapData pixelData = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
unsafe
{
int* pData = (int*)pixelData.Scan0.ToPointer();
pData = x;
for (int i = 0; i < bmp.Height; i)
{
pixelColumn[i] = Color.FromArgb(*pData);
pData = bmp.Width;
}
}
bmp.UnlockBits(pixelData);
return pixelColumn;
}
Обе функции вернут цветовой массив с цветами пикселей для определенного столбца в растровом изображении.
Ответ №3:
Преобразуйте его в массив байтов
private static byte[, ,] BitmapToBytes(Bitmap bitmap)
{
BitmapData bitmapData =
bitmap.LockBits(new Rectangle(new Point(), bitmap.Size), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
byte[] bitmapBytes;
var stride = bitmapData.Stride;
try
{
int byteCount = bitmapData.Stride * bitmap.Height;
bitmapBytes = new byte[byteCount];
Marshal.Copy(bitmapData.Scan0, bitmapBytes, 0, byteCount);
}
finally
{
bitmap.UnlockBits(bitmapData);
}
byte[, ,] result = new byte[3, bitmap.Width, bitmap.Height];
for (int k = 0; k < 3; k )
{
for (int i = 0; i < bitmap.Width; i )
{
for (int j = 0; j < bitmap.Height; j )
{
result[k, i, j] = bitmapBytes[j * stride i * 3 k];
}
}
}
return resu<
}
Комментарии:
1. почему я должен использовать stride? Если я хочу сделать два цикла на изображении размером 10×10, результат длины не будет равен 100..
2. Когда я получаю BitmapData, я использую set PixelFormat . Формат24bppRgb, поэтому каждый пиксель использует 24 бита (по 8 бит используется для красного, зеленого и синего компонентов), однако размер строки может быть не кратным размеру пикселя, поскольку для повышения эффективности система упаковала его в строки, которые начинаются с четырехбайтовой границы, а шаг равенширина одной строки пикселей, округленная до границы в четыре байта
3. Я обнаружил ошибку в своем коде:(, я должен использовать BitmapData. Шаг вместо растрового изображения. Ширина * 3, когда я получаю пиксель: результат [k, i, j] = bitmapBytes[j * BitmapData . Шаг i * 3 k];