Как массив байтов (1 байт на пиксель (изображение в оттенках серого) запихнуть в Bitmap и отобразить в PicterBox? - C#

Узнай цену своей работы

Формулировка задачи:

Здравствуйте! Мне понадобилось каждое входящее изображение переводить в изображение в градациях серого (256 цветов). В

Bitmap

, я так понял, нет такой возможности? В нем только один конструктор принимающий указатель на начало массива байтов, и в этом же конструкторе имеется перечисление PixelFormat, который максимум что принимает подходящие в моем случае, это Format16bppGrayScale и Format8bppIndexed, последний указывает, что массив байтов - индексы на цвета (может можно как-нибудь сделать из этого, что-нибудь подходящие?).

//Вспомогательная структура

    struct Pixel
    {
        public byte R { get; set; }
        public byte G { get; set; }
        public byte B { get; set; }
        public byte A { get; set; }
 
        public Pixel(byte Red, byte Green, byte Blue, byte Alpha) : this()
        {
            R = Red;
            G = Green;
            B = Blue;
            A = Alpha;
        }
    }

//Вспомогательные методы для 24бит на пиксель

        private Pixel GetPixelRGB(int x, int y)
        {
            Pixel pixel = new Pixel();
            int i = ImageData.Stride * y + x * 3;
            pixel.R = RGB[i++];
            pixel.G = RGB[i++];
            pixel.B = RGB[i];
            return pixel;
        }
 
        private void SetPixelRGB(int x, int y, Pixel pixel)
        {
            int i = ImageData.Stride * y + x * 3;
            RGB[i++] = pixel.R;
            RGB[i++] = pixel.G;
            RGB[i] = pixel.B;
        }

// Конвертация изображения в изображение в оттенках серого (Проблема в том,что приходится хранить на каждый //пиксель три одинаковых величины R=G=B=GREY, а хотелось бы одну GREY)

            // Взятие массива байтов изображения
            Bitmap image = new Bitmap(FileName);
            Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);
            ImageData = image.LockBits(rect, ImageLockMode.ReadWrite, image.PixelFormat);
            IntPtr Ptr = ImageData.Scan0;
            int Bytes = ImageData.Stride * image.Height;
            RGB = new byte[Bytes];
            System.Runtime.InteropServices.Marshal.Copy(Ptr, RGB, 0, Bytes);
 
            // Создание изображения на основе массива трех компонент R = G = B = Градации серого.
            Y = new byte[image.Height * ImageData.Stride]; // Массив той же размерности, что и RGB
 
            for (int i = 0; i < image.Height; i++) 
            {
                for (int j = 0; j < image.Width; j++) 
                {
                    Pixel pixel = GetPixelRGB(j, i);
                    byte Grey = (byte)((pixel.R + pixel.G + pixel.B) / 3);
                    pixel.R = Grey;
                    pixel.G = Grey;
                    pixel.B = Grey;
                    SetPixelRGB(j,i,pixel);
                }
            }
 
            System.Runtime.InteropServices.Marshal.Copy(RGB, 0, Ptr, Bytes);
            image.UnlockBits(ImageData);

//Попытка конвертировать изображение в изображение в оттенках серого при помощи нового объекта Bitmap с //указанием нового формата изображения PixelFormat.Format8bppIndexed (Фотка рисуется, но разноцветная, т.к. //Bitmap в данном формате выходит массивом индексов цветов, хотелось бы, чтобы эти индексы представляли //как-нибудь значения серого...)

            Bitmap image = new Bitmap(FileName);
            Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);
            ImageData = image.LockBits(rect, ImageLockMode.ReadWrite, image.PixelFormat);
            IntPtr Ptr = ImageData.Scan0;
            int Bytes = ImageData.Stride * image.Height;
            RGB = new byte[Bytes];
            System.Runtime.InteropServices.Marshal.Copy(Ptr, RGB, 0, Bytes);
            System.Runtime.InteropServices.Marshal.Copy(RGB, 0, Ptr, Bytes);
            image.UnlockBits(ImageData);
 
            Y = new byte[image.Height * image.Width];
 
            for (int i = 0; i < image.Height; i++) 
            {
                for (int j = 0; j < image.Width; j++) 
                {
                    Pixel pixel = GetPixelRGB(j, i);
                    byte Grey = (byte)((pixel.R + pixel.G + pixel.B) / 3);
                    int index = image.Width * i+ j;
                    Y[index] = Grey;
                }
            }
 
