Add resizing filter to make sure pictures are not too big

Closes #810

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-08-05 12:48:22 +02:00
parent f3a05929d9
commit 51cd066a14
No known key found for this signature in database
GPG key ID: A061B9DDE0CA0773
4 changed files with 67 additions and 2 deletions

View file

@ -67,6 +67,7 @@ config :mobilizon, Mobilizon.Web.Upload,
filters: [ filters: [
Mobilizon.Web.Upload.Filter.Dedupe, Mobilizon.Web.Upload.Filter.Dedupe,
Mobilizon.Web.Upload.Filter.AnalyzeMetadata, Mobilizon.Web.Upload.Filter.AnalyzeMetadata,
Mobilizon.Web.Upload.Filter.Resize,
Mobilizon.Web.Upload.Filter.Optimize Mobilizon.Web.Upload.Filter.Optimize
], ],
allow_list_mime_types: ["image/gif", "image/jpeg", "image/png", "image/webp"], allow_list_mime_types: ["image/gif", "image/jpeg", "image/png", "image/webp"],

View file

@ -0,0 +1,42 @@
defmodule Mobilizon.Web.Upload.Filter.Resize do
@moduledoc """
Resize the pictures if they're bigger than maximum size.
This filter requires `Mobilizon.Web.Upload.Filter.AnalyzeMetadata` to be performed before.
"""
@behaviour Mobilizon.Web.Upload.Filter
@maximum_width 1_920
@maximum_height 1_080
def filter(%Mobilizon.Web.Upload{
tempfile: file,
content_type: "image" <> _,
width: width,
height: height
}) do
file
|> Mogrify.open()
|> Mogrify.resize(string(limit_sizes({width, height})))
|> Mogrify.save(in_place: true)
{:ok, :filtered}
end
def filter(_), do: {:ok, :noop}
def limit_sizes({width, height}) when width > @maximum_width do
new_height = round(@maximum_width * height / width)
limit_sizes({@maximum_width, new_height})
end
def limit_sizes({width, height}) when height > @maximum_height do
new_width = round(@maximum_height * width / height)
limit_sizes({new_width, @maximum_height})
end
def limit_sizes({width, height}), do: {width, height}
defp string({width, height}), do: "#{width}x#{height}"
end

View file

@ -60,9 +60,11 @@ defmodule Mobilizon.Web.Upload do
tempfile: String.t(), tempfile: String.t(),
content_type: String.t(), content_type: String.t(),
path: String.t(), path: String.t(),
size: integer() size: integer(),
width: integer(),
height: integer()
} }
defstruct [:id, :name, :tempfile, :content_type, :path, :size] defstruct [:id, :name, :tempfile, :content_type, :path, :size, :width, :height]
@spec store(source, options :: [option()]) :: {:ok, map()} | {:error, any()} @spec store(source, options :: [option()]) :: {:ok, map()} | {:error, any()}
def store(upload, opts \\ []) do def store(upload, opts \\ []) do

View file

@ -0,0 +1,20 @@
defmodule Mobilizon.Web.Upload.Filter.ResizeTest do
use Mobilizon.DataCase, async: true
alias Mobilizon.Web.Upload.Filter.Resize
test "does not resize if dimensions are ok" do
assert {100, 150} == Resize.limit_sizes({100, 150})
end
test "does resize only width if needed" do
assert {1_920, 960} == Resize.limit_sizes({2_000, 1_000})
end
test "does resize only height if needed" do
assert {540, 1_080} == Resize.limit_sizes({1_000, 2_000})
end
test "does resize if dimentions are really big, and keeps ratio" do
assert {724, 1080} == Resize.limit_sizes({10_050, 15_000})
end
end