Неверный профиль ICC возвращает opRGB из WCS с использованием WIC

Я ломал голову, пытаясь понять, что здесь делает библиотека Microsoft WIC / WCS, и был бы признателен за любую помощь от любого, кто разбирается в Windows Color Management. Документация по этому API ужасна.

Я читаю JPEG со встроенным профилем ICC, используя OpenColourProfile, но Windows, похоже, неправильно анализирует встроенную информацию ICC для некоторых изображений. Для других работает нормально. Однако, несмотря на то, что мне не удается проанализировать информацию заголовка с помощью Windows API, я могу правильно отображать все изображения, это просто синтаксический анализ информации заголовка встроенного профиля ICC, который является ошибочным.


Не работает

Используя инструмент exif_tool для отображения информации заголовка профиля ICC для изображения, которое не работает из моего кода, exif_tool правильно возвращает:

Profile CMM Type                : Adobe Systems Inc.
Profile Version                 : 2.1.0
Profile Class                   : Display Device Profile
Color Space Data                : RGB
Profile Connection Space        : XYZ
Profile Date Time               : 2000:08:11 19:51:59
Profile File Signature          : acsp
Primary Platform                : Apple Computer Inc.
CMM Flags                       : Not Embedded, Independent
Device Manufacturer             : none
Device Model                    :
Device Attributes               : Reflective, Glossy, Positive, Color
Rendering Intent                : Perceptual
Connection Space Illuminant     : 0.9642 1 0.82491
Profile Creator                 : Adobe Systems Inc.
Profile ID                      : 0
Profile Copyright               : Copyright 2000 Adobe Systems Incorporated
Profile Description             : Adobe RGB (1998)
Media White Point               : 0.95045 1 1.08905
Media Black Point               : 0 0 0
Red Tone Reproduction Curve     : (Binary data 14 bytes, use -b option to extract)
Green Tone Reproduction Curve   : (Binary data 14 bytes, use -b option to extract)
Blue Tone Reproduction Curve    : (Binary data 14 bytes, use -b option to extract)
Red Matrix Column               : 0.60974 0.31111 0.01947
Green Matrix Column             : 0.20528 0.62567 0.06087
Blue Matrix Column              : 0.14919 0.06322 0.74457

После прочтения заголовка профиля ICC в моем коде Windows возвращает тип CMM как 0000, который не определен (см. Ниже). Также тег версии анализируется на v2.0 (0x02000000), а не на v2.1, как показано в выходных данных exif_tool выше.

введите описание изображения здесь

Кроме того, после этого запрос (в моем коде) на возврат тега ICC 0x64657363 (ProfileDescription) возвращает «opRGB» вместо «Adobe RGB (1998)».

Что касается данных EXIF ​​для этого изображения, цветовое пространство определяется как «некалиброванное», и для него указан «индекс совместимости» со значением «R03», которое, как я понимаю, следует интерпретировать как Adobe RGB.

Работает


Используя другой JPG со встроенным профилем Adobe RGB (1998), я запустил его через exif_tool, и он отобразит:

Profile CMM Type                : Adobe Systems Inc.
Profile Version                 : 2.1.0
Profile Class                   : Display Device Profile
Color Space Data                : RGB
Profile Connection Space        : XYZ
Profile Date Time               : 1999:06:03 00:00:00
Profile File Signature          : acsp
Primary Platform                : Microsoft Corporation
CMM Flags                       : Not Embedded, Independent
Device Manufacturer             : none
Device Model                    :
Device Attributes               : Reflective, Glossy, Positive, Color
Rendering Intent                : Media-Relative Colorimetric
Connection Space Illuminant     : 0.9642 1 0.82491
Profile Creator                 : Adobe Systems Inc.
Profile ID                      : 0
Profile Copyright               : Copyright (c) 1999 Adobe Systems Incorporated. All     Rights Reserved.
Profile Description             : Adobe RGB (1998)
Media White Point               : 0.95045 1 1.08905
Media Black Point               : 0 0 0
Red Tone Reproduction Curve     : (Binary data 14 bytes, use -b option to extract)
Green Tone Reproduction Curve   : (Binary data 14 bytes, use -b option to extract)
Blue Tone Reproduction Curve    : (Binary data 14 bytes, use -b option to extract)
Red Matrix Column               : 0.60974 0.31111 0.01947
Green Matrix Column             : 0.20528 0.62567 0.06087
Blue Matrix Column              : 0.14919 0.06322 0.74457

