app: introduce as-is covers

Risks extreme instability since I am no longer in control of format,
but some users just want very high-quality covers.
This commit is contained in:
Alexander Capehart 2025-03-03 13:09:26 -07:00
parent a7000bc9e5
commit 4fbbbfdc76
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
7 changed files with 40 additions and 4 deletions

View file

@ -141,4 +141,6 @@ object IntegerTable {
const val PLAY_SONG_BY_ITSELF = 0xA124
/** CoverMode.SaveSpace */
const val COVER_MODE_SAVE_SPACE = 0xA125
/** CoverMode.AsIs */
const val COVER_MODE_AS_IS = 0xA126
}

View file

@ -29,7 +29,8 @@ enum class CoverMode {
OFF,
SAVE_SPACE,
BALANCED,
HIGH_QUALITY;
HIGH_QUALITY,
AS_IS;
/**
* The integer representation of this instance.
@ -43,6 +44,7 @@ enum class CoverMode {
SAVE_SPACE -> IntegerTable.COVER_MODE_SAVE_SPACE
BALANCED -> IntegerTable.COVER_MODE_BALANCED
HIGH_QUALITY -> IntegerTable.COVER_MODE_HIGH_QUALITY
AS_IS -> IntegerTable.COVER_MODE_AS_IS
}
companion object {
@ -59,6 +61,7 @@ enum class CoverMode {
IntegerTable.COVER_MODE_SAVE_SPACE -> SAVE_SPACE
IntegerTable.COVER_MODE_BALANCED -> BALANCED
IntegerTable.COVER_MODE_HIGH_QUALITY -> HIGH_QUALITY
IntegerTable.COVER_MODE_AS_IS -> AS_IS
else -> null
}
}

View file

@ -24,13 +24,16 @@ import javax.inject.Inject
import org.oxycblt.auxio.image.CoverMode
import org.oxycblt.auxio.image.ImageSettings
import org.oxycblt.musikr.cover.Cover
import org.oxycblt.musikr.cover.CoverFormat
import org.oxycblt.musikr.cover.CoverIdentifier
import org.oxycblt.musikr.cover.CoverParams
import org.oxycblt.musikr.cover.Covers
import org.oxycblt.musikr.cover.FileCover
import org.oxycblt.musikr.cover.FolderCovers
import org.oxycblt.musikr.cover.MutableCovers
import org.oxycblt.musikr.cover.MutableFileCovers
import org.oxycblt.musikr.cover.MutableFolderCovers
import org.oxycblt.musikr.fs.app.AppFiles
interface SettingCovers {
suspend fun mutate(context: Context, revision: UUID): MutableCovers<out Cover>
@ -51,10 +54,19 @@ constructor(private val imageSettings: ImageSettings, private val identifier: Co
CoverMode.SAVE_SPACE -> siloedCovers(context, revision, CoverParams.of(500, 70))
CoverMode.BALANCED -> siloedCovers(context, revision, CoverParams.of(750, 85))
CoverMode.HIGH_QUALITY -> siloedCovers(context, revision, CoverParams.of(1000, 100))
CoverMode.AS_IS -> asIsCovers(context)
}
private suspend fun siloedCovers(context: Context, revision: UUID, with: CoverParams) =
MutableCovers.chain(
MutableSiloedCovers.from(context, CoverSilo(revision, with), identifier),
MutableFolderCovers(context))
private suspend fun asIsCovers(context: Context) =
MutableCovers.chain(
MutableFileCovers(
AppFiles.at(context.coversDir().resolve("asis").also { it.mkdirs() }),
CoverFormat.asIs(),
identifier),
MutableFolderCovers(context))
}

View file

@ -79,6 +79,7 @@
<item>@string/set_cover_mode_save_space</item>
<item>@string/set_cover_mode_balanced</item>
<item>@string/set_cover_mode_high_quality</item>
<item>@string/set_cover_mode_as_is</item>
</string-array>
<integer-array name="values_cover_mode">
@ -86,6 +87,7 @@
<item>@integer/cover_mode_save_space</item>
<item>@integer/cover_mode_balanced</item>
<item>@integer/cover_mode_high_quality</item>
<item>@integer/cover_mode_as_is</item>
</integer-array>
<string-array name="entries_bar_action">
@ -182,4 +184,5 @@
<integer name="cover_mode_save_space">0xA125</integer>
<integer name="cover_mode_balanced">0xA11D</integer>
<integer name="cover_mode_high_quality">0xA11E</integer>
<integer name="cover_mode_as_is">0xA126</integer>
</resources>

View file

@ -287,6 +287,7 @@
<string name="set_cover_mode_save_space">Save space</string>
<string name="set_cover_mode_balanced">Balanced</string>
<string name="set_cover_mode_high_quality">High quality</string>
<string name="set_cover_mode_as_is">As is</string>
<string name="set_square_covers">Force square album covers</string>
<string name="set_square_covers_desc">Crop all album covers to a 1:1 aspect ratio</string>

View file

@ -29,11 +29,13 @@ abstract class CoverFormat {
companion object {
fun jpeg(params: CoverParams): CoverFormat =
CoverFormatImpl("jpg", params, Bitmap.CompressFormat.JPEG)
CompressingCoverFormat("jpg", params, Bitmap.CompressFormat.JPEG)
fun asIs(): CoverFormat = AsIsCoverFormat()
}
}
private class CoverFormatImpl(
private class CompressingCoverFormat(
override val extension: String,
private val params: CoverParams,
private val format: Bitmap.CompressFormat,
@ -63,3 +65,16 @@ private class CoverFormatImpl(
return inSampleSize
}
}
private class AsIsCoverFormat : CoverFormat() {
override val extension: String = "bin"
override fun transcodeInto(data: ByteArray, output: OutputStream): Boolean {
return try {
output.write(data)
true
} catch (e: Exception) {
false
}
}
}

View file

@ -126,7 +126,7 @@ private class ExtractStepImpl(
val cover =
when (val result =
covers.create(f, extractedMetadata)) {
is CoverResult.Hit<Cover> -> result.cover
is CoverResult.Hit -> result.cover
else -> null
}
val rawSong =