Ootempl.Image (ootempl v0.3.0)

Functions for detecting, validating, and embedding images in Word documents.

This module provides functionality to:

  • Find images with placeholder markers in Word XML
  • Parse placeholder names from alt text markers
  • Validate image files (existence, readability, format)
  • Read image dimensions for aspect ratio calculations
  • Embed images into .docx archives
  • Manage content types for image MIME types
  • Calculate scaled dimensions to fit template bounds

Summary

Functions

Adds or updates a content type entry in the content types XML.

Calculates scaled dimensions to fit template bounds while preserving aspect ratio.

Finds all placeholder images in the given XML element.

Generates a unique filename for the word/media/ folder.

Reads the dimensions (width and height) of an image file.

Returns the MIME type for a given file extension.

Parses the [Content_Types].xml file.

Serializes the content types XML back to a string.

Validates an image file at the given path.

Functions

add_content_type(types_xml, extension, mime_type)

@spec add_content_type(tuple(), String.t(), String.t()) :: tuple()

Adds or updates a content type entry in the content types XML.

If the extension already has a content type defined, it is not added again.

Parameters

  • types_xml - The parsed XML element from parse_content_types/1
  • extension - File extension without the dot (e.g., "png")
  • mime_type - MIME type string (e.g., "image/png")

Returns

Updated XML element

Examples

iex> Ootempl.Image.add_content_type(types_xml, "png", "image/png")
{...}

calculate_scaled_dimensions(arg1, arg2)

@spec calculate_scaled_dimensions(
  {number(), number()},
  {number(), number()} | nil
) :: {float(), float()}

Calculates scaled dimensions to fit template bounds while preserving aspect ratio.

Uses the smaller scale factor to ensure the image fits within the bounds.

Parameters

  • source_dims - Source image dimensions as {width, height}
  • template_dims - Template bounds as {width, height}

Returns

Scaled dimensions as {width, height}

Examples

iex> Ootempl.Image.calculate_scaled_dimensions({800, 600}, {400, 400})
{400.0, 300.0}

iex> Ootempl.Image.calculate_scaled_dimensions({100, 100}, {200, 100})
{100.0, 100.0}

find_placeholder_images(xml_element)

@spec find_placeholder_images(tuple()) :: [map()]

Finds all placeholder images in the given XML element.

Searches for w:drawing elements that contain alt text matching the pattern {{image:name}}.

Parameters

  • xml_element - The XML element to search (typically a document root or paragraph)

Returns

A list of maps containing information about each placeholder image:

%{
  placeholder_name: "logo",
  alt_text: "{{image:logo}}",
  xml_element: xml_drawing,
  relationship_id: "rId5",
  template_dimensions: {width, height}
}

Examples

iex> Ootempl.Image.find_placeholder_images(document_xml)
[
  %{
    placeholder_name: "logo",
    alt_text: "{{image:logo}}",
    xml_element: {...},
    relationship_id: "rId5",
    template_dimensions: {100, 100}
  }
]

generate_media_filename(existing_files, extension)

@spec generate_media_filename([String.t()], String.t()) :: String.t()

Generates a unique filename for the word/media/ folder.

Examines existing filenames and generates the next sequential filename.

Parameters

  • existing_files - List of existing filenames in word/media/ (e.g., ["image1.png", "image2.jpg"])
  • extension - File extension including the dot (e.g., ".png")

Returns

A unique filename string (e.g., "image3.png")

Examples

iex> Ootempl.Image.generate_media_filename(["image1.png", "image2.jpg"], ".png")
"image3.png"

iex> Ootempl.Image.generate_media_filename([], ".png")
"image1.png"

get_image_dimensions(path)

@spec get_image_dimensions(String.t()) ::
  {:ok, {non_neg_integer(), non_neg_integer()}} | {:error, atom()}

Reads the dimensions (width and height) of an image file.

Parameters

  • path - The file path of the image

Returns

  • {:ok, {width, height}} if dimensions can be read
  • {:error, reason} if reading fails

Examples

iex> Ootempl.Image.get_image_dimensions("/path/to/logo.png")
{:ok, {800, 600}}

mime_type_for_extension(ext)

@spec mime_type_for_extension(String.t()) :: String.t() | nil

Returns the MIME type for a given file extension.

Parameters

  • extension - File extension with or without the dot (e.g., ".png" or "png")

Returns

MIME type string, or nil if the extension is not supported

Examples

iex> Ootempl.Image.mime_type_for_extension(".png")
"image/png"

iex> Ootempl.Image.mime_type_for_extension("jpg")
"image/jpeg"

iex> Ootempl.Image.mime_type_for_extension(".bmp")
nil

parse_content_types(xml_string)

@spec parse_content_types(String.t()) :: {:ok, tuple()} | {:error, atom()}

Parses the [Content_Types].xml file.

Parameters

  • xml_string - The XML content as a string

Returns

  • {:ok, xml_element} on successful parse
  • {:error, reason} on parse failure

Examples

iex> xml = ~s(<?xml version="1.0"?><Types xmlns="..."></Types>)
iex> Ootempl.Image.parse_content_types(xml)
{:ok, {...}}

serialize_content_types(types_xml)

@spec serialize_content_types(tuple()) :: String.t()

Serializes the content types XML back to a string.

Parameters

  • types_xml - The XML element to serialize

Returns

XML string

Examples

iex> Ootempl.Image.serialize_content_types(types_xml)
"<?xml version=\"1.0\"?>\n<Types>...</Types>"

validate_image_file(path)

@spec validate_image_file(String.t()) :: :ok | {:error, atom()}

Validates an image file at the given path.

Checks that:

  • The file exists
  • The file is readable
  • The file format is supported (PNG, JPEG, GIF)

Parameters

  • path - The file path to validate

Returns

  • :ok if the file is valid
  • {:error, reason} if validation fails

Examples

iex> Ootempl.Image.validate_image_file("/path/to/logo.png")
:ok

iex> Ootempl.Image.validate_image_file("/path/to/missing.png")
{:error, :file_not_found}

iex> Ootempl.Image.validate_image_file("/path/to/file.bmp")
{:error, :unsupported_format}

xmlAttribute(args \\ [])

(macro)

xmlAttribute(record, args)

(macro)

xmlElement(args \\ [])

(macro)

xmlElement(record, args)

(macro)

xmlText(args \\ [])

(macro)

xmlText(record, args)

(macro)