Как определить изображения CMYK в ASP.NET с помощью C # - PullRequest
15 голосов
/ 21 февраля 2011

Кто-нибудь знает, как правильно идентифицировать изображения CMYK в ASP.NET с помощью C #? Когда я проверяю атрибут 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.

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

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

Ответы [ 6 ]

10 голосов
/ 28 марта 2012

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

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

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 голосов
/ 21 февраля 2011

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

1 голос
/ 02 марта 2011

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

1 голос
/ 24 февраля 2011

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

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

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

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

0 голосов
/ 28 февраля 2012

Итак, вот как я решил проблему, с которой вы столкнулись, которая была такой же, как и у меня. Все в 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;
            }
        }
    }

ура - Джереми

0 голосов
/ 24 февраля 2011

Я предполагал, что все в .NET основано на RGB, aRGB и градациях серого (в градациях серого - RGB (128, 128, 128)).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...