dekstop: image compression (#2979)

* dekstop: image compression

* refactor
This commit is contained in:
Stanislav Dmitrenko
2023-08-25 19:28:39 +03:00
committed by GitHub
parent 7fc108e6fa
commit 96b253c3e7
4 changed files with 42 additions and 8 deletions

View File

@@ -62,7 +62,7 @@ actual fun cropToSquare(image: ImageBitmap): ImageBitmap {
}
actual fun compressImageStr(bitmap: ImageBitmap): String {
val usePng = bitmap.hasAlpha
val usePng = bitmap.hasAlpha()
val ext = if (usePng) "png" else "jpg"
return "data:image/$ext;base64," + Base64.encodeToString(compressImageData(bitmap, usePng).toByteArray(), Base64.NO_WRAP)
}
@@ -89,6 +89,8 @@ actual fun resizeImageToDataSize(image: ImageBitmap, usePng: Boolean, maxDataSiz
actual fun GrayU8.toImageBitmap(): ImageBitmap = ConvertBitmap.grayToBitmap(this, Bitmap.Config.RGB_565).asImageBitmap()
actual fun ImageBitmap.hasAlpha(): Boolean = hasAlpha
actual fun ImageBitmap.addLogo(): ImageBitmap = asAndroidBitmap().applyCanvas {
val radius = (width * 0.16f) / 2
val paint = android.graphics.Paint()

View File

@@ -15,6 +15,7 @@ expect fun compressImageData(bitmap: ImageBitmap, usePng: Boolean): ByteArrayOut
expect fun GrayU8.toImageBitmap(): ImageBitmap
expect fun ImageBitmap.hasAlpha(): Boolean
expect fun ImageBitmap.addLogo(): ImageBitmap
expect fun ImageBitmap.scale(width: Int, height: Int): ImageBitmap

View File

@@ -102,7 +102,7 @@ fun saveImage(uri: URI): String? {
fun saveImage(image: ImageBitmap): String? {
return try {
val ext = if (image.hasAlpha) "png" else "jpg"
val ext = if (image.hasAlpha()) "png" else "jpg"
val dataResized = resizeImageToDataSize(image, ext == "png", maxDataSize = MAX_IMAGE_SIZE)
val fileToSave = generateNewFileName("IMG", ext)
val file = File(getAppFilePath(fileToSave))
@@ -112,7 +112,7 @@ fun saveImage(image: ImageBitmap): String? {
output.close()
fileToSave
} catch (e: Exception) {
Log.e(TAG, "Util.kt saveImage error: ${e.message}")
Log.e(TAG, "Util.kt saveImage error: ${e.stackTraceToString()}")
null
}
}

View File

@@ -10,7 +10,8 @@ import java.awt.image.BufferedImage
import java.io.*
import java.net.URI
import java.util.*
import javax.imageio.ImageIO
import javax.imageio.*
import javax.imageio.stream.MemoryCacheImageOutputStream
import kotlin.math.sqrt
private fun errorBitmap(): ImageBitmap =
@@ -69,7 +70,7 @@ actual fun cropToSquare(image: ImageBitmap): ImageBitmap {
}
actual fun compressImageStr(bitmap: ImageBitmap): String {
val usePng = bitmap.hasAlpha
val usePng = bitmap.hasAlpha()
val ext = if (usePng) "png" else "jpg"
return try {
val encoded = Base64.getEncoder().encodeToString(compressImageData(bitmap, usePng).toByteArray())
@@ -81,15 +82,45 @@ actual fun compressImageStr(bitmap: ImageBitmap): String {
}
actual fun compressImageData(bitmap: ImageBitmap, usePng: Boolean): ByteArrayOutputStream {
val writer = ImageIO.getImageWritersByFormatName(if (usePng) "png" else "jpg").next()
val writeParam = writer.defaultWriteParam
writeParam.compressionMode = ImageWriteParam.MODE_EXPLICIT
writeParam.compressionQuality = 0.85f
val stream = ByteArrayOutputStream()
stream.use { s -> ImageIO.write(bitmap.toAwtImage(), if (usePng) "png" else "jpg", s) }
// MAKE REAL COMPRESSION
//bitmap.compress(if (!usePng) Bitmap.CompressFormat.JPEG else Bitmap.CompressFormat.PNG, 85, stream)
writer.output = MemoryCacheImageOutputStream(stream)
val outputImage = IIOImage(if (usePng) bitmap.toAwtImage() else removeAlphaChannel(bitmap.toAwtImage()), null, null)
writer.write(null, outputImage, writeParam)
writer.dispose()
stream.flush()
return stream
}
private fun removeAlphaChannel(img: BufferedImage): BufferedImage {
if (!img.colorModel.hasAlpha()) return img
val target = BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_RGB)
val g = target.createGraphics()
g.fillRect(0, 0, img.width, img.height)
g.drawImage(img, 0, 0, null)
g.dispose()
return target
}
actual fun GrayU8.toImageBitmap(): ImageBitmap = ConvertBufferedImage.extractBuffered(this).toComposeImageBitmap()
actual fun ImageBitmap.hasAlpha(): Boolean {
val map = toPixelMap()
var y = 0
while (y < height) {
var x = 0
while (x < width) {
if (map[x, y].alpha < 1f) return true
x++
}
y++
}
return false
}
actual fun ImageBitmap.addLogo(): ImageBitmap {
val radius = (width * 0.16f).toInt()
val logoSize = (width * 0.24).toInt()