Merge branch 'feat/vips-heif-upload-filter' into 'develop'

Draft: Pleroma.Upload.Filter.HeifToJpeg using Vix

See merge request pleroma/pleroma!4293
This commit is contained in:
feld 2025-03-25 14:12:18 +00:00
commit a442735949
7 changed files with 96 additions and 1 deletions

View file

@ -0,0 +1 @@
Pleroma.Upload.Filter.HeifToJpeg to convert Apple HEIF/HEIC files to JPEG

View file

@ -712,6 +712,12 @@ No specific configuration.
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`.
#### Pleroma.Upload.Filter.HeifToJpeg
This filter converts HEIC/HEIF files commonly found on MacOS/iOS to JPEGs.
No specific configuration.
## Email
### Pleroma.Emails.Mailer

View file

@ -172,7 +172,8 @@ defmodule Pleroma.ApplicationRequirements do
check_filter(Pleroma.Upload.Filter.Exiftool.ReadDescription, "exiftool"),
check_filter(Pleroma.Upload.Filter.Mogrify, "mogrify"),
check_filter(Pleroma.Upload.Filter.Mogrifun, "mogrify"),
check_filter(Pleroma.Upload.Filter.AnalyzeMetadata, "ffprobe")
check_filter(Pleroma.Upload.Filter.AnalyzeMetadata, "ffprobe"),
check_filter(Pleroma.Upload.Filter.HeifToJpeg)
]
preview_proxy_commands_status =
@ -254,6 +255,12 @@ defmodule Pleroma.ApplicationRequirements do
defp check_repo_pool_size!(result), do: result
defp check_filter(Pleroma.Upload.Filter.HeifToJpeg) do
{:ok, supported} = Vix.Vips.Image.supported_saver_suffixes()
".heif" in supported
end
defp check_filter(filter, command_required) do
filters = Config.get([Pleroma.Upload, :filters])

View file

@ -0,0 +1,42 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Upload.Filter.HeifToJpeg do
@behaviour Pleroma.Upload.Filter
alias Pleroma.Upload
alias Vix.Vips.Image
@spec filter(Pleroma.Upload.t()) :: {:ok, :atom} | {:error, String.t()}
def filter(
%Pleroma.Upload{name: name, path: path, tempfile: tempfile, content_type: "image/heic"} =
upload
) do
try do
name = name |> String.replace_suffix(".heic", ".jpg")
path = path |> String.replace_suffix(".heic", ".jpg")
convert(tempfile)
{:ok, :filtered, %Upload{upload | name: name, path: path, content_type: "image/jpeg"}}
rescue
e in ErlangError ->
{:error, "#{__MODULE__}: #{inspect(e)}"}
end
end
def filter(_), do: {:ok, :noop}
defp convert(tempfile) do
new_file = "#{tempfile}.heic"
with {:ok, image} <- Image.new_from_file(tempfile) do
Image.write_to_stream(image, ".jpg")
|> Stream.into(File.stream!(new_file))
|> Stream.run()
File.rename(new_file, tempfile)
else
_ -> raise("Error converting to JPEG with Vix")
end
end
end

0
test/fixtures/heictmp vendored Normal file
View file

BIN
test/fixtures/image.heic vendored Normal file

Binary file not shown.

View file

@ -0,0 +1,39 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Upload.Filter.HeifToJpegTest do
use Pleroma.DataCase, async: true
alias Pleroma.Upload.Filter
@tag :tmp_dir
test "apply HeicToJpeg filter", %{tmp_dir: tmp_dir} do
tmp_file_path = Path.join([tmp_dir, "image.heic"])
File.cp!(
"test/fixtures/image.heic",
tmp_file_path
)
upload = %Pleroma.Upload{
name: "image.heic",
content_type: "image/heic",
path: Path.absname("test/fixtures/image.heic"),
tempfile: tmp_file_path
}
{: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)
end
end