如何重新着色图像? (见图)
如何以编程方式实现这种颜色替换?
所以这是我用来替换像素的函数:
Color.FromArgb( oldColorInThisPixel.R + (byte)((1 - oldColorInThisPixel.R / 255.0) * colorToReplaceWith.R), oldColorInThisPixel.G + (byte)((1 - oldColorInThisPixel.G / 255.0) * colorToReplaceWith.G), oldColorInThisPixel.B + (byte)((1 - oldColorInThisPixel.B / 255.0) * colorToReplaceWith.B) )
谢谢,CodeInChaos!
计算新像素的公式为:
newColor.R=OldColor; newColor.G=OldColor; newColor.B=255;
推广到任意颜色:
我假设您要将白色到白色和黑色映射到该颜色。 所以公式是newColor=TargetColor+(White-TargetColor)*Input
newColor.R=OldColor+(1-oldColor/255.0)*TargetColor.R; newColor.G=OldColor+(1-oldColor/255.0)*TargetColor.G; newColor.B=OldColor+(1-oldColor/255.0)*TargetColor.B;
然后迭代图像的像素(字节数组)并将它们写入新的RGB数组。 关于如何将图像复制到字节数组并对其进行操作有很multithreading。
最简单的方法是使用ColorMatrix处理图像,您甚至可以处理所需效果的飞行预览 – 这是在图形编辑应用程序中制作了多少个滤色器。 在这里和这里,您可以在C#中使用Colormatrix找到颜色效果的介绍。 通过使用ColorMatrix,您可以根据需要制作彩色滤镜,以及棕褐色,黑/白,反转,范围,亮度,对比度,亮度,水平(通过多次通过)等。
编辑:这是一个例子(更新 – 固定颜色矩阵将较暗的值转换为蓝色而不是之前的归零而不是蓝色部分 – 并且 – 添加0.5f为蓝色,因为在黑色上方的图片变为50%蓝色):
var cm = new ColorMatrix(new float[][] { new float[] {1, 0, 0, 0, 0}, new float[] {0, 1, 1, 0, 0}, new float[] {0, 0, 1, 0, 0}, new float[] {0, 0, 0, 1, 0}, new float[] {0, 0, 0.5f, 0, 1} }); var img = Image.FromFile("C:\\img.png"); var ia = new ImageAttributes(); ia.SetColorMatrix(cm); var bmp = new Bitmap(img.Width, img.Height); var gfx = Graphics.FromImage(bmp); var rect = new Rectangle(0, 0, img.Width, img.Height); gfx.DrawImage(img, rect, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia); bmp.Save("C:\\processed.png", ImageFormat.Png);
你想在这里使用ColorMatrix。 源图像是灰度,其所有R,G和B值都相等。 然后只需用RGB =(0,0,255)替换黑色为深蓝色,白色用RGB =(255,255,255)来获得白色。 因此矩阵可能如下所示:
1 0 0 0 0 // not changing red 0 1 0 0 0 // not changing green 0 0 0 0 0 // B = 0 0 0 0 1 0 // not changing alpha 0 0 1 0 1 // B = 255
此示例表单再现右侧图像:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private Image mImage; protected override void OnPaint(PaintEventArgs e) { if (mImage != null) e.Graphics.DrawImage(mImage, Point.Empty); base.OnPaint(e); } private void button1_Click(object sender, EventArgs e) { using (var srce = Image.FromFile(@"c:\temp\grayscale.png")) { if (mImage != null) mImage.Dispose(); mImage = new Bitmap(srce.Width, srce.Height); float[][] coeff = { new float[] { 1, 0, 0, 0, 0 }, new float[] { 0, 1, 0, 0, 0 }, new float[] { 0, 0, 0, 0, 0 }, new float[] { 0, 0, 0, 1, 0 }, new float[] { 0, 0, 1, 0, 1 }}; ColorMatrix cm = new ColorMatrix(coeff); var ia = new ImageAttributes(); ia.SetColorMatrix(new ColorMatrix(coeff)); using (var gr = Graphics.FromImage(mImage)) { gr.DrawImage(srce, new Rectangle(0, 0, mImage.Width, mImage.Height), 0, 0, mImage.Width, mImage.Height, GraphicsUnit.Pixel, ia); } } this.Invalidate(); } }
取决于你的图像格式是什么以及你的最终格式是什么。
还取决于你想使用什么工具。 你可以使用:
- GDI
- GD +
- 图像处理库,如OpenCV
GDI非常快,但可能非常麻烦。 您需要更改调色板。 GDI +在.NET中公开,可以更慢但更容易。 OpenCV很棒,但增加了依赖性。
(UPDATE)
此代码将图像更改为蓝色比例而不是灰度 – 图像格式为32位ARGB:
private static unsafe void ChangeColors(string imageFileName) { const int noOfChannels = 4; Bitmap img = (Bitmap) Image.FromFile(imageFileName); BitmapData data = img.LockBits(new Rectangle(0,0,img.Width, img.Height), ImageLockMode.ReadWrite, img.PixelFormat); byte* ptr = (byte*) data.Scan0; for (int j = 0; j < data.Height; j++) { byte* scanPtr = ptr + (j * data.Stride); for (int i = 0; i < data.Stride; i++, scanPtr++) { if (i % noOfChannels == 3) { *scanPtr = 255; continue; } if (i % noOfChannels != 0) { *scanPtr = 0; } } } img.UnlockBits(data); img.Save(Path.Combine( Path.GetDirectoryName(imageFileName), "result.png"), ImageFormat.Png); }
此代码项目文章涵盖了以下内容: http : //www.codeproject.com/KB/GDI-plus/Image_Processing_Lab.aspx
它使用AForge.NET库对图像执行Hue过滤,以获得类似的效果:
// create filter AForge.Imaging.Filters.HSLFiltering filter = new AForge.Imaging.Filters.HSLFiltering( ); filter.Hue = new IntRange( 340, 20 ); filter.UpdateHue = false; filter.UpdateLuminance = false; // apply the filter System.Drawing.Bitmap newImage = filter.Apply( image );
它还取决于你想要的东西:你想保留原件并只调整它的显示方式吗? WPF中的效果或像素着色器可能会起作用并且非常快。
如果任何Android开发人员最终看到这个,这就是我想到的灰度和使用CodesInChaos的公式和Android图形类ColorMatrix
和ColorMatrixColorFilter
着色图像。
谢谢您的帮助!
public static ColorFilter getColorFilter(Context context) { final int tint = ContextCompat.getColor(context, R.color.tint); final float R = Color.red(tint); final float G = Color.green(tint); final float B = Color.blue(tint); final float Rs = R / 255; final float Gs = G / 255; final float Bs = B / 255; // resultColor = oldColor + (1 - oldColor/255) * tintColor final float[] colorTransform = { 1, -Rs, 0, 0, R, 1, -Gs, 0, 0, G, 1, -Bs, 0, 0, B, 0, 0, 0, 0.9f, 0}; final ColorMatrix grayMatrix = new ColorMatrix(); grayMatrix.setSaturation(0f); grayMatrix.postConcat(new ColorMatrix(colorTransform)); return new ColorMatrixColorFilter(grayMatrix); }
然后可以将ColorFilter
应用于ImageView
imageView.setColorFilter(getColorFilter(imageView.getContext()));