From c5e47cbc8cfa0e0efc44d3c1a4b7ae5188e956ec Mon Sep 17 00:00:00 2001 From: Claudio Ortolina Date: Sat, 7 Jun 2025 20:07:23 +0100 Subject: [PATCH] Display dominant colors from the db --- lib/music_library/records/dominant_colors.ex | 11 ++++++ lib/music_library/records/record.ex | 34 ++++++++++++++++++- .../live/collection_live/show.html.heex | 2 +- .../live/wishlist_live/show.html.heex | 2 +- ...7185415_add_dominant_colors_to_records.exs | 9 +++++ test/music_library/records_test.exs | 8 +++++ .../support/fixtures/music_library/records.ex | 3 +- 7 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 priv/repo/migrations/20250607185415_add_dominant_colors_to_records.exs diff --git a/lib/music_library/records/dominant_colors.ex b/lib/music_library/records/dominant_colors.ex index e1562131..c36789be 100644 --- a/lib/music_library/records/dominant_colors.ex +++ b/lib/music_library/records/dominant_colors.ex @@ -21,6 +21,17 @@ defmodule MusicLibrary.Records.DominantColors do end end + @doc """ + Same as `extract-dominant_colors/2`, but raises an error if extraction fails. + """ + @spec extract_dominant_colors!(binary(), pos_integer()) :: [String.t()] | no_return + def extract_dominant_colors!(image_data, num_colors \\ 5) do + case extract_dominant_colors(image_data, num_colors) do + {:ok, colors} -> colors + {:error, reason} -> raise "Failed to extract dominant colors: #{inspect(reason)}" + end + end + defp prepare_image_for_analysis(image) do with {:ok, resized} <- Operation.thumbnail_image(image, 150) do ensure_rgb_channels(resized) diff --git a/lib/music_library/records/record.ex b/lib/music_library/records/record.ex index a261a15e..d8d7997b 100644 --- a/lib/music_library/records/record.ex +++ b/lib/music_library/records/record.ex @@ -5,7 +5,7 @@ defmodule MusicLibrary.Records.Record do alias MusicBrainz.{Release, ReleaseGroup} alias MusicLibrary.Artists.Artist - alias MusicLibrary.Records.Cover + alias MusicLibrary.Records.{Cover, DominantColors} @formats [:cd, :backup, :vinyl, :blu_ray, :dvd, :multi] @types [:album, :ep, :live, :compilation, :single, :other] @@ -27,6 +27,7 @@ defmodule MusicLibrary.Records.Record do field :selected_release_id, :string field :release_ids, {:array, :string}, default: [] field :included_release_group_ids, {:array, :string}, default: [] + field :dominant_colors, {:array, :string}, default: [] embeds_many :artists, Artist, on_replace: :delete @@ -112,16 +113,28 @@ defmodule MusicLibrary.Records.Record do :included_release_group_ids, :cover_url, :cover_data, + :dominant_colors, :purchased_at ]) |> cast_embed(:artists) |> validate_required([:type, :title, :musicbrainz_id, :genres]) |> unique_constraint(:musicbrainz_id, name: "records_musicbrainz_id_format_index") |> generate_cover_hash() + |> maybe_generate_dominant_colors() |> update_release_ids() |> update_included_release_group_ids() end + defp maybe_generate_dominant_colors(changeset) do + case get_change(changeset, :dominant_colors) do + nil -> + generate_dominant_colors(changeset) + + _dominant_colors -> + changeset + end + end + def add_genres(record, genres) do change(record, genres: genres) end @@ -130,6 +143,7 @@ defmodule MusicLibrary.Records.Record do record |> change(cover_data: cover_data) |> generate_cover_hash() + |> generate_dominant_colors() end def add_musicbrainz_data(record, musicbrainz_data) do @@ -155,6 +169,24 @@ defmodule MusicLibrary.Records.Record do end end + def generate_dominant_colors(%__MODULE__{cover_data: cover_data} = record) do + change(record, dominant_colors: DominantColors.extract_dominant_colors!(cover_data)) + end + + def generate_dominant_colors(changeset) do + case get_change(changeset, :cover_data) do + nil -> + changeset + + cover_data -> + put_change( + changeset, + :dominant_colors, + DominantColors.extract_dominant_colors!(cover_data) + ) + end + end + defp update_release_ids(changeset) do case get_change(changeset, :musicbrainz_data) do nil -> diff --git a/lib/music_library_web/live/collection_live/show.html.heex b/lib/music_library_web/live/collection_live/show.html.heex index b98f332b..51e3a082 100644 --- a/lib/music_library_web/live/collection_live/show.html.heex +++ b/lib/music_library_web/live/collection_live/show.html.heex @@ -17,7 +17,7 @@ {@record.title}

- <.record_colors colors={@dominant_colors} /> + <.record_colors colors={@record.dominant_colors} /> {Records.Record.format_release_date(@record.release_date)} ยท {format_label( @record.format diff --git a/lib/music_library_web/live/wishlist_live/show.html.heex b/lib/music_library_web/live/wishlist_live/show.html.heex index 5fc65cae..bdcb7338 100644 --- a/lib/music_library_web/live/wishlist_live/show.html.heex +++ b/lib/music_library_web/live/wishlist_live/show.html.heex @@ -17,7 +17,7 @@ {@record.title}

- <.record_colors colors={@dominant_colors} /> + <.record_colors colors={@record.dominant_colors} /> {Records.Record.format_release_date(@record.release_date)} ({gettext("Unreleased")}) diff --git a/priv/repo/migrations/20250607185415_add_dominant_colors_to_records.exs b/priv/repo/migrations/20250607185415_add_dominant_colors_to_records.exs new file mode 100644 index 00000000..afe71fca --- /dev/null +++ b/priv/repo/migrations/20250607185415_add_dominant_colors_to_records.exs @@ -0,0 +1,9 @@ +defmodule MusicLibrary.Repo.Migrations.AddDominantColorsToRecords do + use Ecto.Migration + + def change do + alter table(:records) do + add :dominant_colors, {:array, :string}, default: [] + end + end +end diff --git a/test/music_library/records_test.exs b/test/music_library/records_test.exs index fe8aec20..fb212402 100644 --- a/test/music_library/records_test.exs +++ b/test/music_library/records_test.exs @@ -44,6 +44,14 @@ defmodule MusicLibrary.RecordsTest do assert record.cover_hash == "599407DDF69907D4A60FE13CCAA824D25CF08DC124FD6AA3E8E7ECD98C885FFE" + + assert record.dominant_colors == [ + "#000000", + "#C0C0C0", + "#C08080", + "#404000", + "#804040" + ] end test "it queues a task to retrieve artist info data" do diff --git a/test/support/fixtures/music_library/records.ex b/test/support/fixtures/music_library/records.ex index 6095b4ea..a0687221 100644 --- a/test/support/fixtures/music_library/records.ex +++ b/test/support/fixtures/music_library/records.ex @@ -69,7 +69,8 @@ defmodule MusicLibrary.Fixtures.Records do selected_release_id: "d3f9b9e2-73f5-4b47-a2a7-2c2199aad608", release_date: Enum.random(1969..2024) |> Integer.to_string(), purchased_at: current_time, - artists: [artist_attrs(artist_name)] + artists: [artist_attrs(artist_name)], + dominant_colors: ["#000000", "#C0C0C0", "#C08080", "#404000", "#804040"] }) |> MusicLibrary.Records.create_record()