Packages
image
0.64.0
0.72.0
0.71.0
0.70.0
0.69.0
0.68.0
0.67.0
0.67.0-dev
retired
0.66.0
0.65.0
0.64.0
0.63.0
0.62.1
0.62.0
0.61.1
0.61.0
0.60.0
0.59.3
0.59.2
0.59.1
0.59.0
0.58.0
0.57.0
0.56.1
0.56.0
0.55.2
0.55.1
retired
0.55.0
0.54.4
0.54.3
0.54.2
0.54.1
0.54.0
0.53.0
0.52.3
0.52.2
0.52.1
0.52.0
retired
0.51.0
0.50.0
0.49.0
0.48.1
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.2
0.43.1
0.43.0
0.42.0
0.41.0
0.40.0
0.39.3
0.39.2
0.39.1
0.39.0
0.38.4
0.38.3
0.38.2
0.38.1
0.38.0
0.37.0
0.36.2
0.36.1
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.1
0.31.0
0.30.0
0.29.0
0.28.2
0.28.1
0.28.0
0.27.0
0.26.0
0.25.1
0.25.0
0.24.1
0.24.0
0.23.2
0.23.1
0.23.0
0.22.1
0.22.0
0.21.0
0.20.0
retired
0.19.0
0.18.1
0.18.0
0.17.0
0.16.0
0.15.0
0.14.4
0.14.2
0.14.1
0.14.0
retired
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.10.0-rc.0
retired
0.9.0
retired
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
An approachable image processing library primarily based upon Vix and libvips that is NIF-based, fast, multi-threaded, pipelined and has a low memory footprint.
Current section
Files
Jump to
Current section
Files
lib/image/xmp.ex
defmodule Image.Xmp do
@moduledoc """
Functions to extract and interpret image XMP
data.
"""
import SweetXml
@doc """
Extracts an XMP metadata blob into an Elixir map.
### Arguments
* `xmp` is either the raw XMP XML payload as a string, or a parsed
`SweetXml` xml element. This is the form libvips returns from
`Vix.Vips.Image.header_value(image, "xmp-data")`.
### Returns
* A map keyed by atom field names (`:artist`, `:keywords`,
`:created_at`, `:rating`, …) with the parsed values.
"""
@spec extract_xmp(binary() | tuple()) :: map()
def extract_xmp(xmp) do
SweetXml.xpath(xmp, ~x"//x:xmpmeta",
artist: ~x".//dc:creator/rdf:Seq/rdf:li/text()"s |> transform_by(&maybe_nil/1),
keywords: ~x".//dc:subject/rdf:Bag/rdf:li/text()"ls,
created_at: ~x".//@xmp:CreateDate"s |> transform_by(&to_date_time/1),
rating: ~x".//@xmp:Rating"s |> transform_by(&to_integer/1),
copyright: [
~x".//dc:rights/rdf:Alt"l,
text: ~x"./rdf:li/text()"ls,
language: ~x"./rdf:li/@xml:lang"ls
],
title: [
~x".//dc:title/rdf:Alt"l,
text: ~x"./rdf:li/text()"ls,
language: ~x"./rdf:li/@xml:lang"ls
],
description: [
~x".//dc:description/rdf:Alt"l,
text: ~x"./rdf:li/text()"ls,
language: ~x"./rdf:li/@xml:lang"ls
],
location: [
~x".//rdf:Description",
city: ~x"./@photoshop:City"s |> transform_by(&maybe_nil/1),
state: ~x"./@photoshop:State"s |> transform_by(&maybe_nil/1),
territory: ~x"./@photoshop:Country"s |> transform_by(&maybe_nil/1),
territory_code: ~x"./@Iptc4xmpCore:CountryCode"s |> transform_by(&maybe_nil/1)
]
)
|> zip(:description)
|> zip(:title)
|> zip(:copyright)
end
defp zip(map, key) do
case Map.fetch(map, key) do
{:ok, value} ->
zipped = zip(value)
Map.put(map, key, zipped)
:error ->
map
end
end
defp zip([%{language: languages, text: texts}]) do
languages
|> Enum.zip(texts)
|> Map.new()
end
defp zip([]) do
nil
end
defp to_date_time("") do
nil
end
defp to_date_time(string) do
case NaiveDateTime.from_iso8601(string) do
{:ok, date_time} -> date_time
_other -> string
end
end
defp to_integer(string) do
case Integer.parse(string) do
{integer, ""} -> integer
_other -> nil
end
end
defp maybe_nil(""), do: nil
defp maybe_nil(other), do: other
end