Определение цветового пространства для JPEG - PullRequest
0 голосов
/ 11 июня 2018

Я пишу код для определения цветового пространства изображения JPEG.Я нашел две ссылки, которые могут помочь мне реализовать это.Один находится на oracle.com , другой - на исходном коде C из ijg.com , который "отвечает за эталонную реализацию исходного стандарта JPEG".

Однако они отличаются.Например, в IJG, когда нет маркера Adobe и имеется 4 канала, он принимается за CMYK, но в oracle это YCCA.Также реализация IJG не смотрит на субсэмплинг, тогда как для 4-канального субсэмплирования это - YCCK в спецификациях oracle и т. Д.указать 3 дополнительных цветовых пространства, таких как YCCK, YCCA, RGBA.

Еще один момент заключается в том, что я нашел информацию о том, что JPEG не поддерживает прозрачность в альфа-канале здесь , зачем оракулу говорить о YCCAи RGBA в контексте спецификации метаданных JPEG?

В результате при проверке изображения с помощью логики IJG он говорит мне, что это CMYK (проверено изображение с помощью ImageMagick в Ubuntu, а также говорится, что это CMYK), с оракуломлогика это YCCA.Кому верить?Почему оракул не полагается на оригинальную спецификацию JPEG?Или есть что-то еще, чего я не знаю?

Ответы [ 2 ]

0 голосов
/ 14 июня 2018

После моих комментариев к старым стандартам JPEG я наконец нашел ответ.

Вкл. ИСО / МЭК 10918-6: 2013 (E) , раздел 6.1:

  • Предполагается, что изображения, закодированные только с одним компонентом, представляют собой данные в градациях серого, в которых 0 - черный, а 255 - белый.

  • Изображения, закодированные с помощью трех компонентов,предполагается, что это данные RGB, закодированные как YCbCr, если только изображение не содержит сегмент маркера APP14, как указано в 6.5.3, и в этом случае цветовое кодирование рассматривается как RGB или YCbCr в соответствии с данными приложения сегмента маркера APP14.Отношение между RGB и YCbCr определяется, как указано в Рек.МСЭ-T T.871 |ИСО / МЭК 10918-5.

  • Предполагается, что изображения, кодированные четырьмя компонентами, имеют значение CMYK , где (0,0,0,0) обозначает белый цвет, если толькоизображение содержит сегмент маркера APP14, как указано в 6.5.3, и в этом случае кодирование цвета считается либо CMYK , либо YCCK в соответствии с данными приложения сегмента маркера APP14.Соотношение между CMYK и YCCK определено, как указано в разделе 7.

, а флаги APP14 - "Adobe\0"AP12 имеет флаг преобразования:

Должны поддерживаться значения флага преобразования 0, 1 и 2 и интерпретируются следующим образом:

0 - CMYK для кодированных изображенийс четырьмя компонентами, в которых все четыре значения CMYK дополняются;RGB для изображений, закодированных тремя компонентами;т. е. маркер APP14 не определяет преобразование, применяемое к данным изображения.

1 - изображение, закодированное с помощью трех компонентов с использованием цветовой кодировки YCbCr.

2 - изображение, закодированное с помощью четырех компонентов с использованиемЦветовая кодировка YCCK.

Таким образом, это зависит от CMYK, но это может быть YCCK, если APP14 и AP12 имеют правильные значения.

0 голосов
/ 14 июня 2018

Я изо всех сил пытался понять документ Oracle, на который вы ссылаетесь.

По моему опыту, после написания плагина JPEG для Java ImageIO , правильное решение - следовать реализации IJG.Это то, что делает большинство программного обеспечения, поэтому это создаст наименьшую путаницу среди ваших пользователей (т.е. «Почему мой образ выглядит по-разному в вашем программном обеспечении и программном обеспечении X?»).Алгоритм Sun / Oracle во многих случаях не согласуется с «остальным миром».

В итоге я реализовал несколько иной алгоритм, который учитывает «дополнительные» цветовые пространства Java, но в остальном остается очень близкимк реализации IJG:

// Adapted from libjpeg jdapimin.c:
// Guess the input colorspace
// (Wish JPEG committee had provided a real way to specify this...)
switch (startOfFrame.componentsInFrame()) {
    case 1:
        return JPEGColorSpace.Gray;
    case 2:
        return JPEGColorSpace.GrayA; // Java special case: Gray + Alpha
    case 3:
        if (jfif != null) {
            return JPEGColorSpace.YCbCr; // JFIF implies YCbCr
        }
        else if (adobeDCT != null) {
            switch (adobeDCT.transform) {
                case AdobeDCT.Unknown:
                    return JPEGColorSpace.RGB;
                case AdobeDCT.YCC:
                    return JPEGColorSpace.YCbCr;
                default:
                    // TODO: Warning!
                    return JPEGColorSpace.YCbCr; // assume it's YCbCr
            }
        }
        else {
            // Saw no special markers, try to guess from the component IDs
            int cid0 = startOfFrame.components[0].id;
            int cid1 = startOfFrame.components[1].id;
            int cid2 = startOfFrame.components[2].id;

            if (cid0 == 1 && cid1 == 2 && cid2 == 3) {
                return JPEGColorSpace.YCbCr; // assume JFIF w/out marker
            }
            else if (cid0 == 'R' && cid1 == 'G' && cid2 == 'B') {
                return JPEGColorSpace.RGB; // ASCII 'R', 'G', 'B'
            }
            else if (cid0 == 'Y' && cid1 == 'C' && cid2 == 'c') {
                return JPEGColorSpace.PhotoYCC; // Java special case: YCc
            }
            else {
                // TODO: Warning!
                return JPEGColorSpace.YCbCr; // assume it's YCbCr
            }
        }

    case 4:
        if (adobeDCT != null) {
            switch (adobeDCT.transform) {
                case AdobeDCT.Unknown:
                    return JPEGColorSpace.CMYK;
                case AdobeDCT.YCCK:
                    return JPEGColorSpace.YCCK;
                default:
                    // TODO: Warning!
                    return JPEGColorSpace.YCCK; // assume it's YCCK
            }
        }
        else {
            // Saw no special markers, try to guess from the component IDs
            int cid0 = startOfFrame.components[0].id;
            int cid1 = startOfFrame.components[1].id;
            int cid2 = startOfFrame.components[2].id;
            int cid3 = startOfFrame.components[3].id;

            if (cid0 == 1 && cid1 == 2 && cid2 == 3 && cid3 == 4) {
                return JPEGColorSpace.YCbCrA; // Java special case: YCbCrA
            }
            else if (cid0 == 'R' && cid1 == 'G' && cid2 == 'B' && cid3 == 'A') {
                return JPEGColorSpace.RGBA; // Java special case: RGBA
            }
            else if (cid0 == 'Y' && cid1 == 'C' && cid2 == 'c' && cid3 == 'A') {
                return JPEGColorSpace.PhotoYCCA; // Java special case: YCcA
            }
            else {
                // TODO: Warning!
                // No special markers, assume straight CMYK.
                return JPEGColorSpace.CMYK;
            }
        }

    default:
        throw new IIOException("Cannot determine source color space");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...