C#彩色图像像素化 [英] C# Recolored Image Pixelated

查看:52
本文介绍了C#彩色图像像素化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我可以使用它,但是生成的图像在边缘上被严重像素化.

我已经尝试过System.Drawing:

  var colorMap =新的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 =新的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,新的Rectangle(0,0,image.Width,image.Height),0、0,image.Width,图片高度GraphicsUnit.Pixel,imageAttrs); 

我也尝试过使用它的ReplaceColor()方法尝试ImageProcessor库,但是得到的结果相同(尽管还不算很糟).

有什么方法可以保留原始图像的光滑边缘吗?

解决方案

所讨论的图像非常简单,单色,几何形状.

听起来不错,但问题是您的表格"颜色太短了,除非图像确实确实包含了您放入地图中的一种颜色!但是,这些图像肯定是在启用了抗锯齿功能的情况下绘制的,因此表中并未涵盖所有抗锯齿像素.您需要

  • 任何一种都使用没有抗锯齿的图像,但是它们不会像您想要的那样平滑
  • 或构建适当的 ColorMap ,请参见下文
  • 编写自己的函数,最好使用

    I'm attempting to load an image from the filesystem, re-color it, then save it to a Stream. The images in question are fairly simple, single-color, geometric shapes.

    I have it working, but the resulting images are heavily pixelated along the edges.

    I've tried 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);
    

    I've also tried the ImageProcessor library, using its ReplaceColor() method, but I get the same results (although not quite as bad).

    Any way to do this and preserve the nice smooth edges my original image had?

    解决方案

    The images in question are fairly simple, single-color, geometric shapes.

    Sounds fine but the problem is that your 'Table' of colors is far too short unless the images really and truely contain only the one color you put into the map! But those images most certainly have been drawn with anti-aliasing on and therefore all anti-aliased pixels are not covered by the Table. You need to

    • Either use images without antialiasing, but they won't be as smooth as you want it
    • Or build a proper ColorMap, see below
    • Or write a function of your own, best using Lockbits for speed..
    • Or you can try to achieve the color changes with a ColorMatrix which combines speed and 'color smartness'. However not all changes lend itself to using it.. So you may want to tell us about the kind of changes you will need..

    You are not alone:

    I just tried the example on msdn because it looks so wrong: Saving Jpg files should not work (as it will always generate its own color tables) and look and behold it works, but only because the files created on my machine are Png files with the wrong extension! Once you add ImageFormat.Jpeg to the save it stops working..:

    Original MSDN code:

    myBitmap.Save("Circle2.jpg");
    

    Changed to

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

    Results:

    To build a proper ColorMap you will need to a) loop over all pixels and collect all distinct colors (simple but slow) and then calculate the target colors (fast but not necessarily simple or well-defined.)

    Here are two routines that show how to build a complete 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;
    }
    

    To use it you write:

    // 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];
    }
    

    Note that writing the correct code for the ChangeColor function is anything but simple. Not only will you have to know what you want, you also need the right tools to achieve it. In my code example above I have done a very simplistic channel swap. This will usually not result in what you want: Neither the prime colors nor the anti-aliased pixels can be changed so simply. Instead you should transform from RGB to HSL or HSV and change the hue there! See here for a SetHue example!

    这篇关于C#彩色图像像素化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