//Пришлось и новое пустое изображение загружать/выгружать, т.к. не понял, как устранить ошибку: "Попытка //чтения или записи в защищенную память. Это часто свидетельствует о том, что другая память повреждена."
//при использовании одной лишь строки для создания Bitmap:
//b = new Bitmap(image.Width, image.Height, stride, PixelFormat.Format8bppIndexed, (IntPtr)Y[0]); Как это устранить?
//Без загрузки/разгрузки как показанно ниже?
 
            int stride = image.Width;
            b = new Bitmap(image.Width,image.Height,PixelFormat.Format8bppIndexed);
            Rectangle r = new Rectangle(0, 0, image.Width, image.Height);
            System.Drawing.Imaging.BitmapData imageData = b.LockBits(r, ImageLockMode.ReadWrite, b.PixelFormat);
            IntPtr ptr = imageData.Scan0;
            int bytes = b.Width * b.Height;
            System.Runtime.InteropServices.Marshal.Copy(Y, 0, ptr, bytes);
           b.UnlockBits(imageData);

//Попытка конвертировать изображение в изображение в оттенках серого при помощи объекта Graphics (Проблема в том, что непонятно как нарисованное на picterBox или еще где-нибудь сохранить как изображение куда-нибудь)

            Graphics p = pictureBox1.CreateGraphics();
 
            for (int i = 0; i < image.Height; i++) 
            {
                for (int j = 0; j < image.Width; j++) 
                {
                    Pixel pixel = GetPixelRGB(j, i);
                    byte Grey = (byte)((pixel.R + pixel.G + pixel.B) / 3); // не точная формула, но сойдет.
                    p.DrawLine(new Pen(Color.FromArgb(Grey,Grey,Grey)),new Point(j,i),new Point(j + 1,i + 1));
                }
            }
Фотография вырисовывается, но непонятно,что дальше с этим p делать дальше. Я думал как-нибудь его в сохранить в картинку, но так и не понял как... В общем, хелпппппп!!!

//Попытка конвертировать изображение в изображение в оттенках серого при помощи нового объекта Bitmap с //указанием нового формата изображения Format16bppGrayScale (вообще не рисуется)

1. Y массив byte

           Y = new byte[image.Height * image.Width * 2];
            for (int i = 0; i < image.Height; i++) 
            {
                for (int j = 0; j < image.Width; j++) 
                {
                    Pixel pixel = GetPixelRGB(j, i);
                    byte Grey = (byte)((pixel.R + pixel.G + pixel.B) / 3);
                    int index = image.Width * i+ j *2;
                    Y[index] = Grey;
                    Y[index] = 0;
                }
            }
 
            int stride = image.Width * 2;
            b = new Bitmap(image.Width, image.Height, PixelFormat.Format16bppGrayScale);
//...

2. Y массив unshort

           Y = new unshort[image.Height * image.Width];
            for (int i = 0; i < image.Height; i++) 
            {
                for (int j = 0; j < image.Width; j++) 
                {
                    Pixel pixel = GetPixelRGB(j, i);
                    unshort Grey = (pixel.R + pixel.G + pixel.B) / 3;
                    int index = image.Width * i+ j;
                    Y[index] = Grey;
                }
            }
 
            int stride = image.Width * 2;
            b = new Bitmap(image.Width, image.Height, PixelFormat.Format16bppGrayScale);
//...

Решение задачи: «Как массив байтов (1 байт на пиксель (изображение в оттенках серого) запихнуть в Bitmap и отобразить в PicterBox?»

textual
Листинг программы
              public void Save(BitmapSource image, string filePath) 
        {
 
            using (var filestream = new FileStream(filePath, FileMode.Create)) 
            {
                BitmapEncoder encoder = new JpegBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(image));
                encoder.Save(filestream);
            }
        }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

11   голосов , оценка 4.091 из 5
Похожие ответы