Преобразовать изображение в оттенки серого - PullRequest
52 голосов
/ 15 февраля 2010

Существует ли способ преобразования изображения в 16-битный формат изображения в оттенках серого вместо настройки яркости каждого из компонентов r, g и b.В настоящее время у меня есть bmp из файла.

Bitmap c = new Bitmap("filename");

Я хочу растровое изображение d, то есть версию c в оттенках серого.Я вижу конструктор, который включает System.Drawing.Imaging.PixelFormat, но я не понимаю, как это использовать.Я новичок в области обработки изображений и соответствующих библиотек C #, но имею небольшой опыт работы с самим C #.

Любая помощь, ссылки на онлайн-источники, советы или предложения будут оценены.

РЕДАКТИРОВАТЬ: d - это версия c.

в оттенках серого.

Ответы [ 6 ]

65 голосов
/ 15 февраля 2010

"Я хочу растровое изображение d, то есть шкалу серого. Я вижу подрядчик, который включает в себя System.Drawing.Imaging.PixelFormat, но я не понимаю, как использовать это. "

Вот как это сделать

Bitmap grayScaleBP = new 
         System.Drawing.Bitmap(2, 2, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);

РЕДАКТИРОВАТЬ: Для преобразования в Оттенки серого

             Bitmap c = new Bitmap("fromFile");
             Bitmap d;
             int x, y;

             // Loop through the images pixels to reset color.
             for (x = 0; x < c.Width; x++)
             {
                 for (y = 0; y < c.Height; y++)
                 {
                     Color pixelColor = c.GetPixel(x, y);
                     Color newColor = Color.FromArgb(pixelColor.R, 0, 0);
                     c.SetPixel(x, y, newColor); // Now greyscale
                 }
             }
            d = c;   // d is grayscale version of c  

Быстрая версия от switchonthecode перейдите по ссылке для полного анализа:

public static Bitmap MakeGrayscale3(Bitmap original)
{
   //create a blank bitmap the same size as original
   Bitmap newBitmap = new Bitmap(original.Width, original.Height);

   //get a graphics object from the new image
   Graphics g = Graphics.FromImage(newBitmap);

   //create the grayscale ColorMatrix
   ColorMatrix colorMatrix = new ColorMatrix(
      new float[][] 
      {
         new float[] {.3f, .3f, .3f, 0, 0},
         new float[] {.59f, .59f, .59f, 0, 0},
         new float[] {.11f, .11f, .11f, 0, 0},
         new float[] {0, 0, 0, 1, 0},
         new float[] {0, 0, 0, 0, 1}
      });

   //create some image attributes
   ImageAttributes attributes = new ImageAttributes();

   //set the color matrix attribute
   attributes.SetColorMatrix(colorMatrix);

   //draw the original image on the new image
   //using the grayscale color matrix
   g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
      0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);

   //dispose the Graphics object
   g.Dispose();
   return newBitmap;
}
34 голосов
/ 23 октября 2010
Bitmap d = new Bitmap(c.Width, c.Height);

for (int i = 0; i < c.Width; i++)
{
    for (int x = 0; x < c.Height; x++)
    {
        Color oc = c.GetPixel(i, x);
        int grayScale = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11));
        Color nc = Color.FromArgb(oc.A, grayScale, grayScale, grayScale);
        d.SetPixel(i, x, nc);
    }
}

Таким образом, он также сохраняет альфа-канал.
Наслаждайтесь.

17 голосов
/ 29 сентября 2015

В классе ToolStripRenderer есть статический метод с именем CreateDisabledImage. Его использование так же просто, как:

Bitmap c = new Bitmap("filename");
Image d = ToolStripRenderer.CreateDisabledImage(c);

Используется немного другая матрица, чем в принятом ответе, и дополнительно умножает ее на прозрачность значения 0,7, так что эффект немного отличается от просто оттенков серого, но если вы хотите просто сделать изображение серым, самое простое и лучшее решение.

6 голосов
/ 17 августа 2011

Подводя итог нескольким пунктам здесь: Есть несколько попиксельных опций, которые просты, но не быстрые.

@ Комментарий Луиса, ссылающийся на: (в архиве) https://web.archive.org/web/20110827032809/http://www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-grayscale превосходно.

Он запускает три разных варианта и включает в себя время для каждого.

6 голосов
/ 23 апреля 2011

Ни один из приведенных выше примеров не создает 8-битные (8 бит / с) растровые изображения. Некоторые программы, такие как обработка изображений, поддерживают только 8bpp. К сожалению, библиотеки MS .NET не имеют решения. Формат PixelFormat.Format8bppIndexed выглядит многообещающе, но после многих попыток я не смог заставить его работать.

Чтобы создать настоящий 8-битный растровый файл, вам нужно создать правильные заголовки . В конечном итоге я нашел решение Библиотека градаций серого для создания файлов 8-битных растровых изображений (BMP). Код очень прост:

Image image = Image.FromFile("c:/path/to/image.jpg");
GrayBMP_File.CreateGrayBitmapFile(image, "c:/path/to/8bpp/image.bmp");

Код для этого проекта далеко не симпатичен, но он работает, с одной небольшой проблемой, которую легко исправить. Автор жестко закодировал разрешение изображения до 10х10. Программы обработки изображений не любят это. Это исправление, откройте GrayBMP_File.cs (да, я знаю, что вы называете это странным именем файла) и замените строки 50 и 51 на код ниже. В примере устанавливается разрешение 200x200, но вы должны изменить его на правильный номер.

int resX = 200;
int resY = 200;
// horizontal resolution
Copy_to_Index(DIB_header, BitConverter.GetBytes(resX * 100), 24);
// vertical resolution 
Copy_to_Index(DIB_header, BitConverter.GetBytes(resY * 100), 28);
5 голосов
/ 22 января 2015

Код ниже является самым простым решением:

Bitmap bt = new Bitmap("imageFilePath");

for (int y = 0; y < bt.Height; y++)
{
    for (int x = 0; x < bt.Width; x++)
    {
        Color c = bt.GetPixel(x, y);

        int r = c.R;
        int g = c.G;
        int b = c.B;
        int avg = (r + g + b) / 3;
        bt.SetPixel(x, y, Color.FromArgb(avg,avg,avg));
    }   
}

bt.Save("d:\\out.bmp");
...