[#2497] Image preview proxy: image resize & background color fix with ffmpeg -filter_...
authorIvan Tashkinov <ivantashkinov@gmail.com>
Thu, 21 May 2020 14:35:42 +0000 (17:35 +0300)
committerIvan Tashkinov <ivantashkinov@gmail.com>
Thu, 21 May 2020 14:35:42 +0000 (17:35 +0300)
lib/pleroma/helpers/media_helper.ex
lib/pleroma/web/media_proxy/media_proxy_controller.ex

index 6d1f8ab2232eb539c5501487ac408454594e7491..ee6b76c412beaaffcd42ce07a14b03c9e8522ab9 100644 (file)
@@ -9,12 +9,14 @@ defmodule Pleroma.Helpers.MediaHelper do
 
   @ffmpeg_opts [{:sync, true}, {:stdout, true}]
 
-  def ffmpeg_resize_remote(uri, max_width, max_height) do
+  def ffmpeg_resize_remote(uri, %{max_width: max_width, max_height: max_height}) do
     cmd = ~s"""
     curl -L "#{uri}" |
-    ffmpeg -i pipe:0 -vf \
-      "scale='min(#{max_width},iw)':min'(#{max_height},ih)':force_original_aspect_ratio=decrease" \
-      -f image2 pipe:1 | \
+    ffmpeg -i pipe:0 -f lavfi -i color=c=white \
+      -filter_complex "[0:v] scale='min(#{max_width},iw)':'min(#{max_height},ih)': \
+        force_original_aspect_ratio=decrease [scaled]; \
+        [1][scaled] scale2ref [bg][img]; [bg] setsar=1 [bg]; [bg][img] overlay=shortest=1" \
+      -f image2 -vcodec mjpeg -frames:v 1 pipe:1 | \
     cat
     """
 
@@ -22,41 +24,4 @@ defmodule Pleroma.Helpers.MediaHelper do
       {:ok, Enum.join(stdout_list)}
     end
   end
-
-  @doc "Returns a temporary path for an URI"
-  def temporary_path_for(uri) do
-    name = Path.basename(uri)
-    random = rand_uniform(999_999)
-    Path.join(System.tmp_dir(), "#{random}-#{name}")
-  end
-
-  @doc "Stores binary content fetched from specified URL as a temporary file."
-  @spec store_as_temporary_file(String.t(), binary()) :: {:ok, String.t()} | {:error, atom()}
-  def store_as_temporary_file(url, body) do
-    path = temporary_path_for(url)
-    with :ok <- File.write(path, body), do: {:ok, path}
-  end
-
-  @doc "Modifies image file at specified path by resizing to specified limit dimensions."
-  @spec mogrify_resize_to_limit(String.t(), String.t()) :: :ok | any()
-  def mogrify_resize_to_limit(path, resize_dimensions) do
-    with %Mogrify.Image{} <-
-           path
-           |> Mogrify.open()
-           |> Mogrify.resize_to_limit(resize_dimensions)
-           |> Mogrify.save(in_place: true) do
-      :ok
-    end
-  end
-
-  defp rand_uniform(high) do
-    Code.ensure_loaded(:rand)
-
-    if function_exported?(:rand, :uniform, 1) do
-      :rand.uniform(high)
-    else
-      # Erlang/OTP < 19
-      apply(:crypto, :rand_uniform, [1, high])
-    end
-  end
 end
index fb4b80379e5efedf572dff563b8554ffb7000412..12d4401faf2eac7734f276fa6d7a69337bc9dc7a 100644 (file)
@@ -82,17 +82,16 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do
     {thumbnail_max_width, thumbnail_max_height}
   end
 
-  defp handle_preview("image/" <> _ = content_type, %{params: params} = conn, url) do
+  defp handle_preview("image/" <> _ = _content_type, %{params: params} = conn, url) do
     with {thumbnail_max_width, thumbnail_max_height} <- thumbnail_max_dimensions(params),
          media_proxy_url <- MediaProxy.url(url),
          {:ok, thumbnail_binary} <-
            MediaHelper.ffmpeg_resize_remote(
              media_proxy_url,
-             thumbnail_max_width,
-             thumbnail_max_height
+             %{max_width: thumbnail_max_width, max_height: thumbnail_max_height}
            ) do
       conn
-      |> put_resp_header("content-type", content_type)
+      |> put_resp_header("content-type", "image/jpeg")
       |> send_resp(200, thumbnail_binary)
     else
       _ ->