У меня есть небольшая функция, которая будет перекрашивать пиксели в растровом изображении от заданного цвета к новому заданному цвету.
Проблемы с кодом следующие:
1)функция дает результаты, которые переопределяют белые пиксели, которые не следует учитывать, поскольку у меня есть порог ... (если я не определил этот расчет неправильно)
2) Когда заданы определенные цвета, например, результаты LimeGreen wierd видны визображение, возвращаемое из функции (полагаю, это связано с переполнением типа байта в случае сложения или вычитания)
Базовое изображение, которое я использую, можно найти здесь:
http://www.freeimagehosting.net/uploads/c8745a9de1.png
Результаты, которые я получил, можно найти здесь:
freeimagehosting.net / uploads / fa48e5a0eb.png (Вызывается с Color.Magenta как remapColor, Color.Red как newColor, выглядит как белые пикселии градиент окрашен неправильно)
freeimagehosting.net / uploads / 8faec6a569.png (Вызывается с Color.Magenta как remapColor,Color.Yellow as newColor. Похоже, что белые пиксели применяются, и конец градиента не окрашен правильно)
freeimagehosting.net / uploads / 2efd4c04aa.png (Вызывается с Color.Magenta как remapColor, Color.Blueкак newColor, похоже, что градиент не окрашен правильно)
freeimagehosting.net / uploads / defdf04e16.png (Вызывается с Color.Magenta как remapColor, Color.Teal как newColor, похоже, что белые пиксели не применяются, и ниГрадиент рассчитан правильно)
Функция, которую я имею для этого кода ниже: ОБНОВЛЕНО в соответствии с предложениями
public unsafe static Bitmap RecolorImage(Bitmap original, Color remapColor, Color newColor)
{
Bitmap result = new Bitmap(original.Width, original.Height);
//lock the original bitmap in memory
BitmapData originalData = original.LockBits(
new Rectangle(0, 0, original.Width, original.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
//lock the new bitmap in memory
BitmapData newData = result.LockBits(
new Rectangle(0, 0, original.Width, original.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
//set the number of bytes per pixel
int pixelSize = 4;
int rthreshold = 128;
int gthreshold = 128;
int bthreshold = 128;
for (int y = 0; y < original.Height; y++)
{
//get the data from the original image
byte* oRow = (byte*)originalData.Scan0 + (y * originalData.Stride);
//get the data from the new image
byte* nRow = (byte*)newData.Scan0 + (y * newData.Stride);
for (int x = 0; x < original.Width; x++)
{
//examine the rgb values
byte r = (byte)((oRow[x * pixelSize]));
byte g = (byte)((oRow[x * pixelSize + 1]));
byte b = (byte)((oRow[x * pixelSize + 2]));
byte a = (byte)((oRow[x * pixelSize + 3]));
if (a > 0 &&
Math.Abs(remapColor.R - r) <= rthreshold &&
Math.Abs(remapColor.B - b) <= bthreshold &&
Math.Abs(remapColor.G - g) <= gthreshold
)
{
if (newColor.R == 0)
{
r = 0;
}
else
{
if (newColor.R > remapColor.R)
r = (byte)(r - newColor.R);
else
r = (byte)(r + newColor.R);
}
if (newColor.G == 0)
{
g = 0;
}
else
{
if (newColor.G > remapColor.G)
g = (byte)(g - newColor.G);
else
g = (byte)(g + newColor.G);
}
if (newColor.B == 0)
{
b = 0;
}
else
{
if (newColor.B > remapColor.B)
b = (byte)(b - newColor.B);
else
b = (byte)(b + newColor.B);
}
}
//set the new image's pixel remaped pixel color
nRow[x * pixelSize] = b; //B
nRow[x * pixelSize + 1] = g; //G
nRow[x * pixelSize + 2] = r; //R
nRow[x * pixelSize + 3] = a; //A
}
}
original.UnlockBits(originalData);
result.UnlockBits(newData);
return result;
}
Что дает ....
Возможно ли то, что я пытаюсь сделать?
Надежно ли это?
В моем коде только ошибка?
Есть ли лучший способ добиться этого? "re-mapable техника "на растровых изображениях с использованием градиентов?
Спасибо за ваше время.