musikr.cover: use jpeg for covers

Way faster to encode and the artifacts are minimal at 1kx1k and 100
compression.

Still not fully ideal, but webp is so flow to encode.
This commit is contained in:
Alexander Capehart 2024-12-20 22:05:51 -05:00
parent 1843986f75
commit a598f39dea
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
2 changed files with 29 additions and 20 deletions

View file

@ -35,7 +35,7 @@ interface CoverFiles {
companion object { companion object {
fun at(context: Context, path: String): CoverFiles = fun at(context: Context, path: String): CoverFiles =
CoverFilesImpl(File(context.filesDir, path).also { it.mkdirs() }, CoverFormat.webp()) CoverFilesImpl(File(context.filesDir, path).also { it.mkdirs() }, CoverFormat.jpeg())
} }
} }

View file

@ -29,21 +29,42 @@ internal interface CoverFormat {
fun transcodeInto(data: ByteArray, output: OutputStream): Boolean fun transcodeInto(data: ByteArray, output: OutputStream): Boolean
companion object { companion object {
fun webp(): CoverFormat = WebpCoverFormat() // Enable if perhaps you want to try other formats.
// Currently this is just far too slow.
// fun webp(): CoverFormat = CoverFormatImpl(
// "webp",
// 750,
// 80,
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Bitmap.CompressFormat.WEBP_LOSSY
// } else {
// Bitmap.CompressFormat.WEBP
// }
// )
fun jpeg(): CoverFormat = CoverFormatImpl(
"jpg",
1000,
100,
Bitmap.CompressFormat.JPEG
)
} }
} }
private class WebpCoverFormat() : CoverFormat { private class CoverFormatImpl(
override val extension = EXTENSION override val extension: String,
val size: Int,
val quality: Int,
val format: Bitmap.CompressFormat,
) : CoverFormat {
override fun transcodeInto(data: ByteArray, output: OutputStream) = override fun transcodeInto(data: ByteArray, output: OutputStream) =
BitmapFactory.Options().run { BitmapFactory.Options().run {
inJustDecodeBounds = true inJustDecodeBounds = true
BitmapFactory.decodeByteArray(data, 0, data.size, this) BitmapFactory.decodeByteArray(data, 0, data.size, this)
inSampleSize = calculateInSampleSize(SIZE) inSampleSize = calculateInSampleSize(size)
inJustDecodeBounds = false inJustDecodeBounds = false
val bitmap = BitmapFactory.decodeByteArray(data, 0, data.size, this) ?: return@run false val bitmap = BitmapFactory.decodeByteArray(data, 0, data.size, this) ?: return@run false
bitmap.compress(FORMAT, QUALITY, output) bitmap.compress(format, quality, output)
true true
} }
@ -60,16 +81,4 @@ private class WebpCoverFormat() : CoverFormat {
} }
return inSampleSize return inSampleSize
} }
private companion object {
const val SIZE = 750
val FORMAT =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Bitmap.CompressFormat.WEBP_LOSSY
} else {
Bitmap.CompressFormat.WEBP
}
const val QUALITY = 80
const val EXTENSION = "webp"
}
} }