C# 重新着色图像像素化
C# Recolored Image Pixelated
我正在尝试从文件系统加载图像,重新着色,然后将其保存到流中。有问题的图像非常简单,单色几何形状。
我让它工作了,但是生成的图像沿边缘严重像素化。
我试过了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);
我也尝试过 ImageProcessor 库,使用它的 ReplaceColor() 方法,但我得到了相同的结果(虽然没有那么糟糕)。
有什么方法可以做到这一点并保留我的原始图像的漂亮光滑边缘?
The images in question are fairly simple, single-color, geometric
shapes.
听起来不错,但问题是您的 'Table' 颜色太短,除非图像真的只包含您放入地图中的一种颜色!但是这些图像肯定是在启用抗锯齿的情况下绘制的,因此所有抗锯齿像素都不会被 Table 覆盖。你需要
- 要么使用没有抗锯齿的图像,但它们不会像您想要的那样平滑
- 或构建一个合适的
ColorMap
,见下文
- 或者自己写一个函数,最好用Lockbits来提高速度..
- 或您可以尝试使用结合了速度和'color smartness'的
ColorMatrix
来实现颜色变化。然而,并非所有更改都适合使用它。因此,您可能想告诉我们您需要进行哪些更改...
你并不孤单:
我刚刚在 msdn 上尝试了 example,因为它看起来很不对劲:保存 Jpg
文件应该不起作用(因为它总是会生成自己的颜色表)并观察 它可以工作,但仅 因为在我的机器上创建的文件是 Png
扩展名为 错误 的文件!一旦你添加 ImageFormat.Jpeg
到保存它停止工作..:[=28=]
原始 MSDN 代码:
myBitmap.Save("Circle2.jpg");
改为
myBitmap.Save("Circle2.jpg", ImageFormat.Jpeg);
结果:
要构建合适的 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!
我正在尝试从文件系统加载图像,重新着色,然后将其保存到流中。有问题的图像非常简单,单色几何形状。
我让它工作了,但是生成的图像沿边缘严重像素化。
我试过了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);
我也尝试过 ImageProcessor 库,使用它的 ReplaceColor() 方法,但我得到了相同的结果(虽然没有那么糟糕)。
有什么方法可以做到这一点并保留我的原始图像的漂亮光滑边缘?
The images in question are fairly simple, single-color, geometric shapes.
听起来不错,但问题是您的 'Table' 颜色太短,除非图像真的只包含您放入地图中的一种颜色!但是这些图像肯定是在启用抗锯齿的情况下绘制的,因此所有抗锯齿像素都不会被 Table 覆盖。你需要
- 要么使用没有抗锯齿的图像,但它们不会像您想要的那样平滑
- 或构建一个合适的
ColorMap
,见下文 - 或者自己写一个函数,最好用Lockbits来提高速度..
- 或您可以尝试使用结合了速度和'color smartness'的
ColorMatrix
来实现颜色变化。然而,并非所有更改都适合使用它。因此,您可能想告诉我们您需要进行哪些更改...
你并不孤单:
我刚刚在 msdn 上尝试了 example,因为它看起来很不对劲:保存 Jpg
文件应该不起作用(因为它总是会生成自己的颜色表)并观察 它可以工作,但仅 因为在我的机器上创建的文件是 Png
扩展名为 错误 的文件!一旦你添加 ImageFormat.Jpeg
到保存它停止工作..:[=28=]
原始 MSDN 代码:
myBitmap.Save("Circle2.jpg");
改为
myBitmap.Save("Circle2.jpg", ImageFormat.Jpeg);
结果:
要构建合适的 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!