Как перекрасить изображение? (см. изображения)
Как я могу добиться такой замены цвета программно?
![replacing black with blue]()
Итак, это функция, которую я использовал для замены пикселя:
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!
Ответы
Ответ 1
Формула для вычисления нового пикселя:
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. Существует много потоков о том, как копировать изображение в массив байтов и манипулировать им.
Ответ 2
Проще всего было бы использовать ColorMatrix для обработки изображений, вы даже сможете обрабатывать предварительный просмотр желаемого эффекта на лету - это то, как много цветных фильтров создаются в приложениях для графического редактирования. Здесь и здесь вы можете познакомиться с цветовыми эффектами, используя Colormatrix в С#. Используя ColorMatrix, вы можете сделать раскрашивающий фильтр, как вы хотите, а также сепию, черно-белую, инвертированную, дальность, яркость, контрастность, яркость, уровни (многопроходным) и т.д.
EDIT: Вот пример (обновление - фиксированная цветная матрица для переноса более темных значений в синий цвет вместо предыдущего обнуления, отличного от синих, - и - добавлено 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);
Ответ 3
Здесь вы захотите использовать 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();
}
}
Ответ 4
Зависит от того, каков ваш формат изображения и каким будет ваш окончательный формат.
Также зависит от того, какой инструмент вы хотите использовать.
Вы можете использовать:
- GDI
- GD +
- Библиотека обработки изображений, такая как OpenCV
GDI довольно быстр, но может быть довольно громоздким. Вам нужно изменить палитру.
GDI + отображается в .NET и может быть медленнее, но проще.
OpenCV отлично, но добавляет зависимость.
(ОБНОВЛЕНИЕ)
Этот код изменяет изображение на синие масштабы вместо серого - формат изображения - 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);
}
Ответ 5
Эта статья проекта кода охватывает это и многое другое: 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 );
Ответ 6
Это также зависит от того, что вы хотите: хотите ли вы сохранить оригинал и только настроить способ его отображения? Эффект или pixhader в WPF может сделать трюк и быть очень быстрым.
Ответ 7
Если какие-либо 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()));