如何更改方法以便在黑色背景上创建白色的位图图像?

时间:2017-10-29 01:58:42

标签: c# .net winforms

在构造函数

Bitmap bitmap = new Bitmap(@"I:\test\Untitled3.jpg"););
Bitmap GrayScaleBitmap = GrayScale(bitmap);

方法GrayScale:

private Bitmap GrayScale(Bitmap bmp)
    {
        //get image dimension
        int width = bmp.Width;
        int height = bmp.Height;

        //color of pixel
        System.Drawing.Color p;

        //grayscale
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                //get pixel value
                p = bmp.GetPixel(x, y);

                //extract pixel component ARGB
                int a = p.A;
                int r = p.R;
                int g = p.G;
                int b = p.B;

                //find average
                int avg = (r + g + b) / 3;

                //set new pixel value
                bmp.SetPixel(x, y, System.Drawing.Color.FromArgb(a, avg, avg, avg));
            }
        }

        return bmp;
    }

这是我在油漆测试中所做的原始图像:

我得到的结果是GrayScale:

红色的形状现在在白色背景上是黑色的。 但我希望红色的形状在黑色背景上是白色的,这就是我不确定如何在GrayScale方法中进行更改。

2 个答案:

答案 0 :(得分:0)

你正在做的事情对于灰度来说是正确的。

你想要的是灰度和反转的组合。

鉴于RGB以[0 - 255]的比例运行,您需要使用它来反转当前颜色。我建议进行以下更改;

int avg = 255 - ((r + g +b) / 3)

哪个应该实现你所追求的目标。

说明为什么会起作用;
白色是255,255,255 黑色是0,0,0

所以255 - ((255 + 255 + 255)/ 3)= 0(即白色变黑)。

答案 1 :(得分:0)

  

我希望背景为白色,并且我绘制的形状为黑色。

要实现此目的,请将avg(灰度)值转换为0/1并乘以255.

//find white-black value
int bw = (r + g + b) / 384; // or /3 / 128 if you prefer
//set new pixel value
bmp.SetPixel(x, y, System.Drawing.Color.FromArgb(a, bw*255, bw*255, bw*255));

它为您提供纯黑白图像:

enter image description here

  

即使我在黄色背景上绘制了一个棕色的形状   结果应该是白色背景上的黑色形状。

我建议的方法涵盖了这个要求,但是某些&#34; threshold&#34; (就像在Photoshop中一样)是某些色调所必需的。

int threshold = 128; // [1-254]
//find avg value [0-255]
int wb = (r + g + b) / 3;
//transform avg to [0-1] using threshold
wb = (wb >= threshold) ? 1 : 0;
//set new pixel value
bmp.SetPixel(x, y, System.Drawing.Color.FromArgb(a, wb*255, wb * 255, wb * 255));

如果阈值太小,您的结果将全部为白色,或者如果阈值太大则全黑。在临界情况下,您也可能会出现扭曲的形状/背景(类似于色调/阈值不适合时的图像编辑器)。值128均匀地分隔颜色空间(正如我原来的算法所做的那样)。

阈值过低的一些示例:

答:使用阈值70,输入棕色为黄色。

enter image description here

B:使用阈值60,输入棕色为黄色 enter image description here

完整源代码:

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;    

namespace BwImgSO
{
    class Program
    {
        static void Main(string[] args)
        {
            Bitmap bitmap = new Bitmap(@"C: \Users\me\Desktop\color.jpg");
            Bitmap grayScaleBitmap = GrayScale(bitmap);
            string outputFileName = @"C: \Users\me\Desktop\bw.jpg";
            using (MemoryStream memory = new MemoryStream())
            {
                using (FileStream fs = new FileStream(outputFileName, FileMode.Create, FileAccess.ReadWrite))
                {
                    grayScaleBitmap.Save(memory, ImageFormat.Jpeg);
                    byte[] bytes = memory.ToArray();
                    fs.Write(bytes, 0, bytes.Length);
                }
            }
        }

        private static Bitmap GrayScale(Bitmap bmp)
        {
            //get image dimension
            int width = bmp.Width;
            int height = bmp.Height;
            int threshold = 128;

            //color of pixel
            System.Drawing.Color p;

            //grayscale
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    //get pixel value
                    p = bmp.GetPixel(x, y);

                    //extract pixel component ARGB
                    int a = p.A;
                    int r = p.R;
                    int g = p.G;
                    int b = p.B;

                    //find average, transform to b/w value
                    //int bw = (r + g + b) / 3 / 128; // or 384 if you prefer
                    int wb = (r + g + b) / 3; // avg: [0-255]
                    //transform avg to [0-1] using threshold
                    wb = (wb >= threshold) ? 1 : 0;  
                    //set new pixel value
                    bmp.SetPixel(x, y, System.Drawing.Color.FromArgb(a, bw*255, bw*255, bw*255));
                }
            }

            return bmp;
        }
    }
}