Я пытаюсь выяснить, является ли изображение цветным или нет. На этот вопрос StackOverflow есть ответ это говорит о том, что я должен проверить перечисление PixelFormat
Image
. К сожалению, ответ мне не очень ясен. Безопасно ли проверять, отличается ли image.PixelFormat
от PixelFormat.Format16bppGrayScale
, чтобы считать, что это цветное изображение? А как насчет других значений перечисления? Документация MSDN не очень ясна...
Проверьте, цветное изображение или нет
Ответы (3)
Вы можете улучшить это, избегая Color.FromArgb и перебирая байты вместо целых чисел, но я подумал, что это будет более читабельным для вас и более простым для понимания как подход.
Общая идея заключается в том, чтобы преобразовать изображение в растровое изображение известного формата (32 бита на пиксель ARGB), а затем проверить, содержит ли это растровое изображение какие-либо цвета.
Блокировка битов растрового изображения позволяет вам перебирать его цветовые данные во много раз быстрее, чем при использовании GetPixel, используя небезопасный код.
Если альфа пикселя равна 0, то это, очевидно, GrayScale, потому что альфа 0 означает, что он полностью непрозрачен. Кроме этого - если R = G = B, то он серый (а если они = 255, то черный).
private static unsafe bool IsGrayScale(Image image)
{
using (var bmp = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb))
{
using (var g = Graphics.FromImage(bmp))
{
g.DrawImage(image, 0, 0);
}
var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
var pt = (int*)data.Scan0;
var res = true;
for (var i = 0; i < data.Height * data.Width; i++)
{
var color = Color.FromArgb(pt[i]);
if (color.A != 0 && (color.R != color.G || color.G != color.B))
{
res = false;
break;
}
}
bmp.UnlockBits(data);
return res;
}
}
Ответ SimpleVar в основном правильный: этот код неправильно обрабатывает, когда исходное изображение имеет формат индексированного цвета.
Чтобы решить эту проблему, просто замените внешний блок using
на:
using (var bmp = new Bitmap(image)) {
и полностью удалите внутренний using
, так как объект Graphics
больше не нужен. Это создаст идеальную копию изображения в неиндексированном формате, независимо от формата исходного изображения в пикселях.