При использовании OpenColourProfile мой код (который использует Windows API) правильно анализирует информацию заголовка:

введите описание изображения здесь

После этого запрос (в моем коде) на возврат тега ICC 0x64657363 (ProfileDescription) правильно возвращает «Adobe RGB (1998)».

Что касается данных EXIF ​​для этого изображения, цветовое пространство определяется как «некалиброванное» и не указывается «индекс совместимости».

Код


    /* COLOUR PROFILE MANAGEMENT */
    IWICColorContext* pContextSrc = NULL;
    IWICColorContext* pContextDst = NULL;

    hr = factory->CreateColorContext(&pContextSrc);
    if (!SUCCEEDED(hr))
        return nullptr;

    UINT numColourContexts = 0;
    hr = wic->mFrame->GetColorContexts(1, &pContextSrc, &numColourContexts);

    if (numColourContexts > 0)
    {
        hr = factory->CreateColorContext(&pContextDst);
        if (!SUCCEEDED(hr))
            return nullptr;

        WCHAR destColourContextFilename[_MAX_PATH + 1];
        DWORD destColourContextFilenameSize = sizeof(destColourContextFilename);

        if (GetColorDirectory(NULL, destColourContextFilename, &destColourContextFilenameSize))
        {
            hr = StringCchCatW(destColourContextFilename,
                sizeof(destColourContextFilename) / sizeof(destColourContextFilename[0]),
                L"\\sRGB Color Space Profile.icm");
        }
        else
        {
            hr = E_UNEXPECTED;
        }

        if (SUCCEEDED(hr))
        {
            hr = pContextDst->InitializeFromFilename(destColourContextFilename);
        }


        if (SUCCEEDED(hr))
        {
            hr = factory->CreateColorTransformer(&wic->pColorTransform);
        }

        if (SUCCEEDED(hr))
        {
            hr = wic->pColorTransform->Initialize(wic->mFrame.get(),
                pContextSrc,
                pContextDst,
                wic->mPixelFormat);

            if (!SUCCEEDED(hr))
            {
                return nullptr;
            }
        }

            //  WICColorContextUninitialized = 0,
            //  WICColorContextProfile = 0x1,
            //  WICColorContextExifColorSpace = 0x2
            WICColorContextType type;
            pContextSrc->GetType(&type);

            if (type == WICColorContextType::WICColorContextProfile)
            {
                UINT cbProfile = 0;
                hr = pContextSrc->GetProfileBytes(0, NULL, &cbProfile);

                if (!SUCCEEDED(hr))
                    return nullptr;

                VOID* pvProfile = NULL;

                if (SUCCEEDED(hr))
                {
                    // allocate the block
                    pvProfile = HeapAlloc(
                        GetProcessHeap(),
                        HEAP_ZERO_MEMORY,
                        cbProfile);

                    hr = pvProfile ? S_OK : E_FAIL;
                }

                UINT cbSize = 0;
                if (SUCCEEDED(hr))
                {
                    // copy the profile into the block
                    hr = pContextSrc->GetProfileBytes(cbProfile, (BYTE*)pvProfile, &cbSize);
                }

                // ***Open the memory block as a HPROFILE***
                HPROFILE hProfile = NULL;

                // fill out a PROFILE structure
                PROFILE prof =
                {
                      PROFILE_MEMBUFFER,
                      pvProfile,
                      cbProfile
                };

                // create the HPROFILE
                if (SUCCEEDED(hr))
                {
                    /*hProfile = WcsOpenColorProfile(
                        &prof,
                        NULL,
                        NULL,
                        PROFILE_READ,
                        FILE_SHARE_READ,
                        OPEN_EXISTING,
                        0);*/

                    hProfile = OpenColorProfile(
                            &prof,
                            PROFILE_READ,
                            FILE_SHARE_READ,
                            OPEN_EXISTING);


                    hr = hProfile ? S_OK : E_FAIL;
                    HeapFree(GetProcessHeap(), 0, pvProfile);
                }

                PROFILEHEADER ph;
                GetColorProfileHeader(hProfile,  &ph);


                DWORD size = 100;
                CHAR description[100];
                for (int i = 0; i < 100; i++)
                {
                    description[i] = '\0';
                }
                BOOL b;
                BOOL s = GetColorProfileElement(hProfile, 0x64657363, 12, &size, &description, &b);
                string profileDescription = std::string(description);

Переменная ph представляет снимки экрана с синим изображением выше, а profileDescription представляет описание профиля ICC (которое работает для одного изображения, а не для другого).


Различия между заголовками ICC

Я суммировал различия в информации заголовка ICC, как сообщает exif_tool, что приводит к тому, что API Windows не может правильно проанализировать информацию встроенного заголовка ICC:

Работает

Profile Date Time               : 2000:08:11 19:51:59
Primary Platform                : Apple Computer Inc.
Rendering Intent                : Perceptual
Profile Copyright               : Copyright 2000 Adobe Systems Incorporated

Не работает

Profile Date Time               : 1999:06:03 00:00:00
Primary Platform                : Microsoft Corporation
Rendering Intent                : Media-Relative Colorimetric
Profile Copyright               : Copyright (c) 1999 Adobe Systems Incorporated. All Rights Reserved.

Другое программное обеспечение для редактирования изображений правильно отображает оба изображения как «Adobe RGB (1998)».

Кажется, что API Windows не любит, когда встроенная информация ICC предназначена для платформы Microsoft (?)

Это может быть вызвано отсутствием «Индекса совместимости» (указанного как «R03» для образа, который не работает, и не указан для образа, который действительно работает), но если бы это было так, это могло бы показаться ошибкой в Окна (?)

Может ли быть, что «Adobe RGB» и «Adobe RGB (1998)» - это два разных профиля, а все другое программное обеспечение, которое сообщает о них как «Adobe RGB (1998)», просто не различает их?

у меня голова болит ... Кто-нибудь знает, что здесь творится?

Ваше здоровье

РЕДАКТИРОВАТЬ:

Рабочее изображение (описание профиля = Adobe RGB (1998) при чтении с помощью Windows API):

введите описание изображения здесь

Не работает (описание профиля = opRGB при чтении с помощью Windows API): < img src = "https://i.stack.imgur.com/gNaIW.jpg" alt = "введите описание изображения здесь">


person Laythe    schedule 10.11.2019    source источник
comment
У вас есть соответствующий образец изображения? Откуда вы знаете, что существует только один цветовой контекст?   -  person Simon Mourier    schedule 10.11.2019
comment
Привет, Саймон, спасибо за ответ. Вызов функции GetColorContexts () в обоих случаях возвращает 1, я предполагаю, что не может быть ничего, кроме того, что это возвращает. Я могу отправить изображения, но не знаете, как прикрепить изображения сюда? РЕДАКТИРОВАТЬ: ой. как неловко. только что нашел!   -  person Laythe    schedule 10.11.2019


Ответы (1)


Возможно, намерение отрисовки: перцептивное означает, что в CMM нет необходимости. В то время как Media-Relative Colorimetric, с другой стороны ...

Также opRGB такой же, как Adobe RGB 1998 (в основных цветах и ​​передаточной функции). См. МЭК 61966-2-5-2007. У меня стандартная, матрица на XYZ тоже такая же. Даже Black XYZ такой же. Даже нормализованные абсолютные трехцветные значения XYZ для кодирования одинаковы и говорят, что трехцветные значения XYZ 0,000 0, 0,000 0, 0,000 0 должны соответствовать наблюдаемой наблюдателем черной точке эталонного дисплея и нормализованным значениям трехцветного стимула XYZ 0,9505, 1,0000, 1, 0891 должен соответствовать эталонному уровню яркости дисплея и точке белого, как в профиле ICC.

person Валерий Заподовников    schedule 06.02.2021