Преобразование массива пикселей в изображение на С#

У меня есть массив из int пикселей в моей программе на С#, и я хочу преобразовать его в изображение. Проблема в том, что я конвертирую исходный код Java для программы в эквивалентный код С#. В java строка читает, которая отображает массив целых пикселей в изображение:

Image output = createImage(new MemoryImageSource(width, height, orig, 0, width));

может ли кто-нибудь сказать мне эквивалент C#?

Здесь orig — это массив из int пикселей. Я искал класс Bitmap, и есть метод с именем SetPixel, но проблема в том, что он принимает номер координаты x, y. Но в моем коде есть массив из int пикселей. Еще одна странность заключается в том, что мой исходный массив имеет отрицательное число, и они далеки от 255. В Java это тот же случай (это означает, что массив в C # и Java имеют эквивалентное значение), и значения отлично работают в Java.

Но я не могу перевести эту строку на С#. Пожалуйста помоги.


person Community    schedule 24.12.2008    source источник
comment
Отрицательные значения, вероятно, связаны с тем, что значения int должны быть беззнаковыми. Ничего страшного, если они подписаны, но неподписанные имели бы больше смысла.   -  person Vilx-    schedule 25.12.2008


Ответы (6)


Используя WPF, вы можете создать растровое изображение (изображение) прямо из вашего массива. Затем вы можете закодировать это изображение или отобразить его или поиграть с ним:

int width = 200;
int height = 200;

//
// Here is the pixel format of your data, set it to the proper value for your data
//
PixelFormat pf = PixelFormats.Bgr32;
int rawStride = (width * pf.BitsPerPixel + 7) / 8;

//
// Here is your raw data
//
int[] rawImage = new int[rawStride * height / 4];


//
// Create the BitmapSource
//
BitmapSource bitmap = BitmapSource.Create(
    width, height,
    96, 96, pf, null,
    rawImage, rawStride);
person Frank Krueger    schedule 24.12.2008
comment
Я искал это, и я дурачился со значением rawstride. Ваш код сработал для меня как шарм .. Спасибо ... +1 :) - person K Singh; 14.06.2011
comment
Откуда 7 и 8 в (width * pf.BitsPerPixel + 7) / 8? - person Ryan Amos; 17.07.2012

Вы можете использовать Bitmap.LockBits для получения растровых данных, которые вы можете затем манипулируйте напрямую, а не через SetPixel. (Как использовать LockBits)

person mackenir    schedule 24.12.2008
comment
+1. Если вам нужно обработать всю картинку, то SetPixel/GetPixel работают МЕДЛЕННО. - person Vilx-; 25.12.2008

Мне нравится уже представленный вариант WPF, но здесь он использует LockBits и Bitmap:

        // get the raw image data
        int width, height;
        int[] data = GetData(out width, out height);

        // create a bitmap and manipulate it
        Bitmap bmp = new Bitmap(width,height, PixelFormat.Format32bppArgb);
        BitmapData bits = bmp.LockBits(new Rectangle(0, 0, width, height),
            ImageLockMode.ReadWrite, bmp.PixelFormat);
        unsafe
        {
            for (int y = 0; y < height; y++)
            {
                int* row = (int*)((byte*)bits.Scan0 + (y * bits.Stride));
                for (int x = 0; x < width; x++)
                {
                    row[x] = data[y * width + x];
                }
            }
        }
        bmp.UnlockBits(bits);

С (в качестве тестовых данных):

    public static int[] GetData(out int width, out int height)
    {
        // diagonal gradient over a rectangle
        width = 127;
        height = 128;
        int[] data =  new int[width * height];
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                int val = x + y;
                data[y * width + x] = 0xFF << 24 | (val << 16) | (val << 8) | val;
            }
        }
        return data;
    }
person Marc Gravell    schedule 26.12.2008

Ну, я предполагаю, что каждое целое является составным значением ARGB? Если нет простого варианта, тогда LockBits стоит посмотреть - это будет намного быстрее, чем SetPixel, но сложнее. Вам также нужно убедиться, что вы знаете, как составлено целое число (ARGB? RGBA?). Попробую посмотреть, есть ли более очевидный вариант...

person Marc Gravell    schedule 24.12.2008

Конструктор MemoryImageSource 3-й аргумент представляет собой массив целых чисел, состоящий из значений argb в указанном порядке.

Пример на этой странице создает такой массив с помощью;

pix[index++] = (255 << 24) | (red << 16) | blue;

Вам нужно разложить этот целочисленный массив на массив байтов (был бы полезен оператор сдвига), но он должен быть в порядке bgr, чтобы метод LockBits работал.

person tafa    schedule 24.12.2008
comment
Ваша ссылка кажется мертвой. - person starbeamrainbowlabs; 17.03.2016

Я бы рекомендовал использовать LockBits, но более медленный алгоритм на основе SetPixel может выглядеть примерно так:


// width - how many int's per row        
// array - array of integers
Bitmap createImage(int width, int[] array)
{            
  int height = array.Length / width;
  Bitmap bmp = new Bitmap(width, height);
  for (int y = 0; y < height; y++)
  {
    for (int x = 0; x < array.Length; x += width)
    {
      bmp.SetPixel(x, y, Color.FromArgb(array[i]));
    }
  }
  return bmp;
}
person user21826    schedule 24.12.2008