Подтвердить что ты не робот

Как идентифицировать изображения CMYK в ASP.NET с помощью С#

Кто-нибудь знает, как правильно идентифицировать изображения CMYK в ASP.NET с помощью С#? Когда я проверяю атрибут Flags экземпляра Bitmap, я получаю неправильные результаты.

Я создал три изображения, чтобы проверить это: cmyk.jpg, rgb.jpg и gray.jpg. Это соответственно изображения CMYK, RGB и Grayscale.

Это мой тестовый код:

static void Main(string[] args)
{
    Bitmap bmpCMYK = new Bitmap("cmyk.jpg");
    Bitmap bmpRGB = new Bitmap("rgb.jpg");
    Bitmap bmpGray = new Bitmap("gray.jpg");

    Console.WriteLine("\t\tRgb\tCmyk\tGray\tYcbcr\tYcck\tPixelFormat");

    Console.WriteLine("cmyk.jpg\t{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
        IsSet(bmpCMYK, System.Drawing.Imaging.ImageFlags.ColorSpaceRgb),
        IsSet(bmpCMYK, System.Drawing.Imaging.ImageFlags.ColorSpaceCmyk),
        IsSet(bmpCMYK, System.Drawing.Imaging.ImageFlags.ColorSpaceGray),
        IsSet(bmpCMYK, System.Drawing.Imaging.ImageFlags.ColorSpaceYcbcr),
        IsSet(bmpCMYK, System.Drawing.Imaging.ImageFlags.ColorSpaceYcck),
        bmpCMYK.PixelFormat);

    Console.WriteLine("rgb.jpg\t\t{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
        IsSet(bmpRGB, System.Drawing.Imaging.ImageFlags.ColorSpaceRgb),
        IsSet(bmpRGB, System.Drawing.Imaging.ImageFlags.ColorSpaceCmyk),
        IsSet(bmpRGB, System.Drawing.Imaging.ImageFlags.ColorSpaceGray),
        IsSet(bmpRGB, System.Drawing.Imaging.ImageFlags.ColorSpaceYcbcr),
        IsSet(bmpRGB, System.Drawing.Imaging.ImageFlags.ColorSpaceYcck),
        bmpRGB.PixelFormat);

    Console.WriteLine("gray.jpg\t{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
        IsSet(bmpGray, System.Drawing.Imaging.ImageFlags.ColorSpaceRgb),
        IsSet(bmpGray, System.Drawing.Imaging.ImageFlags.ColorSpaceCmyk),
        IsSet(bmpGray, System.Drawing.Imaging.ImageFlags.ColorSpaceGray),
        IsSet(bmpGray, System.Drawing.Imaging.ImageFlags.ColorSpaceYcbcr),
        IsSet(bmpGray, System.Drawing.Imaging.ImageFlags.ColorSpaceYcck),
        bmpGray.PixelFormat);

    bmpCMYK.Dispose();
    bmpRGB.Dispose();
    bmpGray.Dispose();

    Console.ReadLine();
}

private static bool IsSet(Bitmap bitmap, System.Drawing.Imaging.ImageFlags flag)
{
    return (bitmap.Flags & (int)flag) == (int)flag;
}

Это производит следующий вывод: Test results

Я проверил фактические изображения, а cmyk.jpg - действительно изображение CMYK.

