Преобразование массива пикселей в изображение в C # - PullRequest
3 голосов
/ 25 декабря 2008

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

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

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

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

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

Ответы [ 6 ]

6 голосов
/ 25 декабря 2008

Используя 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);
2 голосов
/ 26 декабря 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;
    }
2 голосов
/ 25 декабря 2008

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

1 голос
/ 25 декабря 2008

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

0 голосов
/ 25 декабря 2008

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

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

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

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

0 голосов
/ 25 декабря 2008

Я бы порекомендовал использовать 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;
}
...