Пытаюсь прочитать PNG и xuggler

Я использую xuggler, чтобы поместить прозрачную маску в видео.

Я пытаюсь открыть действительный png с помощью ImageIO.read(), но когда он рендерится, на моей картинке всегда будет белый фон.

Это мой код для чтения.

        url = new URL(stringUrl);
        imagem = ImageIO.read(url);
        boolean hasAlpha = imagem.getColorModel().hasAlpha();

Это логическое всегда ложно.

И в Xuggler, когда я делаю рендер

mediaReader .setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);

Что я делаю не так?

1 ответ

"Проблема" с вашим исходным файлом изображения заключается в том, что это 24-битный RGB (3-канальный) PNG с tRNS Кусок.

tRNS кусок определяет цвет (255, 255, 255или белый, в данном случае), который должен быть заменен полностью прозрачными пикселями. По сути, применение этой прозрачности работает как битовая маска, где все пиксели либо полностью прозрачны, либо полностью непрозрачны. Однако, будучи "вспомогательным" (необязательным или некритическим) фрагментом в соответствии со спецификацией PNG, PNG-декодеры могут по своему выбору игнорировать эту информацию.

К сожалению, похоже, что по умолчанию PNGImageReader ("Плагин PNG") для ImageIO не применяет эту битовую маску, а вместо этого сохраняет изображение в полностью непрозрачном RGB (что по-прежнему соответствует спецификации поведения).

Ваш второй файл изображения - 32-битный RGBA (4 канала, включая альфа-канал). В этом случае любой читатель должен (и должен) декодировать все каналы, включая полный 8-битный альфа-канал. ImageIO-х PNGImageReader действительно декодирует это с ожидаемой прозрачностью.


PS: Возможно, возможно "исправить" прозрачность вашего первого изображения, используя метаданные.

Метаданные для вашего изображения содержат следующую информацию в собственном формате PNG:

<javax_imageio_png_1.0>
    ....
    <tRNS>
        <tRNS_RGB red="255" green="255" blue="255"/>
    </tRNS>
</javax_imageio_png_1.0>

После анализа этого вы можете преобразовать изображение, сначала создав новое 4-канальное изображение (например, TYPE_4BYTE_ABGR), копируя каналы R, G и B в это новое изображение, и, наконец, установите альфа-канал на 0 для (все пиксели, которые соответствуют прозрачному цвету), или 255 (для всех остальных).

PPS: Вы, вероятно, хотите выполнить эти операции непосредственно на Rasterс, как с помощью BufferedImage.getRGB(..)/setRGB(..) методы преобразуют значения в sRGB цветовой профиль, который может не совсем соответствовать значению RGB из tRNS Кусок.

Там вы идете!:-)

Другие вопросы по тегам