fix: ignore alpha channel on image conversion

if image to convert targets a format that doesn't support transparency, but contains alpha channel, then the alpha channel will be ignore. Non-opaque images may produce visual artifacts.

related to #153
This commit is contained in:
Gauthier Roebroeck 2020-05-08 15:43:04 +08:00
parent 816bbdb8f3
commit 9556ae51f2

View file

@ -3,6 +3,8 @@ package org.gotson.komga.infrastructure.image
import mu.KotlinLogging
import net.coobird.thumbnailator.Thumbnails
import org.springframework.stereotype.Service
import java.awt.Color
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import javax.imageio.ImageIO
@ -23,11 +25,25 @@ class ImageConverter {
logger.info { "Supported write mediaTypes: $supportedWriteMediaTypes" }
}
private val supportsTransparency = listOf("png")
fun convertImage(imageBytes: ByteArray, format: String): ByteArray =
ByteArrayOutputStream().use {
ByteArrayOutputStream().use { baos ->
val image = ImageIO.read(imageBytes.inputStream())
ImageIO.write(image, format, it)
it.toByteArray()
val result = if (!supportsTransparency.contains(format) && containsAlphaChannel(image)) {
if (containsTransparency(image)) logger.info { "Image contains alpha channel but is not opaque, visual artifacts may appear" }
else logger.info { "Image contains alpha channel but is opaque, conversion should not generate any visual artifacts" }
BufferedImage(image.width, image.height, BufferedImage.TYPE_INT_RGB).also {
it.createGraphics().drawImage(image, 0, 0, Color.WHITE, null)
}
} else {
image
}
ImageIO.write(result, format, baos)
baos.toByteArray()
}
fun resizeImage(imageBytes: ByteArray, format: String, size: Int): ByteArray =
@ -38,4 +54,17 @@ class ImageConverter {
.toOutputStream(it)
it.toByteArray()
}
private fun containsAlphaChannel(image: BufferedImage): Boolean =
image.colorModel.hasAlpha()
private fun containsTransparency(image: BufferedImage): Boolean {
for (x in 0 until image.width) {
for (y in 0 until image.height) {
val pixel = image.getRGB(x, y)
if (pixel shr 24 == 0x00) return true
}
}
return false
}
}