의가 변경할 수 있습니다, 당신은하지 Color
개체하지만, R, G, B 값을 비교해야 투명성를 확인하려면 : 당신이 그것을 작동하는 것을 볼 수 있습니다 이제
var originalColor = scrBitmap.GetPixel(i, j);
if (originalColor.R == 0 && originalColor.G == 0 && originalColor.B == 0)
newBitmap.SetPixel(i, j, Color.FromArgb(originalColor.A, Color.Red));
하지만 그것은 매우 소요 각 이미지를 처리하는 데 오랜 시간이 걸립니다. GetPixel
및 SetPixel
은 매우 느립니다 (각 호출에 대해 모든 것을 확인하고 계산하기 때문에 기본 이미지 임). 비트 맵 데이터를 직접 처리하는 것이 훨씬 좋습니다.
static unsafe Bitmap ReplaceColor(Bitmap source,
Color toReplace,
Color replacement)
{
const int pixelSize = 4; // 32 bits per pixel
Bitmap target = new Bitmap(
source.Width,
source.Height,
PixelFormat.Format32bppArgb);
BitmapData sourceData = null, targetData = null;
try
{
sourceData = source.LockBits(
new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
targetData = target.LockBits(
new Rectangle(0, 0, target.Width, target.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
for (int y = 0; y < source.Height; ++y)
{
byte* sourceRow = (byte*)sourceData.Scan0 + (y * sourceData.Stride);
byte* targetRow = (byte*)targetData.Scan0 + (y * targetData.Stride);
for (int x = 0; x < source.Width; ++x)
{
byte b = sourceRow[x * pixelSize + 0];
byte g = sourceRow[x * pixelSize + 1];
byte r = sourceRow[x * pixelSize + 2];
byte a = sourceRow[x * pixelSize + 3];
if (toReplace.R == r && toReplace.G == g && toReplace.B == b)
{
r = replacement.R;
g = replacement.G;
b = replacement.B;
}
targetRow[x * pixelSize + 0] = b;
targetRow[x * pixelSize + 1] = g;
targetRow[x * pixelSize + 2] = r;
targetRow[x * pixelSize + 3] = a;
}
}
}
finally
{
if (sourceData != null)
source.UnlockBits(sourceData);
if (targetData != null)
target.UnlockBits(targetData);
}
return target;
}
물론이 further optimized 할 수 있으며 다른 처리해야 할 수 있습니다 : 당신이 사전에 이미지 형식을 알고 (그리고 각 이미지에 대한 고정 된 것) 경우에 당신은 조금 더 코드가 훨씬 빠르게 작업을 수행 할 수 있습니다 형식 (해당 레이아웃에 대해서는 see this list of pixel formats 및 this article)이지만 비트 맵을 사용하기위한 출발점이라고 생각하십시오.
완전성을 위해 비트 맵 데이터에 직접 액세스 할 수없는 동일한 색상입니다. 몹시 느리기 때문에 거의 사용하지 않아야합니다.
static Bitmap ReplaceColor(Bitmap source,
Color toReplace,
Color replacement)
{
var target = new Bitmap(source.Width, source.Height);
for (int x = 0; x < source.Width; ++x)
{
for (int y = 0; y < source.Height; ++y)
{
var color = source.GetPixel(x, y);
target.SetPixel(x, y, color == toReplace ? replacement : color);
}
}
return target;
}
비교시 알파 채널을 고려해야합니다 (예 : 50 % 투명한 녹색, 예 : 30 % 투명한 녹색과 같은 색). 당신은 대체 픽셀은 원본 이미지의 원시 사본을 만들 수 있습니다 작은 것을 알고있는 경우 (컨텍스트를 만들 Graphics.FromImage
를 사용하여 마지막으로
if (color.R == toReplace.R && color.G == toReplace.G && color.B == toReplace.B)
을하고 그것으로 source
비트 맵을 그릴 : 알파를 무시하려면이 같은 것을 사용할 수있다), 그런 식으로 교체가있을 때만 SetPixel()
으로 전화 할 것입니다. IMO의 최적화는 꽤 쓸모가 없습니다. 성능을 필요로하는 첫 번째 솔루션이 있다면 ...
이것은 가장 좋은 답변이며, DareDevil 덕분에 요구 사항이 충족되었다고 확신합니다. –
그럼 모든 색상을 새로운 색상으로 바꿀 것입니다. (선택된 색상뿐만 아니라) 그라데이션이있는 경우 알파를 확인하면 최적의 결과를 얻을 수 있지만 OP를 만족하면 ... –
잘이 코드는 단일 색상의 이미지. – DareDevil