Изображение в градациях серого из данных YUV420p - PullRequest
1 голос
/ 30 марта 2010

Из того, что я прочитал в Интернете, значение Y является значением яркости и может использоваться для создания изображения в оттенках серого. Следующая ссылка: http://www.bobpowell.net/grayscale.htm, имеет некоторый код C # для определения яркости растрового изображения:

{
  Bitmap bm = new Bitmap(source.Width,source.Height);
  for(int y=0;y<bm.Height;y++)        public Bitmap ConvertToGrayscale(Bitmap source)
  {
    for(int x=0;x<bm.Width;x++)
    {
      Color c=source.GetPixel(x,y);
      int luma = (int)(c.R*0.3 + c.G*0.59+ c.B*0.11);
      bm.SetPixel(x,y,Color.FromArgb(luma,luma,luma));
    }
  }
  return bm;
}

У меня есть метод, который возвращает значения YUV и имеет данные Y в байтовом массиве. У меня есть текущий фрагмент кода, и он не работает на Marshal.Copy - попытка чтения или записи защищенной памяти.

public Bitmap ConvertToGrayscale2(byte[] yuvData, int width, int height)
        {
            Bitmap bmp;
            IntPtr blue = IntPtr.Zero;

            int inputOffSet = 0;
            long[] pixels = new long[width * height];

            try
            {
                for (int y = 0; y < height; y++)
                {
                    int outputOffSet = y * width;
                    for (int x = 0; x < width; x++)
                    {
                        int grey = yuvData[inputOffSet + x] & 0xff;
                        unchecked
                        {
                            pixels[outputOffSet + x] = UINT_Constant | (grey * INT_Constant);
                        }
                    }

                    inputOffSet += width;
                }

                blue = Marshal.AllocCoTaskMem(pixels.Length);
                Marshal.Copy(pixels, 0, blue, pixels.Length); // fails here : Attempted to read or write protected memory


                bmp = new Bitmap(width, height, width, PixelFormat.Format24bppRgb, blue);

            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                if (blue != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(blue);
                    blue = IntPtr.Zero;
                }

            }

            return bmp;
        }

Любая помощь будет оценена?

Ответы [ 3 ]

2 голосов
/ 30 марта 2010

Я думаю, что вы выделили пиксели. Длина байт , но копируете пиксели. Длина longs , что в 8 раз больше памяти (длина составляет 64 бита или 8 байт размер).

Вы можете попробовать:

blue = Marshal.AllocCoTaskMem(Marshal.SizeOf(pixels[0]) * pixels.Length); 

Вам также может понадобиться использовать int [] для пикселей и PixelFormat.Format32bppRgb в конструкторе Bitmap (так как они оба 32-битные). Использование long [] дает вам 64 бита на пиксель, а это не то, чего ожидает 24-битный формат пикселей.

Вы можете получить оттенки синего вместо серого - зависит от того, каковы ваши значения UINT_Constant и INT_Constant.

Нет необходимости делать "& 0xff", так как yuvData [] уже содержит байт.

1 голос
/ 01 апреля 2010

Вот еще пара подходов, которые вы могли бы попробовать.

0 голосов
/ 01 апреля 2010

Я получаю черное изображение с несколькими пикселями в верхнем левом углу, если я использую этот код, и он работает стабильно:

 public static Bitmap ToGrayscale(byte[] yData, int width, int height)
    {
        Bitmap bm = new Bitmap(width, height, PixelFormat.Format32bppRgb);
        Rectangle dimension = new Rectangle(0, 0, bm.Width, bm.Height);
        BitmapData picData = bm.LockBits(dimension, ImageLockMode.ReadWrite, bm.PixelFormat);
        IntPtr pixelStateAddress = picData.Scan0;

        int stride = 4 * (int)Math.Ceiling(3 * width / 4.0);
        byte[] pixels = new byte[stride * height];

        try
        {
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    byte grey = yData[y * width + x];
                    pixels[y * stride + 3 * x] = grey;
                    pixels[y * stride + 3 * x + 1] = grey;
                    pixels[y * stride + 3 * x + 2] = grey;

                }
            }

            Marshal.Copy(pixels, 0, pixelStateAddress, pixels.Length);
            bm.UnlockBits(picData);
        }
        catch (Exception)
        {
            throw;
        }

        return bm;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...