Подтвердить что ты не робот

PixelFormat.Format32bppArgb, похоже, имеет неправильный порядок байтов

Я пытаюсь получить все значения байтов из Bitmap (System.Drawing.Bitmap). Поэтому я блокирую байты и копирую их:

public static byte[] GetPixels(Bitmap bitmap){
    if(bitmap-PixelFormat.Equals(PixelFormat.Format32.bppArgb)){
        var argbData = new byte[bitmap.Width*bitmap.Height*4];
        var bd = bitmap.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
        System.Runtime.InteropServices.Marshal.Copy(bd.Scan0, argbData, 0, bitmap.Width * bitmap.Height * 4);
        bitmap.UnlockBits(bd);
    }
}

Я тестировал это изображение с очень простым изображением 2x2 PNG с пикселями (красный, зеленый, синий, белый), которые я создал в Photoshop. Из-за формата я ожидал следующие значения в argbData:

255 255   0   0    255 0   255   0 
255 0     0 255    255 255 255 255 

Но я получил:

0     0 255 255     0 255   0 255
255   0   0 255   255 255 255 255

Но это формат BGRA. Кто-нибудь знает, почему байты заменяются? Кстати, когда я использую изображение непосредственно для Image.Source, как показано ниже, изображение отображается правильно. Так в чем моя вина?

<Image Source="D:/tmp/test2.png"/>
4b9b3361

Ответ 1

Пиксельные данные: ARGB, 1 байт для альфа, 1 для красного, 1 для зеленого, 1 для синего. Альфа - самый значительный байт, синий - наименее значимый. На маленькой машине, похожей на вашу и многие другие, маленький конец сохраняется первым, поэтому порядок байтов - bb gg rr aa. Таким образом, 0 0 255 255 равно синему = 0, зеленый = 0, красный = 255, альфа = 255. Это красный цвет.

Эта спецификация порядка endian-ness исчезает, когда вы накладываете bd.Scan0 на int * (указатель на целое число), так как целые числа также хранятся в маленьком конце.

Ответ 3

В формате пикселя Bpp32Argb. Вам не нужно байт-байтовый доступ.

Trun Scan0 в указатель Int32 в небезопасном контексте.

unsafe
{
    var ptr=(int*)bmData.Scan0;
}

Вы можете выполнить некоторую операцию бит, как показано ниже. Для доступа к цветным каналам первого пикселя.

И не нужно заботиться о байтовом порядке.

var a=(ptr[0] & 0xFF000000)>>24;
var r=(ptr[0] & 0x00FF0000)>>16;
var g=(ptr[0] & 0x0000FF00)>>8;
var b=(ptr[0] & 0x000000FF);

Кстати, вы можете легко работать с Color.ToArgb() возвращенным int.