Docs
/

@leumas/adapter-meme

Meme / image-caption adapter — impact-text captions, meme templates (Drake, Distracted Boyfriend, Galaxy Brain, …), demotivational posters, free-form text, and a deep-fry filter. Text is drawn as SVG...

@leumas/adapter-meme

Meme / image-caption generator. Give it a source image (base64 or data: URL) and it hands back a PNG (base64 + data-URL) with meme text baked on.

Text is drawn with no canvas dependency: every tool builds an SVG string (font, stroke, word-wrap and auto-fit computed in pure JS) and hands it to sharp.composite(), which rasterizes the SVG over the decoded image and re-encodes to PNG.

Tools

ToolInputOutput
caption{ image, top?, bottom?, options? }Classic white impact top/bottom text with black stroke, auto-fit + wrapped.
fromTemplate{ template, texts, image?, options? }Fill a named template's zones. texts is an object keyed by zone key/alias, or an array in zone order. Without image, a flat template background is generated.
demotivational{ image, title?, subtitle?, options? }Black poster: photo inset with a thin white keyline, serif title + subtitle below.
addText{ image, text, x?, y?, size?, color?, options? }Free-form caption. x/y accept absolute px or a 0..1 fraction (default centered).
addBottomBar{ image, text, options? }Reddit/Tumblr-style solid caption bar added above (position:'top', default) or below the image.
deepFry{ image, options: { level: 1..5 } }Crunchy over-saturated "deep-fried" filter (crush → resharpen → saturate → JPEG-crush).
blankTemplate{ template }Render a template's empty background canvas.
imageInfo{ image }Decode and report { width, height, format, bytes, hasAlpha }.
listTemplates(none)Pure. Catalog of templates with their zones.
describeTemplate{ template }Pure. Full zone geometry for one template.
layoutMeme{ template, texts } or { text, width, height }Pure. Preview where captions land (fontSize + wrapped lines per zone) without rasterizing.

Templates: drake, distracted-boyfriend, two-buttons, expanding-brain, change-my-mind, one-does-not-simply (see data/templates.json).

Usage

import meme from '@leumas/adapter-meme'; // or the registry: registry.run('meme', 'caption', args)

const src = fs.readFileSync('cat.png').toString('base64');

const out = await meme.adapters.caption({ image: src, top: 'one does not simply', bottom: 'make a meme' });
// -> { ok:true, format:'png', base64, dataUrl, bytes, width, height }

await meme.adapters.fromTemplate({ template: 'drake', texts: { top: 'writing my own text renderer', bottom: 'building an SVG and letting sharp do it' } });

meme.adapters.listTemplates();           // pure — no image, no sharp needed

Each POST body maps 1:1 onto a call (one args object per tool).

Dependency & lazy guard

The only heavy dependency is sharp (installed at the workspace root, shared with the image pack — not re-installed here). It is imported lazily and guarded: this module always loads even if the native sharp binary is unavailable. The image tools then return { ok:false, unavailable:true, error:'sharp not installed' }, while the pure tools (listTemplates, describeTemplate, layoutMeme) keep working.

DRY boundary

  • This pack captions/decorates raster IMAGES. It does not do ASCII art or emoji art — that

is text and lives in the ascii / emoji text packs.

  • It does not do general image resize / format-convert / color filters — that is the image

pack. meme is the meme-specific layer (impact text, meme templates, demotivational frames, deep-fry) built on top of the same shared sharp.

  • No canvas/jimp dependency is added: text rendering is SVG → sharp.composite.
Source shared/engines/adapters/domain/meme/README.md (no-git)markdownjson
Generated from the Leumas repository. Every page cites the file it came from.leumas.techllms.txt