NAME

Langertha::Content::Image - Canonical image content block with cross-provider conversion (OpenAI / Anthropic / Gemini)

VERSION

version 0.500

SYNOPSIS

use Langertha::Content::Image;

# From a remote URL
my $img = Langertha::Content::Image->from_url('https://example.com/cat.jpg');

# From a local file (media_type sniffed from extension)
my $img = Langertha::Content::Image->from_file('/tmp/cat.png');

# From raw bytes
my $img = Langertha::Content::Image->from_data($bytes, media_type => 'image/jpeg');

# From an existing base64 string
my $img = Langertha::Content::Image->from_base64($b64, media_type => 'image/png');

# Embed in a chat message — Langertha::Role::Chat converts per engine
my $response = $engine->simple_chat_f({
    role    => 'user',
    content => [ 'What is in this image?', $img ],
});

DESCRIPTION

Provider-neutral image block. Carries either a remote URL, a base64 payload, or both, plus an IANA media_type. Serializes to the three dominant vision-chat wire formats:

  • OpenAI chat completions — { type = 'image_url', image_url => { url => ... } }>

  • Anthropic messages — { type = 'image', source => { type => 'url' | 'base64', ... } }>

  • Google Gemini — { inline_data = { mime_type => ..., data => <base64> } }>

Gemini requires base64, so to_gemini will transparently download a remote URL on first call (cached on the object).

url

Remote HTTP(S) URL of the image. May be passed through directly (OpenAI, Anthropic) or auto-downloaded and base64-encoded (Gemini).

base64

The base64-encoded image payload (no data: URL prefix). Can be supplied at construction, or populated lazily when a provider that requires inline data (Gemini) is targeted.

media_type

IANA media type (image/jpeg, image/png, image/gif, image/webp). Required for base64 payloads on Anthropic and Gemini. Sniffed from the file extension by from_file and from the URL path by from_url.

from_url

my $img = Langertha::Content::Image->from_url($url);
my $img = Langertha::Content::Image->from_url($url, media_type => 'image/jpeg');

Builds an image block referencing a remote URL. Media type is sniffed from the URL extension when not provided.

from_file

my $img = Langertha::Content::Image->from_file('/tmp/cat.png');

Reads a local file, base64-encodes it, and sniffs the media type from the extension (unless media_type is passed).

from_data

my $img = Langertha::Content::Image->from_data($bytes, media_type => 'image/jpeg');

Builds an image block from raw bytes. media_type is required.

from_base64

my $img = Langertha::Content::Image->from_base64($b64, media_type => 'image/png');

Builds an image block from an existing base64 string.

ensure_base64

my $b64 = $img->ensure_base64;

Returns the base64 payload, fetching the URL over HTTP if necessary. Populates media_type from the response Content-Type header when the image was URL-only. Caches the result on the object.

to_openai

my $block = $img->to_openai;
# { type => 'image_url', image_url => { url => ... } }

Serializes to the OpenAI chat-completions image block. Uses the URL when available, otherwise emits a data: URL from the base64 payload.

to_anthropic

my $block = $img->to_anthropic;
# { type => 'image', source => { type => 'url', url => ... } }
# or
# { type => 'image', source => { type => 'base64', media_type => ..., data => ... } }

Serializes to the Anthropic messages image block. Prefers a URL source when available; otherwise emits an inline base64 source (media_type required).

to_gemini

my $block = $img->to_gemini;
# { inline_data => { mime_type => ..., data => <base64> } }

Serializes to the Gemini inlineData part. Auto-downloads URL-only images because Gemini has no URL-fetching equivalent.

SEE ALSO

SUPPORT

Issues

Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha/issues.

IRC

Join #langertha on irc.perl.org or message Getty directly.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <getty@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus https://raudssus.de/.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.