From 13baba90f6deb27b0d6301a705db753cc32bb141 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 9 Nov 2022 13:45:57 -0500 Subject: [PATCH 01/17] Replace ImageMagick with Vips for Media Preview Proxy --- Dockerfile | 4 +- lib/pleroma/helpers/media_helper.ex | 57 +++++++---------------------- mix.exs | 1 + mix.lock | 1 + 4 files changed, 17 insertions(+), 46 deletions(-) diff --git a/Dockerfile b/Dockerfile index d2a3e3573..aba6ebbf1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ COPY . . ENV MIX_ENV=prod -RUN apk add git gcc g++ musl-dev make cmake file-dev &&\ +RUN apk add git gcc g++ musl-dev make cmake file-dev vips &&\ echo "import Config" > config/prod.secret.exs &&\ mix local.hex --force &&\ mix local.rebar --force &&\ @@ -37,7 +37,7 @@ ARG HOME=/opt/pleroma ARG DATA=/var/lib/pleroma RUN apk update &&\ - apk add exiftool ffmpeg imagemagick libmagic ncurses postgresql-client &&\ + apk add exiftool ffmpeg vips libmagic ncurses postgresql-client &&\ adduser --system --shell /bin/false --home ${HOME} pleroma &&\ mkdir -p ${DATA}/uploads &&\ mkdir -p ${DATA}/static &&\ diff --git a/lib/pleroma/helpers/media_helper.ex b/lib/pleroma/helpers/media_helper.ex index 24c845fcd..07dfea55b 100644 --- a/lib/pleroma/helpers/media_helper.ex +++ b/lib/pleroma/helpers/media_helper.ex @@ -8,11 +8,12 @@ defmodule Pleroma.Helpers.MediaHelper do """ alias Pleroma.HTTP + alias Vix.Vips.Operation require Logger def missing_dependencies do - Enum.reduce([imagemagick: "convert", ffmpeg: "ffmpeg"], [], fn {sym, executable}, acc -> + Enum.reduce([ffmpeg: "ffmpeg"], [], fn {sym, executable}, acc -> if Pleroma.Utils.command_available?(executable) do acc else @@ -22,54 +23,22 @@ defmodule Pleroma.Helpers.MediaHelper do end def image_resize(url, options) do - with executable when is_binary(executable) <- System.find_executable("convert"), - {:ok, args} <- prepare_image_resize_args(options), - {:ok, env} <- HTTP.get(url, [], pool: :media), - {:ok, fifo_path} <- mkfifo() do - args = List.flatten([fifo_path, args]) - run_fifo(fifo_path, env, executable, args) + with {:ok, env} <- HTTP.get(url, [], pool: :media), + {:ok, resized} <- + Operation.thumbnail_buffer(env.body, options.max_width, + height: options.max_height, + size: :VIPS_SIZE_DOWN + ) do + if options[:format] == "png" do + Operation.pngsave_buffer(resized, Q: options[:quality]) + else + Operation.jpegsave_buffer(resized, Q: options[:quality], interlace: true) + end else - nil -> {:error, {:convert, :command_not_found}} {:error, _} = error -> error end end - defp prepare_image_resize_args( - %{max_width: max_width, max_height: max_height, format: "png"} = options - ) do - quality = options[:quality] || 85 - resize = Enum.join([max_width, "x", max_height, ">"]) - - args = [ - "-resize", - resize, - "-quality", - to_string(quality), - "png:-" - ] - - {:ok, args} - end - - defp prepare_image_resize_args(%{max_width: max_width, max_height: max_height} = options) do - quality = options[:quality] || 85 - resize = Enum.join([max_width, "x", max_height, ">"]) - - args = [ - "-interlace", - "Plane", - "-resize", - resize, - "-quality", - to_string(quality), - "jpg:-" - ] - - {:ok, args} - end - - defp prepare_image_resize_args(_), do: {:error, :missing_options} - # Note: video thumbnail is intentionally not resized (always has original dimensions) def video_framegrab(url) do with executable when is_binary(executable) <- System.find_executable("ffmpeg"), diff --git a/mix.exs b/mix.exs index 4fd2df2d0..fad81575a 100644 --- a/mix.exs +++ b/mix.exs @@ -193,6 +193,7 @@ defmodule Pleroma.Mixfile do {:eblurhash, "~> 1.2.2"}, {:open_api_spex, "~> 3.16"}, {:ecto_psql_extras, "~> 0.6"}, + {:vix, "~> 0.14.0"}, ## dev & test {:ex_doc, "~> 0.22", only: :dev, runtime: false}, diff --git a/mix.lock b/mix.lock index 7922a8eb1..fdc966c63 100644 --- a/mix.lock +++ b/mix.lock @@ -132,6 +132,7 @@ "ueberauth": {:hex, :ueberauth, "0.10.5", "806adb703df87e55b5615cf365e809f84c20c68aa8c08ff8a416a5a6644c4b02", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3efd1f31d490a125c7ed453b926f7c31d78b97b8a854c755f5c40064bf3ac9e1"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm", "6c7729a2d214806450d29766abc2afaa7a2cbecf415be64f36a6691afebb50e5"}, + "vix": {:hex, :vix, "0.14.0", "f84eaf28191514d385829580db4e1c971e75ecfa771538a40159c18d88340049", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}], "hexpm", "964003b93351b51d0a5b80d80b3d568da4546e6ecbb1ee0bd0fb0a5c8d6e8cc9"}, "web_push_encryption": {:hex, :web_push_encryption, "0.3.1", "76d0e7375142dfee67391e7690e89f92578889cbcf2879377900b5620ee4708d", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.11.1", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "4f82b2e57622fb9337559058e8797cb0df7e7c9790793bdc4e40bc895f70e2a2"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.5", "9dfeee8269b27e958a65b3e235b7e447769f66b5b5925385f5a569269164a210", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "4b977ba4a01918acbf77045ff88de7f6972c2a009213c515a445c48f224ffce9"}, From 481b6ac0d5c610e840fc4b88a357efa28f510ab8 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Thu, 10 Nov 2022 11:07:49 -0500 Subject: [PATCH 02/17] Add Pleroma.Upload.Filter.HeifToJpeg based on vips --- CHANGELOG.md | 1 + lib/pleroma/upload/filter/heif_to_jpeg.ex | 36 +++++++++++++++++ test/fixtures/image.heic | Bin 0 -> 41465 bytes .../upload/filter/heif_to_jpeg_test.exs | 38 ++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 lib/pleroma/upload/filter/heif_to_jpeg.ex create mode 100644 test/fixtures/image.heic create mode 100644 test/pleroma/upload/filter/heif_to_jpeg_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index 394eb5179..7ced3b678 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -150,6 +150,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Added move account API - Enable remote users to interact with posts - Possibility to discover users like `user@example.org`, while Pleroma is working on `pleroma.example.org`. Additional configuration required. +- Added Pleroma.Upload.Filter.HeifToJpeg to automate converting .heic files from Apple devices to JPEGs which can be viewed in browsers. ### Fixed - Subscription(Bell) Notifications: Don't create from Pipeline Ingested replies diff --git a/lib/pleroma/upload/filter/heif_to_jpeg.ex b/lib/pleroma/upload/filter/heif_to_jpeg.ex new file mode 100644 index 000000000..a2095ba01 --- /dev/null +++ b/lib/pleroma/upload/filter/heif_to_jpeg.ex @@ -0,0 +1,36 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Upload.Filter.HeifToJpeg do + @behaviour Pleroma.Upload.Filter + alias Pleroma.Upload + alias Vix.Vips.Operation + + @type conversion :: action :: String.t() | {action :: String.t(), opts :: String.t()} + @type conversions :: conversion() | [conversion()] + + @spec filter(Pleroma.Upload.t()) :: {:ok, :atom} | {:error, String.t()} + def filter(%Pleroma.Upload{content_type: "image/avif"} = upload), do: apply_filter(upload) + def filter(%Pleroma.Upload{content_type: "image/heic"} = upload), do: apply_filter(upload) + def filter(%Pleroma.Upload{content_type: "image/heif"} = upload), do: apply_filter(upload) + + def filter(_), do: {:ok, :noop} + + defp apply_filter(%Pleroma.Upload{name: name, path: path, tempfile: tempfile} = upload) do + ext = String.split(path, ".") |> List.last() + + try do + name = name |> String.replace_suffix(ext, "jpg") + path = path |> String.replace_suffix(ext, "jpg") + {:ok, {vixdata, _vixflags}} = Operation.heifload(tempfile) + {:ok, jpegdata} = Operation.jpegsave_buffer(vixdata) + :ok = File.write(tempfile, jpegdata) + + {:ok, :filtered, %Upload{upload | name: name, path: path, content_type: "image/jpeg"}} + rescue + e in ErlangError -> + {:error, "#{__MODULE__}: #{inspect(e)}"} + end + end +end diff --git a/test/fixtures/image.heic b/test/fixtures/image.heic new file mode 100644 index 0000000000000000000000000000000000000000..efd119a0ea5f9c59d225e2f1ba7269bfe1802d0b GIT binary patch literal 41465 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𝔫oF3jt+&)oY$;m6 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 JuE~EV$w1k)iqQZ7 literal 0 HcmV?d00001 diff --git a/test/pleroma/upload/filter/heif_to_jpeg_test.exs b/test/pleroma/upload/filter/heif_to_jpeg_test.exs new file mode 100644 index 000000000..7627d18ce --- /dev/null +++ b/test/pleroma/upload/filter/heif_to_jpeg_test.exs @@ -0,0 +1,38 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Upload.Filter.HeifToJpegTest do + use Pleroma.DataCase, async: true + alias Pleroma.Upload.Filter + + test "apply HeicToJpeg filter" do + File.cp!( + "test/fixtures/image.heic", + "test/fixtures/heictmp" + ) + + upload = %Pleroma.Upload{ + name: "image.heic", + content_type: "image/heic", + path: Path.absname("test/fixtures/image.heic"), + tempfile: Path.absname("test/fixtures/heictmp") + } + + {:ok, :filtered, result} = Filter.HeifToJpeg.filter(upload) + + assert result.content_type == "image/jpeg" + assert result.name == "image.jpg" + assert String.ends_with?(result.path, "jpg") + + assert {:ok, + %Majic.Result{ + content: + "JPEG image data, JFIF standard 1.02, resolution (DPI), density 96x96, segment length 16, progressive, precision 8, 1024x768, components 3", + encoding: "binary", + mime_type: "image/jpeg" + }} == Majic.perform(result.path, pool: Pleroma.MajicPool) + + on_exit(fn -> File.rm!("test/fixtures/heictmp") end) + end +end From 577ade75cffaa8bfc1926879435312684354ccda Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Tue, 7 Nov 2023 16:31:35 -0500 Subject: [PATCH 03/17] Override elixir_make version --- mix.exs | 3 ++- mix.lock | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mix.exs b/mix.exs index fad81575a..4e4ce35f8 100644 --- a/mix.exs +++ b/mix.exs @@ -193,7 +193,8 @@ defmodule Pleroma.Mixfile do {:eblurhash, "~> 1.2.2"}, {:open_api_spex, "~> 3.16"}, {:ecto_psql_extras, "~> 0.6"}, - {:vix, "~> 0.14.0"}, + {:vix, "~> 0.23.1"}, + {:elixir_make, "~> 0.7.7", override: true}, ## dev & test {:ex_doc, "~> 0.22", only: :dev, runtime: false}, diff --git a/mix.lock b/mix.lock index fdc966c63..1f4eb3dd1 100644 --- a/mix.lock +++ b/mix.lock @@ -9,6 +9,7 @@ "calendar": {:hex, :calendar, "1.0.0", "f52073a708528482ec33d0a171954ca610fe2bd28f1e871f247dc7f1565fa807", [:mix], [{:tzdata, "~> 0.5.20 or ~> 0.1.201603 or ~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "990e9581920c82912a5ee50e62ff5ef96da6b15949a2ee4734f935fdef0f0a6f"}, "captcha": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git", "e0f16822d578866e186a0974d65ad58cddc1e2ab", [ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"]}, "castore": {:hex, :castore, "0.1.22", "4127549e411bedd012ca3a308dede574f43819fe9394254ca55ab4895abfa1a2", [:mix], [], "hexpm", "c17576df47eb5aa1ee40cc4134316a99f5cad3e215d5c77b8dd3cfef12a22cac"}, + "cc_precompiler": {:hex, :cc_precompiler, "0.1.8", "933a5f4da3b19ee56539a076076ce4d7716d64efc8db46fd066996a7e46e2bfd", [:mix], [{:elixir_make, "~> 0.7.3", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "176bdf4366956e456bf761b54ad70bc4103d0269ca9558fd7cee93d1b3f116db"}, "certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"}, @@ -33,7 +34,7 @@ "ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.14", "7a20cfe913b0476542b43870e67386461258734896035e3f284039fd18bd4c4c", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "22f5f98592dd597db9416fcef00effae0787669fdcb6faf447e982b553798e98"}, "ecto_sql": {:hex, :ecto_sql, "3.10.2", "6b98b46534b5c2f8b8b5f03f126e75e2a73c64f3c071149d32987a5378b0fdbd", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "68c018debca57cb9235e3889affdaec7a10616a4e3a80c99fa1d01fdafaa9007"}, "eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"}, - "elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"}, + "elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"}, "esbuild": {:hex, :esbuild, "0.5.0", "d5bb08ff049d7880ee3609ed5c4b864bd2f46445ea40b16b4acead724fb4c4a3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "f183a0b332d963c4cfaf585477695ea59eef9a6f2204fdd0efa00e099694ffe5"}, "eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"}, "ex_aws": {:hex, :ex_aws, "2.1.9", "dc4865ecc20a05190a34a0ac5213e3e5e2b0a75a0c2835e923ae7bfeac5e3c31", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "3e6c776703c9076001fbe1f7c049535f042cb2afa0d2cbd3b47cbc4e92ac0d10"}, @@ -132,7 +133,7 @@ "ueberauth": {:hex, :ueberauth, "0.10.5", "806adb703df87e55b5615cf365e809f84c20c68aa8c08ff8a416a5a6644c4b02", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3efd1f31d490a125c7ed453b926f7c31d78b97b8a854c755f5c40064bf3ac9e1"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm", "6c7729a2d214806450d29766abc2afaa7a2cbecf415be64f36a6691afebb50e5"}, - "vix": {:hex, :vix, "0.14.0", "f84eaf28191514d385829580db4e1c971e75ecfa771538a40159c18d88340049", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}], "hexpm", "964003b93351b51d0a5b80d80b3d568da4546e6ecbb1ee0bd0fb0a5c8d6e8cc9"}, + "vix": {:hex, :vix, "0.23.1", "f0cacb0334a0b4d12fbd7d8b14c78e27bb3cb47c977f5f9abc66162499d03160", [:make, :mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:cc_precompiler, "~> 0.1.4 or ~> 0.2", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7.3 or ~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}], "hexpm", "394d757017392fcbc594fe59fb8f9a7051c18c6fd42859513d7e0e1dfe429f53"}, "web_push_encryption": {:hex, :web_push_encryption, "0.3.1", "76d0e7375142dfee67391e7690e89f92578889cbcf2879377900b5620ee4708d", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.11.1", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "4f82b2e57622fb9337559058e8797cb0df7e7c9790793bdc4e40bc895f70e2a2"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.5", "9dfeee8269b27e958a65b3e235b7e447769f66b5b5925385f5a569269164a210", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "4b977ba4a01918acbf77045ff88de7f6972c2a009213c515a445c48f224ffce9"}, From a4b6e5613fe02fac1a0ec80b8fd6940d2b22f85d Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Tue, 7 Nov 2023 22:03:20 +0000 Subject: [PATCH 04/17] Revert "Add Pleroma.Upload.Filter.HeifToJpeg based on vips" This reverts commit 31d4448ee61b4afac6aa23f8c0287d13aed411a1. This functionality is not reliably working with vips/vix due to codec patent junk --- CHANGELOG.md | 1 - lib/pleroma/upload/filter/heif_to_jpeg.ex | 36 ----------------- test/fixtures/image.heic | Bin 41465 -> 0 bytes .../upload/filter/heif_to_jpeg_test.exs | 38 ------------------ 4 files changed, 75 deletions(-) delete mode 100644 lib/pleroma/upload/filter/heif_to_jpeg.ex delete mode 100644 test/fixtures/image.heic delete mode 100644 test/pleroma/upload/filter/heif_to_jpeg_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ced3b678..394eb5179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -150,7 +150,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Added move account API - Enable remote users to interact with posts - Possibility to discover users like `user@example.org`, while Pleroma is working on `pleroma.example.org`. Additional configuration required. -- Added Pleroma.Upload.Filter.HeifToJpeg to automate converting .heic files from Apple devices to JPEGs which can be viewed in browsers. ### Fixed - Subscription(Bell) Notifications: Don't create from Pipeline Ingested replies diff --git a/lib/pleroma/upload/filter/heif_to_jpeg.ex b/lib/pleroma/upload/filter/heif_to_jpeg.ex deleted file mode 100644 index a2095ba01..000000000 --- a/lib/pleroma/upload/filter/heif_to_jpeg.ex +++ /dev/null @@ -1,36 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Upload.Filter.HeifToJpeg do - @behaviour Pleroma.Upload.Filter - alias Pleroma.Upload - alias Vix.Vips.Operation - - @type conversion :: action :: String.t() | {action :: String.t(), opts :: String.t()} - @type conversions :: conversion() | [conversion()] - - @spec filter(Pleroma.Upload.t()) :: {:ok, :atom} | {:error, String.t()} - def filter(%Pleroma.Upload{content_type: "image/avif"} = upload), do: apply_filter(upload) - def filter(%Pleroma.Upload{content_type: "image/heic"} = upload), do: apply_filter(upload) - def filter(%Pleroma.Upload{content_type: "image/heif"} = upload), do: apply_filter(upload) - - def filter(_), do: {:ok, :noop} - - defp apply_filter(%Pleroma.Upload{name: name, path: path, tempfile: tempfile} = upload) do - ext = String.split(path, ".") |> List.last() - - try do - name = name |> String.replace_suffix(ext, "jpg") - path = path |> String.replace_suffix(ext, "jpg") - {:ok, {vixdata, _vixflags}} = Operation.heifload(tempfile) - {:ok, jpegdata} = Operation.jpegsave_buffer(vixdata) - :ok = File.write(tempfile, jpegdata) - - {:ok, :filtered, %Upload{upload | name: name, path: path, content_type: "image/jpeg"}} - rescue - e in ErlangError -> - {:error, "#{__MODULE__}: #{inspect(e)}"} - end - end -end diff --git a/test/fixtures/image.heic b/test/fixtures/image.heic deleted file mode 100644 index efd119a0ea5f9c59d225e2f1ba7269bfe1802d0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41465 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𝔫oF3jt+&)oY$;m6 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 JuE~EV$w1k)iqQZ7 diff --git a/test/pleroma/upload/filter/heif_to_jpeg_test.exs b/test/pleroma/upload/filter/heif_to_jpeg_test.exs deleted file mode 100644 index 7627d18ce..000000000 --- a/test/pleroma/upload/filter/heif_to_jpeg_test.exs +++ /dev/null @@ -1,38 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2021 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Upload.Filter.HeifToJpegTest do - use Pleroma.DataCase, async: true - alias Pleroma.Upload.Filter - - test "apply HeicToJpeg filter" do - File.cp!( - "test/fixtures/image.heic", - "test/fixtures/heictmp" - ) - - upload = %Pleroma.Upload{ - name: "image.heic", - content_type: "image/heic", - path: Path.absname("test/fixtures/image.heic"), - tempfile: Path.absname("test/fixtures/heictmp") - } - - {:ok, :filtered, result} = Filter.HeifToJpeg.filter(upload) - - assert result.content_type == "image/jpeg" - assert result.name == "image.jpg" - assert String.ends_with?(result.path, "jpg") - - assert {:ok, - %Majic.Result{ - content: - "JPEG image data, JFIF standard 1.02, resolution (DPI), density 96x96, segment length 16, progressive, precision 8, 1024x768, components 3", - encoding: "binary", - mime_type: "image/jpeg" - }} == Majic.perform(result.path, pool: Pleroma.MajicPool) - - on_exit(fn -> File.rm!("test/fixtures/heictmp") end) - end -end From ce42dac331e49dd5ab8c8bca248ee11916804186 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 8 Nov 2023 09:17:32 -0500 Subject: [PATCH 05/17] Change mediaproxy previews to use vips to generate thumbnails instead of ImageMagick --- changelog.d/mediaproxy_preview.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/mediaproxy_preview.change diff --git a/changelog.d/mediaproxy_preview.change b/changelog.d/mediaproxy_preview.change new file mode 100644 index 000000000..ee18cd34b --- /dev/null +++ b/changelog.d/mediaproxy_preview.change @@ -0,0 +1 @@ +Change mediaproxy previews to use vips to generate thumbnails instead of ImageMagick From 0c6a54b37cb208e577fc9e40782bb8b820730428 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Thu, 16 Nov 2023 17:04:47 -0500 Subject: [PATCH 06/17] Upload.Filter.AnalyzeMetadata: Blurhash with a Rust NIF, and use Vix to retrieve image metadata --- lib/pleroma/upload/filter/analyze_metadata.ex | 36 ++++++++++++++----- mix.exs | 4 +-- mix.lock | 7 ++-- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/pleroma/upload/filter/analyze_metadata.ex b/lib/pleroma/upload/filter/analyze_metadata.ex index 9a76a998b..15dec5564 100644 --- a/lib/pleroma/upload/filter/analyze_metadata.ex +++ b/lib/pleroma/upload/filter/analyze_metadata.ex @@ -8,22 +8,23 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadata do """ require Logger + alias Vix.Vips.Image + alias Vix.Vips.Operation + @behaviour Pleroma.Upload.Filter @spec filter(Pleroma.Upload.t()) :: {:ok, :filtered, Pleroma.Upload.t()} | {:ok, :noop} | {:error, String.t()} def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _} = upload) do try do - image = - file - |> Mogrify.open() - |> Mogrify.verbose() + {:ok, image} = Image.new_from_file(file) + {width, height} = {Image.width(image), Image.height(image)} upload = upload - |> Map.put(:width, image.width) - |> Map.put(:height, image.height) - |> Map.put(:blurhash, get_blurhash(file)) + |> Map.put(:width, width) + |> Map.put(:height, height) + |> Map.put(:blurhash, get_blurhash(image)) {:ok, :filtered, upload} rescue @@ -53,7 +54,7 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadata do def filter(_), do: {:ok, :noop} defp get_blurhash(file) do - with {:ok, blurhash} <- :eblurhash.magick(file) do + with {:ok, blurhash} <- vips_blurhash(file) do blurhash else _ -> nil @@ -80,4 +81,23 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadata do {:error, _} = error -> error end end + + defp vips_blurhash(image = %Vix.Vips.Image{}) do + {:ok, resized_image} = Operation.thumbnail_image(image, 20) + {height, width} = {Image.height(resized_image), Image.width(resized_image)} + max = max(height, width) + {x, y} = {max(round(width * 5 / max), 1), max(round(height * 5 / max), 1)} + + {:ok, rgba} = + if Image.has_alpha?(resized_image) do + Image.to_list(resized_image) + else + Operation.bandjoin_const!(resized_image, [255]) + |> Image.to_list() + end + + rgba = List.flatten(rgba) + + Blurhash.encode(x, y, width, height, rgba) + end end diff --git a/mix.exs b/mix.exs index 4e4ce35f8..61768b71d 100644 --- a/mix.exs +++ b/mix.exs @@ -190,11 +190,11 @@ defmodule Pleroma.Mixfile do ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"}, {:restarter, path: "./restarter"}, {:majic, "~> 1.0"}, - {:eblurhash, "~> 1.2.2"}, {:open_api_spex, "~> 3.16"}, {:ecto_psql_extras, "~> 0.6"}, - {:vix, "~> 0.23.1"}, + {:vix, "~> 0.25.0"}, {:elixir_make, "~> 0.7.7", override: true}, + {:blurhash, git: "https://git.feld.me/feld/blurhash.git", ref: "master"}, ## dev & test {:ex_doc, "~> 0.22", only: :dev, runtime: false}, diff --git a/mix.lock b/mix.lock index 1f4eb3dd1..dac911a56 100644 --- a/mix.lock +++ b/mix.lock @@ -4,12 +4,13 @@ "bbcode_pleroma": {:hex, :bbcode_pleroma, "0.2.0", "d36f5bca6e2f62261c45be30fa9b92725c0655ad45c99025cb1c3e28e25803ef", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "19851074419a5fedb4ef49e1f01b30df504bb5dbb6d6adfc135238063bebd1c3"}, "bcrypt_elixir": {:hex, :bcrypt_elixir, "2.3.1", "5114d780459a04f2b4aeef52307de23de961b69e13a5cd98a911e39fda13f420", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "42182d5f46764def15bf9af83739e3bf4ad22661b1c34fc3e88558efced07279"}, "benchee": {:hex, :benchee, "1.1.0", "f3a43817209a92a1fade36ef36b86e1052627fd8934a8b937ac9ab3a76c43062", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}], "hexpm", "7da57d545003165a012b587077f6ba90b89210fd88074ce3c60ce239eb5e6d93"}, + "blurhash": {:git, "https://git.feld.me/feld/blurhash.git", "4cf6e61c9b0824581bdfef10e392fee8caacccec", [ref: "master"]}, "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, "cachex": {:hex, :cachex, "3.6.0", "14a1bfbeee060dd9bec25a5b6f4e4691e3670ebda28c8ba2884b12fe30b36bf8", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "ebf24e373883bc8e0c8d894a63bbe102ae13d918f790121f5cfe6e485cc8e2e2"}, "calendar": {:hex, :calendar, "1.0.0", "f52073a708528482ec33d0a171954ca610fe2bd28f1e871f247dc7f1565fa807", [:mix], [{:tzdata, "~> 0.5.20 or ~> 0.1.201603 or ~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "990e9581920c82912a5ee50e62ff5ef96da6b15949a2ee4734f935fdef0f0a6f"}, "captcha": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git", "e0f16822d578866e186a0974d65ad58cddc1e2ab", [ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"]}, "castore": {:hex, :castore, "0.1.22", "4127549e411bedd012ca3a308dede574f43819fe9394254ca55ab4895abfa1a2", [:mix], [], "hexpm", "c17576df47eb5aa1ee40cc4134316a99f5cad3e215d5c77b8dd3cfef12a22cac"}, - "cc_precompiler": {:hex, :cc_precompiler, "0.1.8", "933a5f4da3b19ee56539a076076ce4d7716d64efc8db46fd066996a7e46e2bfd", [:mix], [{:elixir_make, "~> 0.7.3", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "176bdf4366956e456bf761b54ad70bc4103d0269ca9558fd7cee93d1b3f116db"}, + "cc_precompiler": {:hex, :cc_precompiler, "0.1.9", "e8d3364f310da6ce6463c3dd20cf90ae7bbecbf6c5203b98bf9b48035592649b", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "9dcab3d0f3038621f1601f13539e7a9ee99843862e66ad62827b0c42b2f58a54"}, "certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, "comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"}, @@ -115,6 +116,7 @@ "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, "recon": {:hex, :recon, "2.5.3", "739107b9050ea683c30e96de050bc59248fd27ec147696f79a8797ff9fa17153", [:mix, :rebar3], [], "hexpm", "6c6683f46fd4a1dfd98404b9f78dcabc7fcd8826613a89dcb984727a8c3099d7"}, "remote_ip": {:git, "https://git.pleroma.social/pleroma/remote_ip.git", "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8", [ref: "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8"]}, + "rustler": {:hex, :rustler, "0.30.0", "cefc49922132b072853fa9b0ca4dc2ffcb452f68fb73b779042b02d545e097fb", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "9ef1abb6a7dda35c47cfc649e6a5a61663af6cf842a55814a554a84607dee389"}, "sleeplocks": {:hex, :sleeplocks, "1.1.2", "d45aa1c5513da48c888715e3381211c859af34bee9b8290490e10c90bb6ff0ca", [:rebar3], [], "hexpm", "9fe5d048c5b781d6305c1a3a0f40bb3dfc06f49bf40571f3d2d0c57eaa7f59a5"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"}, @@ -128,12 +130,13 @@ "telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"}, "tesla": {:hex, :tesla, "1.4.4", "bb89aa0c9745190930366f6a2ac612cdf2d0e4d7fff449861baa7875afd797b2", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.3", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "d5503a49f9dec1b287567ea8712d085947e247cb11b06bc54adb05bfde466457"}, "timex": {:hex, :timex, "3.7.7", "3ed093cae596a410759104d878ad7b38e78b7c2151c6190340835515d4a46b8a", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "0ec4b09f25fe311321f9fc04144a7e3affe48eb29481d7a5583849b6c4dfa0a7"}, + "toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"}, "trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"}, "tzdata": {:hex, :tzdata, "1.0.5", "69f1ee029a49afa04ad77801febaf69385f3d3e3d1e4b56b9469025677b89a28", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "55519aa2a99e5d2095c1e61cc74c9be69688f8ab75c27da724eb8279ff402a5a"}, "ueberauth": {:hex, :ueberauth, "0.10.5", "806adb703df87e55b5615cf365e809f84c20c68aa8c08ff8a416a5a6644c4b02", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3efd1f31d490a125c7ed453b926f7c31d78b97b8a854c755f5c40064bf3ac9e1"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm", "6c7729a2d214806450d29766abc2afaa7a2cbecf415be64f36a6691afebb50e5"}, - "vix": {:hex, :vix, "0.23.1", "f0cacb0334a0b4d12fbd7d8b14c78e27bb3cb47c977f5f9abc66162499d03160", [:make, :mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:cc_precompiler, "~> 0.1.4 or ~> 0.2", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7.3 or ~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}], "hexpm", "394d757017392fcbc594fe59fb8f9a7051c18c6fd42859513d7e0e1dfe429f53"}, + "vix": {:hex, :vix, "0.25.0", "b294ca3140c0357b262d86e9966949949844282b81923bb990668c1ee5a35337", [:make, :mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:cc_precompiler, "~> 0.1.4 or ~> 0.2", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7.3 or ~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}], "hexpm", "be09c96982978bc2d0c501a73e0b65ba58ec94c1afb94e3617029d6ce7ae8c3f"}, "web_push_encryption": {:hex, :web_push_encryption, "0.3.1", "76d0e7375142dfee67391e7690e89f92578889cbcf2879377900b5620ee4708d", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.11.1", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "4f82b2e57622fb9337559058e8797cb0df7e7c9790793bdc4e40bc895f70e2a2"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.5", "9dfeee8269b27e958a65b3e235b7e447769f66b5b5925385f5a569269164a210", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "4b977ba4a01918acbf77045ff88de7f6972c2a009213c515a445c48f224ffce9"}, From 88cc7e6a0431385b5fce292179c7eb05e64e3a24 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 17 Nov 2023 11:06:31 -0500 Subject: [PATCH 07/17] Resize images to 100 pixels before hashing --- lib/pleroma/upload/filter/analyze_metadata.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/upload/filter/analyze_metadata.ex b/lib/pleroma/upload/filter/analyze_metadata.ex index 15dec5564..99d1ec5bc 100644 --- a/lib/pleroma/upload/filter/analyze_metadata.ex +++ b/lib/pleroma/upload/filter/analyze_metadata.ex @@ -83,7 +83,7 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadata do end defp vips_blurhash(image = %Vix.Vips.Image{}) do - {:ok, resized_image} = Operation.thumbnail_image(image, 20) + {:ok, resized_image} = Operation.thumbnail_image(image, 100) {height, width} = {Image.height(resized_image), Image.width(resized_image)} max = max(height, width) {x, y} = {max(round(width * 5 / max), 1), max(round(height * 5 / max), 1)} From 9511212e32649116783e202d58ec06f362d05157 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 17 Nov 2023 11:06:50 -0500 Subject: [PATCH 08/17] Fetch the library from the Pleroma repository --- mix.exs | 4 +++- mix.lock | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index 61768b71d..024105f0e 100644 --- a/mix.exs +++ b/mix.exs @@ -194,7 +194,9 @@ defmodule Pleroma.Mixfile do {:ecto_psql_extras, "~> 0.6"}, {:vix, "~> 0.25.0"}, {:elixir_make, "~> 0.7.7", override: true}, - {:blurhash, git: "https://git.feld.me/feld/blurhash.git", ref: "master"}, + {:blurhash, + git: "https://git.pleroma.social/pleroma/elixir-libraries/blurhash.git", + ref: "61cfc428df3f266bdd20f181d188c6f59da34814"}, ## dev & test {:ex_doc, "~> 0.22", only: :dev, runtime: false}, diff --git a/mix.lock b/mix.lock index dac911a56..0399a981f 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "bbcode_pleroma": {:hex, :bbcode_pleroma, "0.2.0", "d36f5bca6e2f62261c45be30fa9b92725c0655ad45c99025cb1c3e28e25803ef", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "19851074419a5fedb4ef49e1f01b30df504bb5dbb6d6adfc135238063bebd1c3"}, "bcrypt_elixir": {:hex, :bcrypt_elixir, "2.3.1", "5114d780459a04f2b4aeef52307de23de961b69e13a5cd98a911e39fda13f420", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "42182d5f46764def15bf9af83739e3bf4ad22661b1c34fc3e88558efced07279"}, "benchee": {:hex, :benchee, "1.1.0", "f3a43817209a92a1fade36ef36b86e1052627fd8934a8b937ac9ab3a76c43062", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}], "hexpm", "7da57d545003165a012b587077f6ba90b89210fd88074ce3c60ce239eb5e6d93"}, - "blurhash": {:git, "https://git.feld.me/feld/blurhash.git", "4cf6e61c9b0824581bdfef10e392fee8caacccec", [ref: "master"]}, + "blurhash": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/blurhash.git", "61cfc428df3f266bdd20f181d188c6f59da34814", [ref: "61cfc428df3f266bdd20f181d188c6f59da34814"]}, "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, "cachex": {:hex, :cachex, "3.6.0", "14a1bfbeee060dd9bec25a5b6f4e4691e3670ebda28c8ba2884b12fe30b36bf8", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "ebf24e373883bc8e0c8d894a63bbe102ae13d918f790121f5cfe6e485cc8e2e2"}, "calendar": {:hex, :calendar, "1.0.0", "f52073a708528482ec33d0a171954ca610fe2bd28f1e871f247dc7f1565fa807", [:mix], [{:tzdata, "~> 0.5.20 or ~> 0.1.201603 or ~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "990e9581920c82912a5ee50e62ff5ef96da6b15949a2ee4734f935fdef0f0a6f"}, From 7988c62f6d926729fdbd0a2181f94f409c7aed02 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 17 Nov 2023 11:21:46 -0500 Subject: [PATCH 09/17] Update changelogs --- changelog.d/blurhash.change | 1 + changelog.d/{mediaproxy_preview.change => vips.change} | 0 2 files changed, 1 insertion(+) create mode 100644 changelog.d/blurhash.change rename changelog.d/{mediaproxy_preview.change => vips.change} (100%) diff --git a/changelog.d/blurhash.change b/changelog.d/blurhash.change new file mode 100644 index 000000000..428a74d7a --- /dev/null +++ b/changelog.d/blurhash.change @@ -0,0 +1 @@ +Replace eblurhash with a Rust NIF blurhash. This also removes a dependency on ImageMagick. diff --git a/changelog.d/mediaproxy_preview.change b/changelog.d/vips.change similarity index 100% rename from changelog.d/mediaproxy_preview.change rename to changelog.d/vips.change From 8208777b067d5af382c4675451fcadd547e808f4 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 17 Nov 2023 11:32:56 -0500 Subject: [PATCH 10/17] Rust is required for blurhash --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index aba6ebbf1..734bb2991 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ COPY . . ENV MIX_ENV=prod -RUN apk add git gcc g++ musl-dev make cmake file-dev vips &&\ +RUN apk add git gcc g++ musl-dev make cmake file-dev vips rust &&\ echo "import Config" > config/prod.secret.exs &&\ mix local.hex --force &&\ mix local.rebar --force &&\ From cf5ef1d75fab406275ab07fa8d52a819d90431b8 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 17 Nov 2023 11:37:51 -0500 Subject: [PATCH 11/17] Vix has pre-built NIFs for the following triples: aarch64-apple-darwin aarch64-linux-gnu aarch64-linux-musl armv7l-linux-gnueabihf x86_64-apple-darwin x86_64-linux-gnu x86_64-linux-musl aarch64-apple-darwin aarch64-linux-gnu aarch64-linux-musl armv7l-linux-gnueabihf x86_64-apple-darwin x86_64-linux-gnu x86_64-linux-musl --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 734bb2991..13d8a85ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ COPY . . ENV MIX_ENV=prod -RUN apk add git gcc g++ musl-dev make cmake file-dev vips rust &&\ +RUN apk add git gcc g++ musl-dev make cmake file-dev rust &&\ echo "import Config" > config/prod.secret.exs &&\ mix local.hex --force &&\ mix local.rebar --force &&\ From be39146ecc6d55191f8ed3ec9cd3e113d8ee5e21 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 17 Nov 2023 11:44:33 -0500 Subject: [PATCH 12/17] Update docs to include dependencies on rust and vips where appropriate --- docs/installation/alpine_linux_en.md | 2 +- docs/installation/arch_linux_en.md | 1 + docs/installation/debian_based_en.md | 2 +- docs/installation/debian_based_jp.md | 1 + docs/installation/freebsd_en.md | 3 ++- 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/installation/alpine_linux_en.md b/docs/installation/alpine_linux_en.md index 7154bca48..9794833a3 100644 --- a/docs/installation/alpine_linux_en.md +++ b/docs/installation/alpine_linux_en.md @@ -28,7 +28,7 @@ sudo apk upgrade * Install some tools, which are needed later: ```shell -sudo apk add git build-base cmake file-dev +sudo apk add git build-base cmake file-dev rust ``` ### Install Elixir and Erlang diff --git a/docs/installation/arch_linux_en.md b/docs/installation/arch_linux_en.md index f7d722ef9..dbfbf6bf8 100644 --- a/docs/installation/arch_linux_en.md +++ b/docs/installation/arch_linux_en.md @@ -14,6 +14,7 @@ This guide will assume that you have administrative rights, either as root or a * `base-devel` * `cmake` * `file` +* `rust` #### Optional packages used in this guide diff --git a/docs/installation/debian_based_en.md b/docs/installation/debian_based_en.md index b61e4addd..44c93e1ef 100644 --- a/docs/installation/debian_based_en.md +++ b/docs/installation/debian_based_en.md @@ -20,7 +20,7 @@ sudo apt full-upgrade * Install some of the above mentioned programs: ```shell -sudo apt install git build-essential postgresql postgresql-contrib cmake libmagic-dev +sudo apt install git build-essential postgresql postgresql-contrib cmake libmagic-dev rust ``` ### Install Elixir and Erlang diff --git a/docs/installation/debian_based_jp.md b/docs/installation/debian_based_jp.md index 1424ad7f4..43902c987 100644 --- a/docs/installation/debian_based_jp.md +++ b/docs/installation/debian_based_jp.md @@ -21,6 +21,7 @@ Note: This article is potentially outdated because at this time we may not have - `build-essential` - `cmake` - `libmagic-dev` +- `rust` #### このガイドで利用している追加パッケージ diff --git a/docs/installation/freebsd_en.md b/docs/installation/freebsd_en.md index 50ed30d74..b88853dd1 100644 --- a/docs/installation/freebsd_en.md +++ b/docs/installation/freebsd_en.md @@ -9,7 +9,7 @@ This document was written for FreeBSD 12.1, but should be work on future release This assumes the target system has `pkg(8)`. ``` -# pkg install elixir postgresql12-server postgresql12-client postgresql12-contrib git-lite sudo nginx gmake acme.sh cmake +# pkg install elixir postgresql12-server postgresql12-client postgresql12-contrib git-lite sudo nginx gmake acme.sh cmake rust vips ``` Copy the rc.d scripts to the right directory: @@ -41,6 +41,7 @@ Create a user for Pleroma: ``` # pw add user pleroma -m # echo 'export LC_ALL="en_US.UTF-8"' >> /home/pleroma/.profile +# echo 'export VIX_COMPILATION_MODE=PLATFORM_PROVIDED_LIBVIPS' >> /home/pleroma/.profile # su -l pleroma ``` From 299c548b124377e51f6c089bc0df31b2989be3ef Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Thu, 23 Nov 2023 16:15:53 -0500 Subject: [PATCH 13/17] Prevent a blurhash failure from breaking all metadata collection --- lib/pleroma/upload/filter/analyze_metadata.ex | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/pleroma/upload/filter/analyze_metadata.ex b/lib/pleroma/upload/filter/analyze_metadata.ex index 99d1ec5bc..92b80b1b1 100644 --- a/lib/pleroma/upload/filter/analyze_metadata.ex +++ b/lib/pleroma/upload/filter/analyze_metadata.ex @@ -83,21 +83,23 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadata do end defp vips_blurhash(image = %Vix.Vips.Image{}) do - {:ok, resized_image} = Operation.thumbnail_image(image, 100) - {height, width} = {Image.height(resized_image), Image.width(resized_image)} - max = max(height, width) - {x, y} = {max(round(width * 5 / max), 1), max(round(height * 5 / max), 1)} + with {:ok, resized_image} <- Operation.thumbnail_image(image, 100), + {height, width} <- {Image.height(resized_image), Image.width(resized_image)}, + max <- max(height, width), + {x, y} <- {max(round(width * 5 / max), 1), max(round(height * 5 / max), 1)} do + {:ok, rgba} = + if Image.has_alpha?(resized_image) do + Image.to_list(resized_image) + else + Operation.bandjoin_const!(resized_image, [255]) + |> Image.to_list() + end - {:ok, rgba} = - if Image.has_alpha?(resized_image) do - Image.to_list(resized_image) - else - Operation.bandjoin_const!(resized_image, [255]) - |> Image.to_list() - end + rgba = List.flatten(rgba) - rgba = List.flatten(rgba) - - Blurhash.encode(x, y, width, height, rgba) + Blurhash.encode(x, y, width, height, rgba) + else + _ -> nil + end end end From 03db495e1d88f34bef8d556b0f88806c3260d403 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Tue, 28 Nov 2023 12:23:41 +0400 Subject: [PATCH 14/17] AnalyzeMetadata: Switch to rinpatch_blurhash --- lib/pleroma/upload/filter/analyze_metadata.ex | 14 +++++++------- mix.exs | 6 ++---- mix.lock | 4 ++-- test/fixtures/png_with_transparency.png | Bin 0 -> 84250 bytes .../upload/filter/analyze_metadata_test.exs | 14 ++++++++++++++ 5 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 test/fixtures/png_with_transparency.png diff --git a/lib/pleroma/upload/filter/analyze_metadata.ex b/lib/pleroma/upload/filter/analyze_metadata.ex index 92b80b1b1..710fd02d2 100644 --- a/lib/pleroma/upload/filter/analyze_metadata.ex +++ b/lib/pleroma/upload/filter/analyze_metadata.ex @@ -87,17 +87,17 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadata do {height, width} <- {Image.height(resized_image), Image.width(resized_image)}, max <- max(height, width), {x, y} <- {max(round(width * 5 / max), 1), max(round(height * 5 / max), 1)} do - {:ok, rgba} = + {:ok, rgb} = if Image.has_alpha?(resized_image) do - Image.to_list(resized_image) + # remove alpha channel + resized_image + |> Operation.extract_band!(0, n: 3) + |> Image.write_to_binary() else - Operation.bandjoin_const!(resized_image, [255]) - |> Image.to_list() + Image.write_to_binary(resized_image) end - rgba = List.flatten(rgba) - - Blurhash.encode(x, y, width, height, rgba) + Blurhash.encode(rgb, width, height, x, y) else _ -> nil end diff --git a/mix.exs b/mix.exs index 3a31ae3ab..e5e77c0f7 100644 --- a/mix.exs +++ b/mix.exs @@ -142,7 +142,7 @@ defmodule Pleroma.Mixfile do {:gun, "~> 2.0.0-rc.1", override: true}, {:finch, "~> 0.10.0"}, {:jason, "~> 1.2"}, - {:mogrify, "~> 0.9.1"}, + {:mogrify, "~> 0.8.0"}, {:ex_aws, "~> 2.1.6"}, {:ex_aws_s3, "~> 2.0"}, {:sweet_xml, "~> 0.7.2"}, @@ -194,9 +194,7 @@ defmodule Pleroma.Mixfile do {:ecto_psql_extras, "~> 0.6"}, {:vix, "~> 0.25.0"}, {:elixir_make, "~> 0.7.7", override: true}, - {:blurhash, - git: "https://git.pleroma.social/pleroma/elixir-libraries/blurhash.git", - ref: "61cfc428df3f266bdd20f181d188c6f59da34814"}, + {:blurhash, "~> 0.1.0", hex: :rinpatch_blurhash}, ## dev & test {:ex_doc, "~> 0.22", only: :dev, runtime: false}, diff --git a/mix.lock b/mix.lock index 7fa316971..c7d65ffe2 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "bbcode_pleroma": {:hex, :bbcode_pleroma, "0.2.0", "d36f5bca6e2f62261c45be30fa9b92725c0655ad45c99025cb1c3e28e25803ef", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "19851074419a5fedb4ef49e1f01b30df504bb5dbb6d6adfc135238063bebd1c3"}, "bcrypt_elixir": {:hex, :bcrypt_elixir, "2.3.1", "5114d780459a04f2b4aeef52307de23de961b69e13a5cd98a911e39fda13f420", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "42182d5f46764def15bf9af83739e3bf4ad22661b1c34fc3e88558efced07279"}, "benchee": {:hex, :benchee, "1.1.0", "f3a43817209a92a1fade36ef36b86e1052627fd8934a8b937ac9ab3a76c43062", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}], "hexpm", "7da57d545003165a012b587077f6ba90b89210fd88074ce3c60ce239eb5e6d93"}, - "blurhash": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/blurhash.git", "61cfc428df3f266bdd20f181d188c6f59da34814", [ref: "61cfc428df3f266bdd20f181d188c6f59da34814"]}, + "blurhash": {:hex, :rinpatch_blurhash, "0.1.0", "01a888b0f5f1f382ab52e4396f01831cbe8486ea5828604c90f4dac533d39a4b", [:mix], [{:mogrify, "~> 0.8.0", [hex: :mogrify, repo: "hexpm", optional: true]}], "hexpm", "19911a5dcbb0acb9710169a72f702bce6cb048822b12de566ccd82b2cc42b907"}, "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, "cachex": {:hex, :cachex, "3.6.0", "14a1bfbeee060dd9bec25a5b6f4e4691e3670ebda28c8ba2884b12fe30b36bf8", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "ebf24e373883bc8e0c8d894a63bbe102ae13d918f790121f5cfe6e485cc8e2e2"}, "calendar": {:hex, :calendar, "1.0.0", "f52073a708528482ec33d0a171954ca610fe2bd28f1e871f247dc7f1565fa807", [:mix], [{:tzdata, "~> 0.5.20 or ~> 0.1.201603 or ~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "990e9581920c82912a5ee50e62ff5ef96da6b15949a2ee4734f935fdef0f0a6f"}, @@ -77,7 +77,7 @@ "mint": {:hex, :mint, "1.5.1", "8db5239e56738552d85af398798c80648db0e90f343c8469f6c6d8898944fb6f", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "4a63e1e76a7c3956abd2c72f370a0d0aecddc3976dea5c27eccbecfa5e7d5b1e"}, "mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm"}, "mock": {:hex, :mock, "0.3.8", "7046a306b71db2488ef54395eeb74df0a7f335a7caca4a3d3875d1fc81c884dd", [:mix], [{:meck, "~> 0.9.2", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "7fa82364c97617d79bb7d15571193fc0c4fe5afd0c932cef09426b3ee6fe2022"}, - "mogrify": {:hex, :mogrify, "0.9.3", "238c782f00271dace01369ad35ae2e9dd020feee3443b9299ea5ea6bed559841", [:mix], [], "hexpm", "0189b1e1de27455f2b9ae8cf88239cefd23d38de9276eb5add7159aea51731e6"}, + "mogrify": {:hex, :mogrify, "0.8.0", "3506f3ca3f7b95a155f3b4ef803b5db176f5a0633723e3fe85e0d6399e3b11c8", [:mix], [], "hexpm", "2278d245f07056ea3b586e98801e933695147066fa4cf563f552c1b4f0ff8ad9"}, "mox": {:hex, :mox, "1.0.2", "dc2057289ac478b35760ba74165b4b3f402f68803dd5aecd3bfd19c183815d64", [:mix], [], "hexpm", "f9864921b3aaf763c8741b5b8e6f908f44566f1e427b2630e89e9a73b981fef2"}, "nimble_options": {:hex, :nimble_options, "0.4.0", "c89babbab52221a24b8d1ff9e7d838be70f0d871be823165c94dd3418eea728f", [:mix], [], "hexpm", "e6701c1af326a11eea9634a3b1c62b475339ace9456c1a23ec3bc9a847bca02d"}, "nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"}, diff --git a/test/fixtures/png_with_transparency.png b/test/fixtures/png_with_transparency.png new file mode 100644 index 0000000000000000000000000000000000000000..7963149dbeabb5a9da0fe62408aca4578d0d73f1 GIT binary patch literal 84250 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%0AUdF=8-%|f`Xgxh*sC=UrTc6;$v^; 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 oyK;GoTyxiJ;h$K4O)YybcN literal 0 HcmV?d00001 diff --git a/test/pleroma/upload/filter/analyze_metadata_test.exs b/test/pleroma/upload/filter/analyze_metadata_test.exs index b800a4a43..e4ac673b2 100644 --- a/test/pleroma/upload/filter/analyze_metadata_test.exs +++ b/test/pleroma/upload/filter/analyze_metadata_test.exs @@ -20,6 +20,20 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadataTest do assert meta.blurhash end + test "it blurhashes images with an alpha component" do + upload = %Pleroma.Upload{ + name: "an… image.jpg", + content_type: "image/jpeg", + path: Path.absname("test/fixtures/png_with_transparency.png"), + tempfile: Path.absname("test/fixtures/png_with_transparency.png") + } + + {:ok, :filtered, meta} = AnalyzeMetadata.filter(upload) + + assert %{width: 320, height: 320} = meta + assert meta.blurhash == "eXJi-E:SwCEm5rCmn$+YWYn+15K#5A$xxCi{SiV]s*W:Efa#s.jE-T" + end + test "adds the dimensions for videos" do upload = %Pleroma.Upload{ name: "coolvideo.mp4", From b3214be32f83541626b198b86ee065b92862f4cf Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Tue, 28 Nov 2023 12:33:54 +0400 Subject: [PATCH 15/17] AnayzeMetadata: Fix error case that would never match --- lib/pleroma/upload/filter/analyze_metadata.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/upload/filter/analyze_metadata.ex b/lib/pleroma/upload/filter/analyze_metadata.ex index 710fd02d2..ef75d73d3 100644 --- a/lib/pleroma/upload/filter/analyze_metadata.ex +++ b/lib/pleroma/upload/filter/analyze_metadata.ex @@ -78,7 +78,7 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadata do %{width: width, height: height} else nil -> {:error, {:ffprobe, :command_not_found}} - {:error, _} = error -> error + error -> {:error, error} end end From da26964d2be8183d22596d64aa0db5e9b3b96888 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Tue, 28 Nov 2023 12:39:22 +0400 Subject: [PATCH 16/17] Changelog: Adjust blurhash change --- changelog.d/blurhash.change | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/blurhash.change b/changelog.d/blurhash.change index 428a74d7a..c45e3058a 100644 --- a/changelog.d/blurhash.change +++ b/changelog.d/blurhash.change @@ -1 +1 @@ -Replace eblurhash with a Rust NIF blurhash. This also removes a dependency on ImageMagick. +Replace eblurhash with a rinpatch_blurhash. This also removes a dependency on ImageMagick. From ccc2adee4111367d67646f6f2828e03b861dd393 Mon Sep 17 00:00:00 2001 From: Lain Soykaf Date: Tue, 28 Nov 2023 13:13:43 +0400 Subject: [PATCH 17/17] Linting --- lib/pleroma/upload/filter/analyze_metadata.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/upload/filter/analyze_metadata.ex b/lib/pleroma/upload/filter/analyze_metadata.ex index ef75d73d3..e510ae3e6 100644 --- a/lib/pleroma/upload/filter/analyze_metadata.ex +++ b/lib/pleroma/upload/filter/analyze_metadata.ex @@ -82,7 +82,7 @@ defmodule Pleroma.Upload.Filter.AnalyzeMetadata do end end - defp vips_blurhash(image = %Vix.Vips.Image{}) do + defp vips_blurhash(%Vix.Vips.Image{} = image) do with {:ok, resized_image} <- Operation.thumbnail_image(image, 100), {height, width} <- {Image.height(resized_image), Image.width(resized_image)}, max <- max(height, width),