mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-30 14:57:59 +01:00
all processing code
This commit is contained in:
parent
2159fbd9c7
commit
56db3807aa
6 changed files with 156 additions and 29 deletions
|
@ -15,6 +15,7 @@ defmodule Philomena.Application do
|
||||||
# Starts a worker by calling: Philomena.Worker.start_link(arg)
|
# Starts a worker by calling: Philomena.Worker.start_link(arg)
|
||||||
# {Philomena.Worker, arg},
|
# {Philomena.Worker, arg},
|
||||||
Pow.Store.Backend.MnesiaCache,
|
Pow.Store.Backend.MnesiaCache,
|
||||||
|
Philomena.Servers.ImageProcessor,
|
||||||
{Redix, name: :redix}
|
{Redix, name: :redix}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -8,19 +8,6 @@ defmodule Philomena.ImageIntensities do
|
||||||
|
|
||||||
alias Philomena.ImageIntensities.ImageIntensity
|
alias Philomena.ImageIntensities.ImageIntensity
|
||||||
|
|
||||||
@doc """
|
|
||||||
Returns the list of image_intensities.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
iex> list_image_intensities()
|
|
||||||
[%ImageIntensity{}, ...]
|
|
||||||
|
|
||||||
"""
|
|
||||||
def list_image_intensities do
|
|
||||||
Repo.all(ImageIntensity)
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Gets a single image_intensity.
|
Gets a single image_intensity.
|
||||||
|
|
||||||
|
@ -49,8 +36,8 @@ defmodule Philomena.ImageIntensities do
|
||||||
{:error, %Ecto.Changeset{}}
|
{:error, %Ecto.Changeset{}}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def create_image_intensity(attrs \\ %{}) do
|
def create_image_intensity(image, attrs \\ %{}) do
|
||||||
%ImageIntensity{}
|
%ImageIntensity{image_id: image.id}
|
||||||
|> ImageIntensity.changeset(attrs)
|
|> ImageIntensity.changeset(attrs)
|
||||||
|> Repo.insert()
|
|> Repo.insert()
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ defmodule Philomena.ImageIntensities.ImageIntensity do
|
||||||
@doc false
|
@doc false
|
||||||
def changeset(image_intensity, attrs) do
|
def changeset(image_intensity, attrs) do
|
||||||
image_intensity
|
image_intensity
|
||||||
|> cast(attrs, [])
|
|> cast(attrs, [:nw, :ne, :sw, :se])
|
||||||
|> validate_required([])
|
|> validate_required([:image_id, :nw, :ne, :sw, :se])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -108,6 +108,12 @@ defmodule Philomena.Images.Image do
|
||||||
|> validate_required([])
|
|> validate_required([])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def creation_changeset(image, attrs, attribution) do
|
||||||
|
image
|
||||||
|
|> cast(attrs, [:source_url, :description])
|
||||||
|
|> change(attribution)
|
||||||
|
end
|
||||||
|
|
||||||
def image_changeset(image, attrs) do
|
def image_changeset(image, attrs) do
|
||||||
image
|
image
|
||||||
|> cast(attrs, [
|
|> cast(attrs, [
|
||||||
|
@ -140,4 +146,16 @@ defmodule Philomena.Images.Image do
|
||||||
|> TagDiffer.diff_input(old_tags, new_tags)
|
|> TagDiffer.diff_input(old_tags, new_tags)
|
||||||
|> TagValidator.validate_tags()
|
|> TagValidator.validate_tags()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def thumbnail_changeset(image, attrs) do
|
||||||
|
image
|
||||||
|
|> cast(attrs, [:image_sha512_hash])
|
||||||
|
|> change(thumbnails_generated: true, duplication_checked: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_changeset(image, attrs) do
|
||||||
|
image
|
||||||
|
|> cast(attrs, [:image_sha512_hash])
|
||||||
|
|> change(processed: true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
defmodule Philomena.Processors do
|
defmodule Philomena.Processors do
|
||||||
# alias Philomena.Images.Image
|
alias Philomena.Images.Image
|
||||||
# alias Philomena.Repo
|
alias Philomena.ImageIntensities
|
||||||
|
alias Philomena.Repo
|
||||||
|
alias Philomena.Mime
|
||||||
alias Philomena.Sha512
|
alias Philomena.Sha512
|
||||||
|
alias Philomena.Servers.ImageProcessor
|
||||||
|
|
||||||
@mimes %{
|
@mimes %{
|
||||||
"image/gif" => "image/gif",
|
"image/gif" => "image/gif",
|
||||||
|
@ -29,7 +32,90 @@ defmodule Philomena.Processors do
|
||||||
"video/webm" => Philomena.Processors.Webm
|
"video/webm" => Philomena.Processors.Webm
|
||||||
}
|
}
|
||||||
|
|
||||||
def analysis_to_changes(analysis, file, upload_name) do
|
def after_upload(image, params) do
|
||||||
|
with upload when not is_nil(upload) <- params["image"],
|
||||||
|
file <- upload.path,
|
||||||
|
mime <- @mimes[Mime.file(file)],
|
||||||
|
analyzer when not is_nil(analyzer) <- @analyzers[mime],
|
||||||
|
analysis <- analyzer.analyze(file),
|
||||||
|
changes <- analysis_to_changes(analysis, file, upload.filename)
|
||||||
|
do
|
||||||
|
image
|
||||||
|
|> Image.image_changeset(changes)
|
||||||
|
else
|
||||||
|
_ ->
|
||||||
|
image
|
||||||
|
|> Image.image_changeset(%{})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def after_insert(image) do
|
||||||
|
File.cp!(image.uploaded_image, Path.join([image_file_root(), image.image]))
|
||||||
|
ImageProcessor.cast(self(), image.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_image(image_id) do
|
||||||
|
image = Repo.get!(Image, image_id)
|
||||||
|
|
||||||
|
mime = image.image_mime_type
|
||||||
|
file = image_file(image)
|
||||||
|
analyzer = @analyzers[mime]
|
||||||
|
analysis = analyzer.analyze(file)
|
||||||
|
processor = @processors[mime]
|
||||||
|
process = processor.process(analysis, file)
|
||||||
|
|
||||||
|
apply_edit_script(image, process)
|
||||||
|
sha512 = Sha512.file(file)
|
||||||
|
changeset = Image.thumbnail_changeset(image, %{"image_sha512_hash" => sha512})
|
||||||
|
image = Repo.update!(changeset)
|
||||||
|
|
||||||
|
processor.post_process(analysis, file)
|
||||||
|
sha512 = Sha512.file(file)
|
||||||
|
changeset = Image.process_changeset(image, %{"image_sha512_hash" => sha512})
|
||||||
|
Repo.update!(changeset)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp apply_edit_script(image, changes) do
|
||||||
|
for change <- changes do
|
||||||
|
apply_change(image, change)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp apply_change(image, {:intensities, intensities}) do
|
||||||
|
ImageIntensities.create_image_intensity(image, intensities)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp apply_change(image, {:replace_original, new_file}) do
|
||||||
|
file = image_file(image)
|
||||||
|
|
||||||
|
File.cp(new_file, file)
|
||||||
|
File.chmod(file, 0o755)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp apply_change(image, {:thumbnails, thumbnails}) do
|
||||||
|
thumb_dir = image_thumb_dir(image)
|
||||||
|
|
||||||
|
for thumbnail <- thumbnails do
|
||||||
|
apply_thumbnail(image, thumb_dir, thumbnail)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp apply_thumbnail(_image, thumb_dir, {:copy, new_file, destination}) do
|
||||||
|
new_destination = Path.join([thumb_dir, destination])
|
||||||
|
|
||||||
|
File.cp(new_file, new_destination)
|
||||||
|
File.chmod(new_destination, 0o755)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp apply_thumbnail(image, thumb_dir, {:symlink_original, destination}) do
|
||||||
|
file = image_file(image)
|
||||||
|
new_destination = Path.join([thumb_dir, destination])
|
||||||
|
|
||||||
|
File.ln_s(file, new_destination)
|
||||||
|
File.chmod(new_destination, 0o755)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp analysis_to_changes(analysis, file, upload_name) do
|
||||||
{width, height} = analysis.dimensions
|
{width, height} = analysis.dimensions
|
||||||
%{size: size} = File.stat(file)
|
%{size: size} = File.stat(file)
|
||||||
sha512 = Sha512.file(file)
|
sha512 = Sha512.file(file)
|
||||||
|
@ -50,16 +136,20 @@ defmodule Philomena.Processors do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_upload(image) do
|
|
||||||
File.cp(image.uploaded_image, Path.join([image_file_root(), image.image]))
|
|
||||||
end
|
|
||||||
|
|
||||||
defp aspect_ratio(_, 0), do: 0.0
|
defp aspect_ratio(_, 0), do: 0.0
|
||||||
defp aspect_ratio(w, h), do: w / h
|
defp aspect_ratio(w, h), do: w / h
|
||||||
|
|
||||||
|
defp image_file(image) do
|
||||||
|
Path.join([image_file_root(), image.image])
|
||||||
|
end
|
||||||
|
|
||||||
|
defp image_thumb_dir(image) do
|
||||||
|
Path.join([image_thumbnail_root(), time_identifier(image.created_at), to_string(image.id)])
|
||||||
|
end
|
||||||
|
|
||||||
defp build_filename(extension) do
|
defp build_filename(extension) do
|
||||||
[
|
[
|
||||||
time_identifier(),
|
time_identifier(DateTime.utc_now()),
|
||||||
"/",
|
"/",
|
||||||
usec_identifier(),
|
usec_identifier(),
|
||||||
pid_identifier(),
|
pid_identifier(),
|
||||||
|
@ -69,10 +159,8 @@ defmodule Philomena.Processors do
|
||||||
|> Enum.join()
|
|> Enum.join()
|
||||||
end
|
end
|
||||||
|
|
||||||
defp time_identifier do
|
defp time_identifier(time) do
|
||||||
now = DateTime.utc_now()
|
Enum.join([time.year, time.month, time.day], "/")
|
||||||
|
|
||||||
Enum.join([now.year, now.month, now.day], "/")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp usec_identifier do
|
defp usec_identifier do
|
||||||
|
|
33
lib/philomena/servers/image_processor.ex
Normal file
33
lib/philomena/servers/image_processor.ex
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
defmodule Philomena.Servers.ImageProcessor do
|
||||||
|
use GenServer
|
||||||
|
|
||||||
|
def start_link(default) when is_list(default) do
|
||||||
|
GenServer.start_link(__MODULE__, default)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cast(pid, image_id) do
|
||||||
|
GenServer.cast(pid, {:enqueue, image_id})
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def init([]) do
|
||||||
|
{:ok, []}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_cast({:enqueue, image_id}, []) do
|
||||||
|
# Ensure that tempfiles get cleaned up by reaping
|
||||||
|
# the process after it is done
|
||||||
|
Task.async(fn -> process(image_id) end)
|
||||||
|
|> Task.await()
|
||||||
|
|
||||||
|
{:noreply, []}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp process(image_id) do
|
||||||
|
Philomena.Processors.process_image(image_id)
|
||||||
|
#rescue
|
||||||
|
# _ ->
|
||||||
|
# nil
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue