PdfElixide.Document.Image (pdf_elixide v0.12.0)

Copy Markdown View Source

A raster image (photo, logo, scanned picture) extracted from a PDF page, with its zero-based page index, on-page bounding box, and dimensions.

The pixel data is not carried on the struct; instead :ref is a handle to the underlying image, and you encode it on demand with to_binary/2 (bytes) or save/3 (to a file), choosing :png or :jpeg:

{:ok, png} = PdfElixide.Document.Image.to_binary(image)              # PNG bytes
{:ok, jpg} = PdfElixide.Document.Image.to_binary(image, format: :jpeg)
:ok = PdfElixide.Document.Image.save(image, "out.png")              # format inferred
:ok = PdfElixide.Document.Image.save(image, "out.jpg", format: :jpeg)

:format reports how the image was stored in the PDF — :jpeg (a JPEG blob) or :raw (decoded pixels) — which tells you whether a JPEG encode is lossless: for a :jpeg source the original bytes are passed through untouched (except CMYK JPEGs, which must be re-encoded to RGB), while a :raw source is always encoded fresh. The :color_space and :bits_per_component fields describe the image as it was stored.

For the raw stored bytes (rather than an encoded PNG/JPEG), use data/1, which returns {:jpeg, bytes} (the original JPEG blob) or {:raw, bytes, pixel_format} (bare pixels — not a standalone file; pair them with :width, :height, and :color_space, or reach for to_binary/2 when you want an encoded image).

data/1, to_binary/2 and save/3 take the handle's lock shared and close/1 takes it exclusively, so encoding one image from several processes runs in parallel; see the Concurrency guide.

Summary

Types

The stored color space, resolved to an atom. :icc_based covers any ICC-profile-based space (the component count is dropped).

Options for to_binary/2 and save/3.

The layout of raw (uncompressed) pixel data from data/1.

The raw stored bytes of an image, from data/1: either the original JPEG blob or bare decoded pixels with their layout.

t()

Functions

Releases the image's pixel data immediately.

Returns whether the image has been released with close/1.

Returns the image's raw stored bytes.

Same as data/1 but returns the raw data directly, raising on error.

Writes the image to a file at the given path.

Same as save/3 but raises on error.

Encodes the image to a binary in the requested format.

Same as to_binary/2 but returns the binary directly, raising on error.

Types

color_space()

@type color_space() ::
  :device_rgb
  | :device_gray
  | :device_cmyk
  | :indexed
  | :cal_gray
  | :cal_rgb
  | :lab
  | :icc_based
  | :separation
  | :device_n
  | :pattern

The stored color space, resolved to an atom. :icc_based covers any ICC-profile-based space (the component count is dropped).

image_opts()

@type image_opts() :: [{:format, :png | :jpeg}]

Options for to_binary/2 and save/3.

An unknown key, or a :format other than :png or :jpeg, raises ArgumentError naming the offending key; see the "Errors versus exceptions" section of PdfElixide.Error.

pixel_format()

@type pixel_format() :: :rgb | :grayscale | :cmyk

The layout of raw (uncompressed) pixel data from data/1.

raw_data()

@type raw_data() :: {:jpeg, binary()} | {:raw, binary(), pixel_format()}

The raw stored bytes of an image, from data/1: either the original JPEG blob or bare decoded pixels with their layout.

t()

@type t() :: %PdfElixide.Document.Image{
  bbox: PdfElixide.Geometry.Rect.t() | nil,
  bits_per_component: non_neg_integer(),
  color_space: color_space(),
  format: :jpeg | :raw,
  height: non_neg_integer(),
  page: non_neg_integer(),
  ref: reference(),
  rotation_degrees: integer(),
  width: non_neg_integer()
}

Functions

close(image)

@spec close(t()) :: :ok

Releases the image's pixel data immediately.

The bytes behind :ref are normally freed when the BEAM garbage-collects the handle; close/1 frees them now, which is worth doing when walking many large images. Calling it is optional and idempotent. It takes the handle's lock exclusively, so it waits for an in-flight data/1, to_binary/2 or save/3 on the same image — immediately means as soon as the handle is idle, not preemptively.

Afterwards data/1, to_binary/2, and save/3 return {:error, %PdfElixide.Error{reason: :closed}} (bang variants raise it); the metadata fields on the struct keep working. An image's lifetime is independent of the document it came from — closing either one leaves the other usable.

closed?(image)

@spec closed?(t()) :: boolean()

Returns whether the image has been released with close/1.

data(image)

@spec data(t()) :: {:ok, raw_data()} | {:error, PdfElixide.Error.t()}

Returns the image's raw stored bytes.

Gives {:jpeg, bytes} for a JPEG-stored image (the original DCTDecode blob) or {:raw, bytes, pixel_format} for one stored as decoded pixels, where pixel_format is :rgb, :grayscale, or :cmyk. The :raw bytes are bare pixels, not a standalone image file — use to_binary/2 when you need an encoded PNG or JPEG.

data!(image)

@spec data!(t()) :: raw_data()

Same as data/1 but returns the raw data directly, raising on error.

save(image, path, opts \\ [])

@spec save(t(), Path.t(), image_opts()) :: :ok | {:error, PdfElixide.Error.t()}

Writes the image to a file at the given path.

The output format is taken from opts[:format] when given, otherwise inferred from the path extension (.png → PNG, .jpg/.jpeg → JPEG). An unknown extension with no :format option raises ArgumentError.

The path is handed to the operating system unchanged — see the "File paths" section of PdfElixide.

save!(image, path, opts \\ [])

@spec save!(t(), Path.t(), image_opts()) :: :ok

Same as save/3 but raises on error.

The path is handed to the operating system unchanged — see the "File paths" section of PdfElixide.

to_binary(image, opts \\ [])

@spec to_binary(t(), image_opts()) :: {:ok, binary()} | {:error, PdfElixide.Error.t()}

Encodes the image to a binary in the requested format.

opts[:format] is :png (the default) or :jpeg. For a :jpeg source image the original bytes are returned untouched (zero loss), except CMYK JPEGs which are re-encoded to RGB.

That pass-through copies the stored blob once, straight into the returned binary; the PNG and re-encoding paths hold the encoded image and the binary at the same time, so they peak at roughly twice the output size.

Returns the bytes rather than writing them, so no path is involved; use save/3 to write a file.

to_binary!(image, opts \\ [])

@spec to_binary!(t(), image_opts()) :: binary()

Same as to_binary/2 but returns the binary directly, raising on error.

Returns the bytes rather than writing them, so no path is involved; use save!/3 to write a file.