defmodule Pdf.Image do
@moduledoc false
defstruct bits: nil,
width: nil,
height: nil,
color_type: nil,
size: nil,
data: nil,
dictionary: nil
import Pdf.Size
@stream_start "\nstream\n"
@stream_end "endstream\n"
def new({:binary, image_data}, objects) do
case identify_image(image_data) do
:jpeg ->
{Pdf.Images.JPEG.prepare_image(image_data), objects}
:png ->
Pdf.Images.PNG.prepare_image(image_data, objects)
_else ->
{:error, :image_format_not_recognised}
end
end
def new(image_path, objects) do
new({:binary, File.read!(image_path)}, objects)
end
def identify_image(<<255, 216, _rest::binary>>), do: :jpeg
def identify_image(<<137, 80, 78, 71, 13, 10, 26, 10, _rest::binary>>), do: :png
def identify_image(_), do: {:error, :image_format_not_recognised}
def size(%__MODULE__{size: size, dictionary: dictionary}) do
size_of(dictionary) + size + byte_size(@stream_start <> @stream_end)
end
def to_iolist(%__MODULE__{data: data, dictionary: dictionary}) do
Pdf.Export.to_iolist(
Enum.filter(
[
dictionary,
@stream_start,
data,
@stream_end
],
& &1
)
)
end
defimpl Pdf.Size do
def size_of(%Pdf.Image{} = image), do: Pdf.Image.size(image)
end
defimpl Pdf.Export do
def to_iolist(%Pdf.Image{} = image), do: Pdf.Image.to_iolist(image)
end
end