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:
parent
f3a05929d9
commit
51cd066a14
|
@ -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"],
|
||||||
|
|
42
lib/web/upload/filter/resize.ex
Normal file
42
lib/web/upload/filter/resize.ex
Normal 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
|
|
@ -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
|
||||||
|
|
20
test/web/upload/filter/resize_test.exs
Normal file
20
test/web/upload/filter/resize_test.exs
Normal 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
|
Loading…
Reference in a new issue