philomena/lib/philomena/processors/png.ex

98 lines
2.3 KiB
Elixir
Raw Normal View History

2019-11-26 01:06:40 +01:00
defmodule Philomena.Processors.Png do
2019-11-26 03:57:47 +01:00
alias Philomena.Intensities
2019-11-26 01:06:40 +01:00
2019-11-26 03:57:47 +01:00
def process(analysis, file, versions) do
dimensions = analysis.dimensions
2020-07-06 20:10:35 +02:00
animated? = analysis.animated?
2019-11-26 01:06:40 +01:00
2019-11-26 03:57:47 +01:00
{:ok, intensities} = Intensities.file(file)
2020-07-06 20:10:35 +02:00
scaled = Enum.flat_map(versions, &scale_if_smaller(file, animated?, dimensions, &1))
2019-11-26 01:06:40 +01:00
2019-11-26 03:57:47 +01:00
%{
intensities: intensities,
thumbnails: scaled
}
2019-11-26 01:06:40 +01:00
end
2021-04-07 21:16:43 +02:00
def post_process(analysis, file) do
if analysis.animated? do
# libpng has trouble with animations, so skip optimization
%{}
else
%{replace_original: optimize(file)}
end
2019-11-26 01:06:40 +01:00
end
2019-11-29 01:11:05 +01:00
def intensities(_analysis, file) do
{:ok, intensities} = Intensities.file(file)
intensities
end
2021-04-01 18:49:41 +02:00
# Sobelow misidentifies removing the .bak file
# sobelow_skip ["Traversal.FileModule"]
2019-11-26 03:57:47 +01:00
defp optimize(file) do
2019-11-26 01:06:40 +01:00
optimized = Briefly.create!(extname: ".png")
{_output, 0} =
2019-11-27 02:45:57 +01:00
System.cmd("optipng", ["-fix", "-i0", "-o2", "-quiet", "-clobber", file, "-out", optimized])
# Remove useless .bak file
File.rm(optimized <> ".bak")
2019-11-26 03:57:47 +01:00
optimized
end
2020-07-06 20:10:35 +02:00
defp scale_if_smaller(_file, _animated?, _dimensions, {:full, _target_dim}) do
2019-11-27 02:45:57 +01:00
[{:symlink_original, "full.png"}]
2019-11-26 03:57:47 +01:00
end
2020-07-06 20:12:18 +02:00
defp scale_if_smaller(
file,
animated?,
{width, height},
{thumb_name, {target_width, target_height}}
) do
2019-11-26 03:57:47 +01:00
if width > target_width or height > target_height do
2020-07-06 20:10:35 +02:00
scaled = scale(file, animated?, {target_width, target_height})
2019-11-26 03:57:47 +01:00
2019-11-27 02:45:57 +01:00
[{:copy, scaled, "#{thumb_name}.png"}]
2019-11-26 03:57:47 +01:00
else
2019-11-27 02:45:57 +01:00
[{:symlink_original, "#{thumb_name}.png"}]
2019-11-26 03:57:47 +01:00
end
2019-11-26 01:06:40 +01:00
end
2020-07-06 20:10:35 +02:00
defp scale(file, animated?, {width, height}) do
2019-11-26 01:06:40 +01:00
scaled = Briefly.create!(extname: ".png")
2020-01-11 05:20:19 +01:00
scale_filter =
"scale=w=#{width}:h=#{height}:force_original_aspect_ratio=decrease,format=rgb32"
2019-11-26 01:06:40 +01:00
{_output, 0} =
2020-07-06 20:10:35 +02:00
cond do
animated? ->
2020-07-06 20:12:18 +02:00
System.cmd("ffmpeg", [
"-loglevel",
"0",
"-y",
"-i",
file,
"-plays",
"0",
"-vf",
scale_filter,
"-f",
"apng",
scaled
])
2020-01-11 05:20:19 +01:00
2020-07-06 20:10:35 +02:00
true ->
System.cmd("ffmpeg", ["-loglevel", "0", "-y", "-i", file, "-vf", scale_filter, scaled])
end
System.cmd("optipng", ["-i0", "-o1", "-quiet", "-clobber", scaled])
2019-11-26 01:06:40 +01:00
2019-11-26 03:57:47 +01:00
scaled
2019-11-26 01:06:40 +01:00
end
2019-12-22 15:19:43 +01:00
end