C# Recolored Image Pixelated

泄露秘密 提交于 2019-12-11 19:33:30

问题


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?


回答1:


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!



来源:https://stackoverflow.com/questions/28847270/c-sharp-recolored-image-pixelated

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!