C#重新着色的图像像素化

时间:2015-03-04 05:30:12

标签: c# .net image-processing imageprocessor

我正在尝试从文件系统加载图像,重新着色,然后将其保存到Stream。有问题的图像是相当简单的单色几何形状。

我有它工作,但结果图像沿边缘重像素化。

我试过System.Drawing:

var colorMap = new ColorMap
{
    OldColor = Color.FromArgb(255, 255, 255, 255),
    NewColor = Color.FromArgb(255, 255, 0, 0)
};
var imageAttrs = new ImageAttributes();
imageAttrs.SetRemapTable(new[] {colorMap});

var newImage = new Bitmap(image.Width, image.Height);
var graphics = Graphics.FromImage(newImage);

graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

graphics.DrawImage(image,
    new Rectangle(0, 0, image.Width, image.Height),
    0, 0,
    image.Width,
    image.Height,
    GraphicsUnit.Pixel,
    imageAttrs);

我也尝试过使用其ReplaceColor()方法的ImageProcessor库,但我得到了相同的结果(虽然不是很糟糕)。

任何方法都可以保留原始图像的漂亮光滑边缘吗?

1 个答案:

答案 0 :(得分:2)

  

有问题的图像相当简单,单色,几何   形状。

听起来很不错但问题是你的'桌子'颜色太短了,除非图像真的真实地只包含你放入地图的一种颜色!但是这些图像肯定是通过抗锯齿绘制的,因此表中没有涵盖所有抗锯齿像素。你需要

  • 要么使用没有抗锯齿的图片,但它们不会像你想要的那样平滑
  • 构建合适的ColorMap,见下文
  • 编写自己的功能,最好使用Lockbits来提高速度..
  • 您可以尝试使用结合速度和“颜色智能”的ColorMatrix来实现颜色变化。然而,并非所有更改都适合使用它。所以您可能想告诉我们您需要的更改类型..

你并不孤单:

我刚试过msdn上的example,因为它看起来很错误:保存Jpg文件不起作用(因为它总会生成自己的颜色表)并且看起来并且看起来它的工作原理,但仅,因为在我的计算机上创建的文件是带有错误扩展名的Png个文件!将ImageFormat.Jpeg添加到保存后,它将停止工作..:

原始MSDN代码:

myBitmap.Save("Circle2.jpg");

已更改为

myBitmap.Save("Circle2.jpg", ImageFormat.Jpeg);

结果:

enter image description here enter image description here

要构建一个合适的ColorMap,你需要a)遍历所有像素并收集所有不同的颜色(简单但很慢),然后计算目标颜色(快速但不一定简单或明确定义)。

以下两个例程展示了如何构建完整的ColorMap

List<Color> GetDistinctColors(Bitmap bmp)
{
    List<Color> colors = new List<Color>();
    for (int y = 0; y < bmp.Height; y++)
        for (int x = 0; x < bmp.Width; x++)
        {
            Color c = bmp.GetPixel(x,y);
            if (!colors.Contains(c)) colors.Add(c);
        }

    return colors;
}

List<Color> ChangeColors(List<Color> colors)
{
    List<Color> newColors = new List<Color>();
    foreach(Color c in colors)
    {
        int A = 255;   //  here you need..
        int R = c.G;   //  ..to write..
        int G = c.R;   //  ..your custom .
        int B = c.B;   //  ..color change code!!
        newColors.Add(Color.FromArgb(A,R,G,B));
    }
    return newColors;
}

要使用它,请写下:

// prepare the two lists:
List<Color> colors = GetDistinctColors((Bitmap)myImage);
List<Color> newColors = ChangeColors(colors);


// Create a complete color map
ColorMap[] myColorMap = new ColorMap[colors.Count];
for (int i = 0; i < colors.Count; i++)
{
   myColorMap[i] = new ColorMap();
   myColorMap[i].OldColor = colors[i];
   myColorMap[i].NewColor = newColors[i];
}

请注意,为ChangeColor函数编写正确的代码并不简单。您不仅需要知道自己想要什么,还需要正确的工具来实现它。在上面的代码示例中,我做了一个非常简单的通道交换。这通常不会产生您想要的结果:素色和消除锯齿的像素都不能如此简单地改变。相反,你应该从RGB转换为HSL或HSV,并在那里改变色调!请参阅此处查看SetHue example!