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 const val PLAY_SONG_BY_ITSELF = 0xA124
/** CoverMode.SaveSpace */ /** CoverMode.SaveSpace */
const val COVER_MODE_SAVE_SPACE = 0xA125 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, OFF,
SAVE_SPACE, SAVE_SPACE,
BALANCED, BALANCED,
HIGH_QUALITY; HIGH_QUALITY,
AS_IS;
/** /**
* The integer representation of this instance. * The integer representation of this instance.
@ -43,6 +44,7 @@ enum class CoverMode {
SAVE_SPACE -> IntegerTable.COVER_MODE_SAVE_SPACE SAVE_SPACE -> IntegerTable.COVER_MODE_SAVE_SPACE
BALANCED -> IntegerTable.COVER_MODE_BALANCED BALANCED -> IntegerTable.COVER_MODE_BALANCED
HIGH_QUALITY -> IntegerTable.COVER_MODE_HIGH_QUALITY HIGH_QUALITY -> IntegerTable.COVER_MODE_HIGH_QUALITY
AS_IS -> IntegerTable.COVER_MODE_AS_IS
} }
companion object { companion object {
@ -59,6 +61,7 @@ enum class CoverMode {
IntegerTable.COVER_MODE_SAVE_SPACE -> SAVE_SPACE IntegerTable.COVER_MODE_SAVE_SPACE -> SAVE_SPACE
IntegerTable.COVER_MODE_BALANCED -> BALANCED IntegerTable.COVER_MODE_BALANCED -> BALANCED
IntegerTable.COVER_MODE_HIGH_QUALITY -> HIGH_QUALITY IntegerTable.COVER_MODE_HIGH_QUALITY -> HIGH_QUALITY
IntegerTable.COVER_MODE_AS_IS -> AS_IS
else -> null else -> null
} }
} }

View file

@ -24,13 +24,16 @@ import javax.inject.Inject
import org.oxycblt.auxio.image.CoverMode import org.oxycblt.auxio.image.CoverMode
import org.oxycblt.auxio.image.ImageSettings import org.oxycblt.auxio.image.ImageSettings
import org.oxycblt.musikr.cover.Cover import org.oxycblt.musikr.cover.Cover
import org.oxycblt.musikr.cover.CoverFormat
import org.oxycblt.musikr.cover.CoverIdentifier import org.oxycblt.musikr.cover.CoverIdentifier
import org.oxycblt.musikr.cover.CoverParams import org.oxycblt.musikr.cover.CoverParams
import org.oxycblt.musikr.cover.Covers import org.oxycblt.musikr.cover.Covers
import org.oxycblt.musikr.cover.FileCover import org.oxycblt.musikr.cover.FileCover
import org.oxycblt.musikr.cover.FolderCovers import org.oxycblt.musikr.cover.FolderCovers
import org.oxycblt.musikr.cover.MutableCovers import org.oxycblt.musikr.cover.MutableCovers
import org.oxycblt.musikr.cover.MutableFileCovers
import org.oxycblt.musikr.cover.MutableFolderCovers import org.oxycblt.musikr.cover.MutableFolderCovers
import org.oxycblt.musikr.fs.app.AppFiles
interface SettingCovers { interface SettingCovers {
suspend fun mutate(context: Context, revision: UUID): MutableCovers<out Cover> 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.SAVE_SPACE -> siloedCovers(context, revision, CoverParams.of(500, 70))
CoverMode.BALANCED -> siloedCovers(context, revision, CoverParams.of(750, 85)) CoverMode.BALANCED -> siloedCovers(context, revision, CoverParams.of(750, 85))
CoverMode.HIGH_QUALITY -> siloedCovers(context, revision, CoverParams.of(1000, 100)) 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) = private suspend fun siloedCovers(context: Context, revision: UUID, with: CoverParams) =
MutableCovers.chain( MutableCovers.chain(
MutableSiloedCovers.from(context, CoverSilo(revision, with), identifier), MutableSiloedCovers.from(context, CoverSilo(revision, with), identifier),
MutableFolderCovers(context)) 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_save_space</item>
<item>@string/set_cover_mode_balanced</item> <item>@string/set_cover_mode_balanced</item>
<item>@string/set_cover_mode_high_quality</item> <item>@string/set_cover_mode_high_quality</item>
<item>@string/set_cover_mode_as_is</item>
</string-array> </string-array>
<integer-array name="values_cover_mode"> <integer-array name="values_cover_mode">
@ -86,6 +87,7 @@
<item>@integer/cover_mode_save_space</item> <item>@integer/cover_mode_save_space</item>
<item>@integer/cover_mode_balanced</item> <item>@integer/cover_mode_balanced</item>
<item>@integer/cover_mode_high_quality</item> <item>@integer/cover_mode_high_quality</item>
<item>@integer/cover_mode_as_is</item>
</integer-array> </integer-array>
<string-array name="entries_bar_action"> <string-array name="entries_bar_action">
@ -182,4 +184,5 @@
<integer name="cover_mode_save_space">0xA125</integer> <integer name="cover_mode_save_space">0xA125</integer>
<integer name="cover_mode_balanced">0xA11D</integer> <integer name="cover_mode_balanced">0xA11D</integer>
<integer name="cover_mode_high_quality">0xA11E</integer> <integer name="cover_mode_high_quality">0xA11E</integer>
<integer name="cover_mode_as_is">0xA126</integer>
</resources> </resources>

View file

@ -287,6 +287,7 @@
<string name="set_cover_mode_save_space">Save space</string> <string name="set_cover_mode_save_space">Save space</string>
<string name="set_cover_mode_balanced">Balanced</string> <string name="set_cover_mode_balanced">Balanced</string>
<string name="set_cover_mode_high_quality">High quality</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">Force square album covers</string>
<string name="set_square_covers_desc">Crop all album covers to a 1:1 aspect ratio</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 { companion object {
fun jpeg(params: CoverParams): CoverFormat = 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, override val extension: String,
private val params: CoverParams, private val params: CoverParams,
private val format: Bitmap.CompressFormat, private val format: Bitmap.CompressFormat,
@ -63,3 +65,16 @@ private class CoverFormatImpl(
return inSampleSize 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 = val cover =
when (val result = when (val result =
covers.create(f, extractedMetadata)) { covers.create(f, extractedMetadata)) {
is CoverResult.Hit<Cover> -> result.cover is CoverResult.Hit -> result.cover
else -> null else -> null
} }
val rawSong = val rawSong =