PNG выводит альфа-канал, но без RGB, а JPG выводит RGB, но без альфа - PullRequest
0 голосов
/ 15 апреля 2019

Я хочу разделить файл PNG на еще 4 PNG, 3 для RGB и один альфа. Когда я ввожу PNG, альфа-канал выводится правильно, но каналы RGB ничего не выводят. Если я ввожу JPG, каналы RGB выводятся правильно, но альфа не работает, потому что нет альфа-канала для получения.

Я пытался использовать несколько изображений, все из которых были PNG или JPG, и все они терпели неудачу так же, как я описал.

val original = ImageIO.read(File("images/input.png"))

val alpha = BufferedImage(original.width, original.height, original.type)
val red = BufferedImage(original.width, original.height, original.type)
val green = BufferedImage(original.width, original.height, original.type)
val blue = BufferedImage(original.width, original.height, original.type)

for (y in 0 until original.height) {
    for (x in 0 until original.width) {
        val color = original.getRGB(x,y)

        val a = color  and 0xff000000.toInt()
        val r = color  and 0x00ff0000
        val g = color  and 0x0000ff00
        val b = color  and 0x000000ff

        alpha.setRGB(x,y,a)
        red.setRGB(x,y,r)
        green.setRGB(x,y,g)
        blue.setRGB(x,y,b)

    }
}

ImageIO.write(alpha,"png", File("images/alpha.png"))
ImageIO.write(red,"png", File("images/red.png"))
ImageIO.write(green,"png", File("images/green.png"))
ImageIO.write(blue,"png", File("images/blue.png"))

Я ожидаю получить 4 выхода только с соответствующими каналами, но получаю только альфа-канал с PNG и без альфа-канала с JPG.

Ответы [ 3 ]

1 голос
/ 16 апреля 2019

setRGB использует TYPE_INT_ARGB в качестве цветовой модели.Поскольку ваши битовые маски устанавливают альфа-канал на 0, изображения кажутся пустыми.Установите альфа на ff для изображений, которые будут показаны.

val a = color and 0xff000000.toInt()
val r = (color and 0x00ff0000) or 0xff000000.toInt()
val g = (color and 0x0000ff00) or 0xff000000.toInt()
val b = (color and 0x000000ff) or 0xff000000.toInt() 
0 голосов
/ 16 апреля 2019

Причина, по которой ваш код не работает должным образом, отчасти потому, что вы создаете новые BufferedImage s на основе исходного типа:

BufferedImage(original.width, original.height, original.type)

Тип оригинала зависит от входного изображения . Для JPEG это обычно будет TYPE_3BYTE_BGR (в котором нет альфы). Для PNG это зависит от типа или PNG (оттенки серого, палитра, истинный цвет, с альфа-каналом или без него и т. Д.). Ваш входной PNG, кажется, имеет истинный цвет с альфа, вероятно, в результате TYPE_4BYTE_ABGR или TYPE_INT_ARGB

Вместо этого вы можете создать 4 изображения в градациях серого (только «уровни»), используя TYPE_BYTE_GRAY, или, как вы делаете сейчас, 4 изображения ARGB, используя TYPE_INT_ARGB (извините, если мой синтаксис Kotlin отключен, я в основном программирую на Java эти дней):

BufferedImage(original.width, original.height, BufferedImage.TYPE_INT_ARGB)

Далее, как уже указывал @AlexanderEgger, методы set/getRGB работают в упакованном формате ARGB, поэтому вам нужно убедиться, что цвета непрозрачны (and с , просто цветовой маской, приведет к полностью прозрачному цвету):

val a = color and 0xff000000.toInt()
val r = (color and 0x00ff0000) or 0xff000000.toInt()
val g = (color and 0x0000ff00) or 0xff000000.toInt()
val b = (color and 0x000000ff) or 0xff000000.toInt()  

Или, если вам нравится подход с уровнями, вы делаете то, что предлагает @MarkSetchell, и создаете все серые изображения (опять же, синтаксис Kotlin может быть немного неправильным):

BufferedImage(original.width, original.height, BufferedImage.TYPE_BYTE_GRAY)

...

val a = (color >> 24) and 0xff
val r = (color >> 16) and 0xff
val g = (color >>  8) and 0xff
val b =  color        and 0xff

val aa = 0xff000000.toInt() or (a << 16) or (a << 8) or a
val rr = 0xff000000.toInt() or (r << 16) or (r << 8) or r
val gg = 0xff000000.toInt() or (g << 16) or (g << 8) or g
val bb = 0xff000000.toInt() or (b << 16) or (b << 8) or b

(и передать aa, rr, gg и bb до setRGB).

0 голосов
/ 16 апреля 2019

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

...