PNG输出alpha通道但不输出RGB,JPG输出RGB但不输出alpha

时间:2019-04-15 16:23:00

标签: image-processing kotlin png jpeg rgba

我想将一个PNG文件拆分为另外4个PNG,其中3个用于RGB,一个Alpha。当我输入PNG时,alpha通道会正确输出,但是RGB通道什么也不会输出。如果我输入JPG,则RGB通道可以正确输出,但是alpha失败,因为没有Alpha通道。

我尝试使用多幅图像,这些图像都是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的Alpha通道,而不接收带有JPG的Alpha通道。

3 个答案:

答案 0 :(得分:1)

setRGB使用TYPE_INT_ARGB作为颜色模型。当您的位掩码将Alpha通道设置为0时,图像似乎为空。将alpha设置为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() 

答案 1 :(得分:0)

JPEG文件格式不包含任何Alpha通道-使用JPEG重新创建某种透明度的方法是添加由单色图像组成的另一层,然后通过该图像过滤图像,但这确实很特别用例,在此示例中您很可能不想执行任何操作。

答案 2 :(得分:0)

您的代码无法按预期运行的部分原因是,您根据原始类型创建了新的BufferedImage

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

原始类型将根据输入图像而有所不同。对于JPEG,通常为TYPE_3BYTE_BGR(不包含alpha)。对于PNG,它取决于类型或PNG(灰度,调色板,真彩色,带有或不带有alpha等)。您输入的PNG似乎是带有alpha的真彩色,可能会导致TYPE_4BYTE_ABGRTYPE_INT_ARGB

相反,您可以使用TYPE_BYTE_GRAY创建4个灰度图像(只是“级别”),或者像现在一样,使用TYPE_INT_ARGB创建4个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

(并将aarrggbb传递到setRGB)。