Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
image_codecs.hpp
Go to the documentation of this file.
1#pragma once
2
3// Extended image codecs — GIF and TIFF readers/writers.
4//
5// Skia (the default Pulp decode path via SkImages::DeferredFromEncodedData)
6// covers PNG / JPEG / WebP / BMP / ICO in the m144 prebuilt that Pulp pins,
7// but does NOT compile in the GIF decoder by default and ships no TIFF
8// codec at all. This header fills that gap with dedicated reader/writer
9// entry points.
10//
11// This header provides a Skia-free public surface that:
12// • Decodes GIF87a / GIF89a (single frame + animation frames + LZW + LCT)
13// into RGBA8 pixel buffers using an in-tree decoder. The decoder is
14// MIT-clean (no LZW patent — patent expired in 2004), header-light,
15// and depends only on the C++ standard library.
16// • Decodes Baseline TIFF 6.0 (uncompressed and PackBits compression,
17// 8-bit Grayscale / RGB / RGBA, BitsPerSample=8) into RGBA8. Wider
18// TIFF coverage (LZW, JPEG-in-TIFF, multi-strip stitching) would
19// require libtiff which is heavyweight and only ~MIT-compatible
20// under its custom permissive license; not pulled in here.
21// • Encodes uncompressed Baseline TIFF (RGB / RGBA) and a static
22// GIF89a (single global palette, 256-color quantisation via simple
23// median-cut). Writer paths are intended for editor / asset export
24// use; not optimized for runtime hot paths.
25//
26// The codec functions return std::optional<DecodedRaster> on success and
27// std::nullopt on any malformed input — no exceptions thrown, callers
28// can degrade gracefully (fall back to Skia, or report unsupported).
29//
30// Animation: GifReader::decode_first() decodes a single frame for
31// callers that only want the cover image (matches existing
32// SkImages::DeferredFromEncodedData behavior). GifReader::decode_all()
33// returns every frame in order plus per-frame delays in milliseconds;
34// the GIF89a wire format stores centi-seconds, which the codec converts.
35
36#include <cstddef>
37#include <cstdint>
38#include <optional>
39#include <string>
40#include <vector>
41
42namespace pulp::canvas {
43
47 uint32_t width = 0;
48 uint32_t height = 0;
50 std::vector<uint8_t> rgba;
51};
52
53struct GifFrame {
58 uint32_t delay_ms = 0;
59};
60
62class GifReader {
63public:
67 static std::optional<DecodedRaster> decode_first(const uint8_t* data,
68 std::size_t size);
69
73 static std::optional<std::vector<GifFrame>> decode_all(
74 const uint8_t* data, std::size_t size);
75
80 static bool is_gif(const uint8_t* data, std::size_t size);
81};
82
88class GifWriter {
89public:
93 static std::vector<uint8_t> encode_still(const DecodedRaster& raster);
94};
95
108public:
109 static std::optional<DecodedRaster> decode(const uint8_t* data,
110 std::size_t size);
111
112 static bool is_tiff(const uint8_t* data, std::size_t size);
113};
114
120public:
121 static std::vector<uint8_t> encode(const DecodedRaster& raster);
122};
123
124} // namespace pulp::canvas
GIF reader. Decodes GIF87a + GIF89a streams.
Definition image_codecs.hpp:62
static bool is_gif(const uint8_t *data, std::size_t size)
Quick probe — does the byte stream begin with a GIF87a/89a signature?
static std::optional< std::vector< GifFrame > > decode_all(const uint8_t *data, std::size_t size)
Decode every frame in order.
static std::optional< DecodedRaster > decode_first(const uint8_t *data, std::size_t size)
Decode just the first frame of the GIF.
GIF writer.
Definition image_codecs.hpp:88
static std::vector< uint8_t > encode_still(const DecodedRaster &raster)
Encode the raster as a standalone GIF89a file.
TIFF reader.
Definition image_codecs.hpp:107
static bool is_tiff(const uint8_t *data, std::size_t size)
static std::optional< DecodedRaster > decode(const uint8_t *data, std::size_t size)
TIFF writer.
Definition image_codecs.hpp:119
static std::vector< uint8_t > encode(const DecodedRaster &raster)
Definition affine_transform.hpp:24
A decoded raster image.
Definition image_codecs.hpp:46
std::vector< uint8_t > rgba
Tightly packed RGBA8. .size() == width * height * 4.
Definition image_codecs.hpp:50
uint32_t height
Definition image_codecs.hpp:48
uint32_t width
Definition image_codecs.hpp:47
Definition image_codecs.hpp:53
uint32_t delay_ms
Frame delay in milliseconds (the GIF spec uses centi-seconds; the codec converts so callers can hand ...
Definition image_codecs.hpp:58
DecodedRaster raster
Definition image_codecs.hpp:54