Skip to main content

Crate letratag_render

Crate letratag_render 

Source
Expand description

Deterministic image rendering. The canvas is feed columns by 32 head rows.

Active rows are a design choice, not a physical printhead calibration. Images keep their aspect ratio (rounded down to whole pixels, with a one-pixel minimum), including any existing white margins, and are centered on the full canvas. An odd spare pixel goes on the right or bottom. Scaling uses nearest neighbors sampled at pixel centers. No text, font, or PDF rendering is done.

§letratag-render

Bounded, deterministic image rendering for the DYMO LetraTag 200B: PNG or 8-bit grayscale input becomes a 32-row binary raster in the wire format of letratag-protocol, and rasters can be encoded back to PNG previews. No Bluetooth, CUPS, or hardware dependency.

crates.io repository

Part of letratag-linux.

§Install

[dependencies]
letratag-render = "0.1.1"

Rust 1.98 or newer. No default features; there are no feature flags. PNG support uses the image crate; letratag-protocol provides the raster type.

§Examples

§Render grayscale samples

render_gray takes row-major 8-bit grayscale (0 is black, 255 is white). Images keep their aspect ratio (rounded down to whole pixels, one-pixel minimum) and are centered on the canvas; an odd spare pixel goes to the right or bottom. Scaling samples nearest neighbors at pixel centers.

use letratag_render::{render_gray, RenderOptions};

let pixels = vec![0u8; 4 * 2]; // 4x2 black source
let raster = render_gray(4, 2, &pixels, RenderOptions::default()).unwrap();
assert_eq!(raster.width(), 400); // the default output width
// The 4x2 source scales to 60x30 and is centered on the 400x32 canvas.
assert!(raster.get(200, 16));
assert!(!raster.get(0, 0));

§Render a PNG and build a preview

render_png decodes only PNG (header dimensions are checked before decoder construction, and decoder buffers are bounded). preview_png encodes the actual full-height raster, without rescaling or trimming, as a grayscale PNG.

use letratag_render::{preview_png, render_gray, render_png, RenderOptions};

let raster = render_gray(2, 2, &[0, 255, 255, 0], RenderOptions::default()).unwrap();
let png = preview_png(&raster).unwrap();
assert_eq!(&png[..8], b"\x89PNG\r\n\x1a\n");

// The preview is a full-height grayscale PNG that decodes again.
let roundtrip = render_png(&png, RenderOptions::default()).unwrap();
assert_eq!(roundtrip.width(), raster.width());

§Options and validation errors

RenderOptions selects the output width (feed columns), the number of active rows across the tape, the luminance threshold, and optional deterministic 4x4 Bayer dithering. Invalid options and mismatched input are rejected with structured errors before any rendering.

use letratag_render::{render_gray, Error, RenderOptions};

let mut options = RenderOptions::default();
options.width = 0;
assert!(matches!(
    render_gray(1, 1, &[0], options),
    Err(Error::InvalidOutputWidth { width: 0 })
));
assert!(matches!(
    render_gray(1, 1, &[0, 0], RenderOptions::default()),
    Err(Error::GrayscaleLength { .. })
));

§API overview

ItemPurpose
render_pngDecode a bounded PNG into a Raster
render_grayRender row-major 8-bit grayscale into a Raster
preview_pngEncode a Raster as a full-height grayscale PNG
RenderOptionsOutput width, active rows, threshold, dither (Default: 400 columns, 30 rows, 128, no dither)
ErrorBounded, structured rendering errors
MAX_PNG_BYTES, MAX_SOURCE_DIMENSION, MAX_SOURCE_PIXELS, MAX_DECODE_BYTESInput and decoder resource limits

§Limitations

  • PNG only. No JPEG, text, font, or PDF rendering. For APNG, only the default image is rendered, not animation frames.
  • Rendering is aspect-ratio preserving with thresholding or Bayer dithering. It never stretches, crops silently, or fits to page; content outside the active rows is a design choice, not a physical printhead calibration.
  • The 30 active rows are a design convention (S1’s canvas), not a measured printhead limit; the full 32-row wire frame is always transmitted.
  • This crate renders images; it does not print. Feeding a raster to a printer is the job of a transport (see letratag-transport), and physical print completion is never proven by a raster or a preview.

§License

MIT. See the main repository for the full license text and the reference-notice inventory in docs/legal/.

Structs§

RenderOptions

Enums§

Error

Constants§

MAX_DECODE_BYTES
MAX_PNG_BYTES
MAX_SOURCE_DIMENSION
MAX_SOURCE_PIXELS

Functions§

preview_png
Encode the actual full-height raster, without rescaling or trimming.
render_gray
Render row-major 8-bit grayscale: zero is black and 255 is white.
render_png
Decode only PNG. Header dimensions are checked before decoder construction; Limits bounds its buffers and decoded storage is checked before allocation. Alpha is composited on white before integer Rec. 709 luminance conversion. For APNG, only the default PNG image is rendered, not animation frames.