По-видимому, это "известная проблема". У Alex Gil была такая же проблема в WPF (см. Этот вопрос: Как идентифицировать изображения CMYK с помощью С#), и ему удалось решить его, используя класс BitmapDecoder для загрузки изображения. Мне немного неудобно использовать это решение в ASP.NET, потому что он требует, чтобы я добавлял ссылки на WindowsBase.dll и PresentationCore.dll, и я не уверен, что хочу это в веб-проекте.

Кто-нибудь знает какие-либо другие чистые .NET-решения, чтобы проверить, находится ли образ в формате CMYK, который я могу безопасно использовать в ASP.NET?

4b9b3361

Ответ 1

Я использую комбинацию значений ImageFlags и PixelFormat. Обратите внимание, что PixelFormat.Forma32bppCMYK отсутствует в .NET. Я выхватил его из GdiPlusPixelFormats.h в SDK Windows.

Фокус в том, что Windows 7 и Server 2008 R2 вернут правильный формат пикселей, но отсутствуют флаги изображений. Vista и Server 2008 возвращают неверный формат пикселей, но правильные флаги изображений. Insanity.

public ImageColorFormat GetColorFormat(this Bitmap bitmap)
{
    const int pixelFormatIndexed = 0x00010000;
    const int pixelFormat32bppCMYK = 0x200F;
    const int pixelFormat16bppGrayScale = (4 | (16 << 8);

    // Check image flags
    var flags = (ImageFlags)bitmap.Flags;
    if (flags.HasFlag(ImageFlags.ColorSpaceCmyk) || flags.HasFlag(ImageFlags.ColorSpaceYcck))
    {
        return ImageColorFormat.Cmyk;
    }
    else if (flags.HasFlag(ImageFlags.ColorSpaceGray))
    {
        return ImageColorFormat.Grayscale;
    }

    // Check pixel format
    var pixelFormat = (int)bitmap.PixelFormat;
    if (pixelFormat == pixelFormat32bppCMYK)
    {
        return ImageColorFormat.Cmyk;
    }
    else if ((pixelFormat & pixelFormatIndexed) != 0)
    {
        return ImageColorFormat.Indexed;
    }
    else if (pixelFormat == pixelFormat16bppGrayScale)
    {
        return ImageColorFormat.Grayscale;
    }

    // Default to RGB
    return ImageColorFormat.Rgb;
}    

public enum ImageColorFormat
{
    Rgb,
    Cmyk,
    Indexed,
    Grayscale
}

Ответ 2

Идея: если вы не хотите ссылаться на эти dll в своем веб-проекте, вы можете сделать обработку вне веб-проекта в службе, которая может быть в любом случае лучше?

Ответ 3

Вы можете проверить FreeImage, который является win32 DLL, но имеет оболочку .NET, я использую его в производственной среде и это здорово.

Я был бы удивлен, если бы не смог предоставить эту информацию.

(изменить) Я не заметил, прежде чем вы попросили чистые .NET-решения - возможно, это не сработает, но я нашел это полезным дополнением к ограничениям платформы .NET для манипуляций с изображениями.

Другая идея, если вам нужно всего лишь определить формат, - извлечь ее непосредственно из файла. Я понятия не имею, насколько сложна спецификация формата JPEG, но эй, это только 29 страниц!

Ответ 4

Как ранее ответили, самым надежным способом будет синтаксический анализ заголовка файла для извлечения этих данных.

Ответ 5

Итак, вот как я решил проблему, с которой вы столкнулись, что было тем же, что и у меня. Все в csharp выглядит, чтобы вернуть rgb-информацию, когда вы знаете, что это 100% изображение cymk. Итак, что делать, хорошо зайдите в корневой каталог и прочитайте файл. Вот что я сделал и протестировал, чтобы хорошо работать и должен охватывать все ОС, и 50 для 50 imgs проверены правильно. Это тоже 2.0 на всякий случай.

     public bool isByteACMYK(Stream image)
    {
        using (StreamReader sr = new StreamReader(image)) 
        { 
            string contents = sr.ReadToEnd(); 
            if (contents.ToLower().Contains("cmyk")) 
            { 
                return true;
            } 
        }
        return false;
    }

    public bool isFileACMYKJpeg(System.Drawing.Image image)
    {
        System.Drawing.Imaging.ImageFlags flagValues = (System.Drawing.Imaging.ImageFlags)Enum.Parse(typeof(System.Drawing.Imaging.ImageFlags), image.Flags.ToString());
        if (flagValues.ToString().ToLower().IndexOf("ycck") == -1)
        {
            // based on http://www.maxostudio.com/Tut_CS_CMYK.cfm

            bool ret = false;
            try{
                int cmyk = (image.Flags & (int)ImageFlags.ColorSpaceCmyk);
                int ycck = (image.Flags & (int)ImageFlags.ColorSpaceYcck);

                ret = ((cmyk > 0) || (ycck > 0));
            } catch (Exception ex){

            }
            return ret;
        }
        return true;
    } 
    // my upload test .. but you could turn a file to stream and do the same
    public void UpdatePool(HttpPostedFile newimage)
    {
        if (newimage.ContentLength != 0)
        {
            Stream stream = newimage.InputStream;
            MemoryStream memoryStream = new MemoryStream();
            CopyStream(stream,memoryStream);
            memoryStream.Position = 0;
            stream = memoryStream;


            System.Drawing.Image processed_image = null;

            processed_image = System.Drawing.Image.FromStream(newimage.InputStream);

            if (imageService.isFileACMYKJpeg(processed_image) || imageService.isByteACMYK(stream))
            {
                Flash["error"] = "You have uploaded a CMYK image.  Please conver to RGB first.";
                RedirectToReferrer();
                return;
            }
        }
    }

cheers - Джереми

Ответ 6

Я был в предположении, что все в .NET было основано на RGB, aRGB и оттенках серого (в оттенках серого есть RGB (128, 128, 128)).

Если мое предположение верно, вам нужно будет пройти сторонний маршрут.