Как массив байтов (1 байт на пиксель (изображение в оттенках серого) запихнуть в Bitmap и отобразить в PicterBox? - C#
Формулировка задачи:
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)); } }
//Попытка конвертировать изображение в изображение в оттенках серого при помощи нового объекта 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?»
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); } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д