Применение цветового фильтра к растровому объекту - PullRequest
4 голосов
/ 25 марта 2012

Я нашел этот код о том, как применить цветной фильтр к растровому объекту в C #.Проблема в том, что для этого используется небезопасный код.Есть ли управляемый, безопасный способ сделать то же самое?Я знаю, что мог бы использовать библиотеку, такую ​​как AForge.NET или что-то подобное, но я надеюсь, что есть простой способ просто применить цветной фильтр.Все, что мне нужно, это простая замена цвета, замена белых пикселей на желтые.Есть предложения?

1 Ответ

4 голосов
/ 25 марта 2012

Вы всегда можете использовать безопасные методы GetPixel и SetPixel, но они медленны при использовании на многих пикселях, поэтому вы используете небезопасный метод для использования указателей на память растрового изображения. Это небезопасный способ сделать это.

Если ваше растровое изображение очень маленькое и вам не очень важна производительность, используйте методы GetPixel и SetPixel.

    private void ReplaceColor(Bitmap bitmap, Color originalColor, Color replacementColor)
    {
        for (var y = 0; y < bitmap.Height; y++)
        {
            for (var x = 0; x < bitmap.Width; x++)
            {
                if (bitmap.GetPixel(x, y) == originalColor)
                {
                    bitmap.SetPixel(x, y, replacementColor);
                }
            }
        }
    }

    private unsafe void ReplaceColorUnsafe(Bitmap bitmap, byte[] originalColor, byte[] replacementColor)
    {
        if (originalColor.Length != replacementColor.Length)
        {
            throw new ArgumentException("Original and Replacement arguments are in different pixel formats.");
        }

        if (originalColor.SequenceEqual(replacementColor))
        {
            return;
        }

        var data = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size),
                                   ImageLockMode.ReadWrite,
                                   bitmap.PixelFormat);

        var bpp = Image.GetPixelFormatSize(data.PixelFormat);

        if (originalColor.Length != bpp)
        {
            throw new ArgumentException("Original and Replacement arguments and the bitmap are in different pixel format.");
        }

        var start = (byte*)data.Scan0;
        var end = start + data.Stride;

        for (var px = start; px < end; px += bpp)
        {
            var match = true;

            for (var bit = 0; bit < bpp; bit++)
            {
                if (px[bit] != originalColor[bit])
                {
                    match = false;
                    break;
                }
            }

            if (!match)
            {
                continue;
            }

            for (var bit = 0; bit < bpp; bit++)
            {
                px[bit] = replacementColor[bit];
            }
        }

        bitmap.UnlockBits(data);
    }

Использование будет:

        this.ReplaceColor(myBitmap, Color.White, Color.Yellow); // SLOW

OR

        var orgRGB = new byte[] { 255, 255, 255 }; // White (in RGB format)
        var repRGB = new byte[] { 255, 255, 0 }; // Yellow (in RGB format)

        var orgARGB = new byte[] { 255, 255, 255, 255 }; // White (in ARGB format)
        var repARGB = new byte[] { 255, 255, 255, 0 }; // Yellow (in ARGB format)

        var orgRGBA = new byte[] { 255, 255, 255, 255 }; // White (in RGBA format)
        var repRGBA = new byte[] { 255, 255, 0, 255 }; // Yellow (in RGBA format)

        var orgBytes = orgRGB; // or ARGB or RGBA, depending on bitmap's pixel format
        var repBytes = repRGB; // or ARGB or RGBA, depending on bitmap's pixel format

        this.ReplaceColorUnsafe(myBitmap, orgBytes, repBytes); // FAST
...