From 6cd689dfbfea29eff519910d67774453bf3bad6f Mon Sep 17 00:00:00 2001 From: Deluan Date: Wed, 1 Apr 2026 23:01:02 -0400 Subject: [PATCH] refactor(artwork): rename DevJpegCoverArt to EnableWebPEncoding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced the internal DevJpegCoverArt flag with a user-facing EnableWebPEncoding config option (defaults to true). When disabled, the fallback encoding now preserves the original image format — PNG sources stay PNG for non-square resizes, matching v0.60.3 behavior. The previous implementation incorrectly re-encoded PNG sources as JPEG in non-square mode. Also added EnableWebPEncoding to the insights data. --- conf/configuration.go | 4 ++-- core/artwork/artwork_internal_test.go | 12 ++++++------ core/artwork/reader_resized.go | 14 ++++++-------- core/metrics/insights.go | 1 + core/metrics/insights/data.go | 1 + 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/conf/configuration.go b/conf/configuration.go index fce5e0b2f..abb891138 100644 --- a/conf/configuration.go +++ b/conf/configuration.go @@ -70,6 +70,7 @@ type configOptions struct { MPVCmdTemplate string CoverArtPriority string CoverArtQuality int + EnableWebPEncoding bool ArtistArtPriority string ArtistImageFolder string DiscArtPriority string @@ -141,7 +142,6 @@ type configOptions struct { DevOptimizeDB bool DevPreserveUnicodeInExternalCalls bool DevEnableMediaFileProbe bool - DevJpegCoverArt bool } type scannerOptions struct { @@ -716,6 +716,7 @@ func setViperDefaults() { viper.SetDefault("mpvcmdtemplate", "mpv --audio-device=%d --no-audio-display %f --input-ipc-server=%s") viper.SetDefault("coverartpriority", "cover.*, folder.*, front.*, embedded, external") viper.SetDefault("coverartquality", 75) + viper.SetDefault("enablewebpencoding", true) viper.SetDefault("artistartpriority", "artist.*, album/artist.*, external") viper.SetDefault("artistimagefolder", "") viper.SetDefault("discartpriority", "disc*.*, cd*.*, cover.*, folder.*, front.*, discsubtitle, embedded") @@ -826,7 +827,6 @@ func setViperDefaults() { viper.SetDefault("devoptimizedb", true) viper.SetDefault("devpreserveunicodeinexternalcalls", false) viper.SetDefault("devenablemediafileprobe", true) - viper.SetDefault("devjpegcoverart", false) } func init() { diff --git a/core/artwork/artwork_internal_test.go b/core/artwork/artwork_internal_test.go index 4b2359898..a905990e7 100644 --- a/core/artwork/artwork_internal_test.go +++ b/core/artwork/artwork_internal_test.go @@ -436,18 +436,18 @@ var _ = Describe("Artwork", func() { Entry("landscape jpg image", "jpg", "webp", true, 200), ) }) - When("DevJpegCoverArt is true and square is false", func() { + When("EnableWebPEncoding is false and square is false", func() { BeforeEach(func() { - conf.Server.DevJpegCoverArt = true + conf.Server.EnableWebPEncoding = false }) - It("returns JPEG even if original image is a PNG", func() { + It("returns PNG if original image is a PNG", func() { conf.Server.CoverArtPriority = "front.png" r, _, err := aw.Get(context.Background(), alMultipleCovers.CoverArtID(), 15, false) Expect(err).ToNot(HaveOccurred()) img, format, err := image.Decode(r) Expect(err).ToNot(HaveOccurred()) - Expect(format).To(Equal("jpeg")) + Expect(format).To(Equal("png")) Expect(img.Bounds().Size().X).To(Equal(15)) Expect(img.Bounds().Size().Y).To(Equal(15)) }) @@ -463,11 +463,11 @@ var _ = Describe("Artwork", func() { Expect(img.Bounds().Size().Y).To(Equal(200)) }) }) - When("DevJpegCoverArt is true and square is true", func() { + When("EnableWebPEncoding is false and square is true", func() { var alCover model.Album BeforeEach(func() { - conf.Server.DevJpegCoverArt = true + conf.Server.EnableWebPEncoding = false }) It("returns PNG for square mode", func() { dirName := createImage("png", false, 200) diff --git a/core/artwork/reader_resized.go b/core/artwork/reader_resized.go index 88ca8b83b..1f45e120c 100644 --- a/core/artwork/reader_resized.go +++ b/core/artwork/reader_resized.go @@ -117,7 +117,7 @@ func (a *resizedArtworkReader) resizeImage(ctx context.Context, reader io.Reader } func resizeStaticImage(data []byte, size int, square bool) (io.Reader, int, error) { - original, _, err := image.Decode(bytes.NewReader(data)) + original, format, err := image.Decode(bytes.NewReader(data)) if err != nil { return nil, 0, err } @@ -157,14 +157,12 @@ func resizeStaticImage(data []byte, size int, square bool) (io.Reader, int, erro buf := bufPool.Get().(*bytes.Buffer) buf.Reset() - if conf.Server.DevJpegCoverArt { - if square { - err = png.Encode(buf, dst) - } else { - err = jpeg.Encode(buf, dst, &jpeg.Options{Quality: conf.Server.CoverArtQuality}) - } - } else { + if conf.Server.EnableWebPEncoding { err = webp.Encode(buf, dst, webp.Options{Quality: conf.Server.CoverArtQuality}) + } else if format == "png" || square { + err = png.Encode(buf, dst) + } else { + err = jpeg.Encode(buf, dst, &jpeg.Options{Quality: conf.Server.CoverArtQuality}) } if err != nil { bufPool.Put(buf) diff --git a/core/metrics/insights.go b/core/metrics/insights.go index b87f1df5e..1dcd13b25 100644 --- a/core/metrics/insights.go +++ b/core/metrics/insights.go @@ -195,6 +195,7 @@ var staticData = sync.OnceValue(func() insights.Data { data.Config.EnableArtworkPrecache = conf.Server.EnableArtworkPrecache data.Config.EnableArtworkUpload = conf.Server.EnableArtworkUpload data.Config.CoverArtQuality = conf.Server.CoverArtQuality + data.Config.EnableWebPEncoding = conf.Server.EnableWebPEncoding data.Config.EnableCoverAnimation = conf.Server.EnableCoverAnimation data.Config.EnableNowPlaying = conf.Server.EnableNowPlaying data.Config.EnableDownloads = conf.Server.EnableDownloads diff --git a/core/metrics/insights/data.go b/core/metrics/insights/data.go index b316c866d..06a20b6f8 100644 --- a/core/metrics/insights/data.go +++ b/core/metrics/insights/data.go @@ -65,6 +65,7 @@ type Data struct { EnablePrometheus bool `json:"enablePrometheus,omitempty"` EnableArtworkUpload bool `json:"enableArtworkUpload,omitempty"` CoverArtQuality int `json:"coverArtQuality,omitempty"` + EnableWebPEncoding bool `json:"enableWebPEncoding,omitempty"` EnableCoverAnimation bool `json:"enableCoverAnimation,omitempty"` EnableNowPlaying bool `json:"enableNowPlaying,omitempty"` SessionTimeout uint64 `json:"sessionTimeout,omitempty"`