![]() |
tinyimg 1.0.0
Lightweight image manipulation library for Cloudflare Workers
|
Lightweight memory management implementatins in C. More...
#include <stddef.h>#include <stdint.h>Go to the source code of this file.
Classes | |
| struct | TinyHeapStats |
| A snapshot of heap occupancy. More... | |
| struct | TinyArenaMark |
| A saved arena position. More... | |
Macros | |
| #define | TINYIMG_MAX_PIXELS 16000000u |
| Maximum number of pixels allowed in an image, whatever its channel count. Bounds decode time, which scales with pixels rather than bytes. | |
| #define | TINYIMG_MAX_IMAGE_BYTES 33554432u |
| Largest pixel buffer a single image may hold. | |
| #define | TINYIMG_ALIGNMENT 16u |
| Alignment every allocation is rounded up to. | |
| #define | TINYIMG_HEAP_MAX 67108864u |
| Largest heap the host build reserves, matching the wasm module's –max-memory. | |
| #define | TINYIMG_MAX_BLOBS 8 |
| How many blobs can be resident at once. | |
| #define | TINYIMG_BLOB_ID_MAX 32 |
| Longest blob id, including the terminator. | |
Typedefs | |
| typedef enum TinyBlobKind | TinyBlobKind |
| Kinds of data the library reads but does not ship. | |
Enumerations | |
| enum | TinyBlobKind { TINYIMG_BLOB_FONT = 0 , TINYIMG_BLOB_ICC = 1 , TINYIMG_BLOB_CASCADE = 2 } |
| Kinds of data the library reads but does not ship. More... | |
Functions | |
| void * | tiny_memcpy (void *dest, const void *src, size_t n) |
| Replicates the behavior of the standard memcpy function, copying n bytes from src to dest. | |
| void * | tiny_memset (void *s, int c, size_t n) |
| Replicates the behavior of the standard memset function, filling the first n bytes of the memory area pointed to by s with the constant byte c. | |
| void * | tiny_memmove (void *dest, const void *src, size_t n) |
| Replicates the behavior of the standard memmove function, copying n bytes from src to dest. Unlike memcpy, memmove is safe to use when the source and destination memory areas overlap. | |
| int | tiny_memcmp (const void *s1, const void *s2, size_t n) |
| Replicates the behavior of the standard memcmp function, comparing the first n bytes of the memory areas pointed to by s1 and s2. | |
| int | tiny_heap_init (void *memory, size_t size) |
| Installs a caller supplied block as the heap. | |
| void | tiny_heap_bootstrap (void) |
| Installs the platform's default heap if no heap exists yet. | |
| int | tiny_heap_stats (TinyHeapStats *stats) |
| Reads the current heap occupancy. | |
| void * | tiny_alloc (size_t size) |
| Allocates a block from the heap. | |
| void * | tiny_realloc (void *pointer, size_t size) |
| Resizes a block, moving it only when it cannot grow in place. | |
| void | tiny_free (void *pointer) |
| Returns a block to the heap, coalescing it with free neighbors. | |
| size_t | tiny_alloc_size (const void *pointer) |
| Usable size of a block, which may exceed what was asked for. | |
| void * | tiny_arena_alloc (size_t size, size_t alignment) |
| Allocates a block from the arena, aligned to the requested boundary. | |
| void | tiny_arena_mark (TinyArenaMark *mark) |
| Records the current arena position. | |
| void | tiny_arena_release (const TinyArenaMark *mark) |
| Rewinds the arena to a recorded position. | |
| void | tiny_arena_reset (void) |
| Releases every block the arena has handed out. | |
| size_t | tiny_arena_reserved (void) |
| Bytes the arena currently holds from the heap. | |
| int | tiny_blob_load (TinyBlobKind kind, const char *id, const uint8_t *data, size_t size) |
| Registers a blob under an id. | |
| const uint8_t * | tiny_blob_get (TinyBlobKind kind, const char *id, size_t *size) |
| Looks up a resident blob. | |
| const uint8_t * | tiny_blob_at (TinyBlobKind kind, uint32_t index, const char **id, size_t *size) |
| Walks the resident blobs of one kind. | |
| int | tiny_blob_free (TinyBlobKind kind, const char *id) |
| Releases one resident blob. | |
| void | tiny_blob_free_all (void) |
| Releases every resident blob. | |
Lightweight memory management implementatins in C.
| #define TINYIMG_ALIGNMENT 16u |
Alignment every allocation is rounded up to.
Sixteen bytes so a pixel buffer can be read with aligned SIMD128 loads.
| #define TINYIMG_MAX_IMAGE_BYTES 33554432u |
Largest pixel buffer a single image may hold.
The pixel cap alone cannot express the constraint that actually fails: an allocation is bytes, so a 15 megapixel RGBA image passes a 16 megapixel check and then dies in the allocator. Half the heap leaves room for the encoded source, a decoder's component planes and one scratch buffer.
Measured full-decode ceilings against the 64 MiB heap, which is what this number is set from: JPEG 4:2:0 13.81 Mpx, 4:2:2 12.28, 4:4:4 10.32, PNG RGB 10.97, PNG RGBA 8.56. Every one of those failed in the allocator before this cap existed, so the specific error was unreachable for all of them.
| #define TINYIMG_MAX_PIXELS 16000000u |
Maximum number of pixels allowed in an image, whatever its channel count. Bounds decode time, which scales with pixels rather than bytes.
A grayscale image is the only one that reaches this, because TINYIMG_MAX_IMAGE_BYTES binds first at every wider channel count.
| typedef enum TinyBlobKind TinyBlobKind |
Kinds of data the library reads but does not ship.
Anything large enough to dominate the module, or only needed by some callers, arrives at runtime instead of being linked in. The host either imports it as a wrangler Data module or fetches it from a bucket; the library only ever sees bytes already in linear memory.
| enum TinyBlobKind |
Kinds of data the library reads but does not ship.
Anything large enough to dominate the module, or only needed by some callers, arrives at runtime instead of being linked in. The host either imports it as a wrangler Data module or fetches it from a bucket; the library only ever sees bytes already in linear memory.
| Enumerator | |
|---|---|
| TINYIMG_BLOB_FONT | A TrueType, OpenType, PSF or BDF face. |
| TINYIMG_BLOB_ICC | An ICC color profile. |
| TINYIMG_BLOB_CASCADE | A packed detection cascade. |
| void * tiny_alloc | ( | size_t | size | ) |
Allocates a block from the heap.
First fit over an address ordered block list, so the cost is linear in the number of live blocks rather than constant. An image pipeline holds a handful of blocks at a time; a workload that holds thousands would want a size bucketed free list instead.
The returned block is aligned to TINYIMG_ALIGNMENT and its contents are undefined.
| size | Number of bytes to allocate. Zero returns NULL. |
| size_t tiny_alloc_size | ( | const void * | pointer | ) |
Usable size of a block, which may exceed what was asked for.
| pointer | The block. |
| void * tiny_arena_alloc | ( | size_t | size, |
| size_t | alignment ) |
Allocates a block from the arena, aligned to the requested boundary.
The arena never frees an individual block. It is reclaimed in bulk, either back to a saved position with tiny_arena_release or entirely with tiny_arena_reset. Use it for scratch that lives no longer than the call that asked for it.
Amortized O(1) time complexity. The arena takes chunks from the heap as it needs them, so an allocation never invalidates a pointer it handed out earlier.
| size | Number of bytes to allocate. |
| alignment | Required alignment in bytes. Must be a power of two; zero means TINYIMG_ALIGNMENT. |
| void tiny_arena_mark | ( | TinyArenaMark * | mark | ) |
Records the current arena position.
| mark | Receives the position. |
| void tiny_arena_release | ( | const TinyArenaMark * | mark | ) |
Rewinds the arena to a recorded position.
Any pointer handed out after the mark was taken is dangling afterwards.
| mark | A position from tiny_arena_mark. |
| size_t tiny_arena_reserved | ( | void | ) |
Bytes the arena currently holds from the heap.
| void tiny_arena_reset | ( | void | ) |
Releases every block the arena has handed out.
O(n) time complexity, where n is the number of chunks. Any pointer previously returned by tiny_arena_alloc is dangling afterwards.
| const uint8_t * tiny_blob_at | ( | TinyBlobKind | kind, |
| uint32_t | index, | ||
| const char ** | id, | ||
| size_t * | size ) |
Walks the resident blobs of one kind.
The way to act on every blob of a kind without knowing what any of them is called. Face detection needs it: a caller loads whichever cascades they have and the detector runs all of them, so nothing in the library names a blob.
The order is the slot order, which is not the load order once a blob has been freed and its slot reused.
| kind | What to walk. |
| index | Which one, from zero. |
| id | Receives the id it was loaded under. May be NULL. |
| size | Receives the byte length. May be NULL. |
| int tiny_blob_free | ( | TinyBlobKind | kind, |
| const char * | id ) |
Releases one resident blob.
| kind | What to release. |
| id | The id it was loaded under, or NULL for the first blob of that kind. |
| const uint8_t * tiny_blob_get | ( | TinyBlobKind | kind, |
| const char * | id, | ||
| size_t * | size ) |
Looks up a resident blob.
| kind | What to look for. |
| id | The id it was loaded under, or NULL for the first blob of that kind. |
| size | Receives the byte length. May be NULL. |
| int tiny_blob_load | ( | TinyBlobKind | kind, |
| const char * | id, | ||
| const uint8_t * | data, | ||
| size_t | size ) |
Registers a blob under an id.
The library takes ownership of data, which must have come from tiny_alloc, and releases it with tiny_blob_free or tiny_blob_free_all. Loading over an existing kind and id replaces it and frees what was there.
| kind | What the bytes are. |
| id | Name the caller will ask for it by. Truncated at TINYIMG_BLOB_ID_MAX. |
| data | The bytes, owned by the library from here on. |
| size | Number of bytes. |
| void tiny_free | ( | void * | pointer | ) |
Returns a block to the heap, coalescing it with free neighbors.
A NULL pointer, a pointer the heap never handed out, and a second free of the same pointer are all ignored rather than corrupting the block list.
| pointer | The block to free. |
| void tiny_heap_bootstrap | ( | void | ) |
Installs the platform's default heap if no heap exists yet.
On wasm the heap starts at __heap_base and grows through memory.grow up to the module's –max-memory. On a host build it is one reservation of TINYIMG_HEAP_MAX, which stays untouched address space until written to.
Idempotent, and called by every allocation, so nothing has to remember to initialize the library before using it.
| int tiny_heap_init | ( | void * | memory, |
| size_t | size ) |
Installs a caller supplied block as the heap.
The block is never grown, which is what makes it the right choice for a test that wants exhaustion to happen at a predictable size. A wasm module or a host process should call tiny_heap_bootstrap instead and let the heap grow.
Any pointer handed out by a previous heap is dangling afterwards.
| memory | Pointer to the memory block to be used for the heap. |
| size | Size of the memory block in bytes. |
| int tiny_heap_stats | ( | TinyHeapStats * | stats | ) |
Reads the current heap occupancy.
O(n) time complexity, where n is the number of blocks.
| stats | Receives the snapshot. |
| int tiny_memcmp | ( | const void * | s1, |
| const void * | s2, | ||
| size_t | n ) |
Replicates the behavior of the standard memcmp function, comparing the first n bytes of the memory areas pointed to by s1 and s2.
O(n) time complexity, where n is the number of bytes to compare.
| s1 | Pointer to the first memory area to be compared. |
| s2 | Pointer to the second memory area to be compared. |
| n | Number of bytes to compare. |
| void * tiny_memcpy | ( | void * | dest, |
| const void * | src, | ||
| size_t | n ) |
Replicates the behavior of the standard memcpy function, copying n bytes from src to dest.
O(n) time complexity, where n is the number of bytes to copy.
| dest | Destination buffer where the content is to be copied. |
| src | Source buffer from which the content is to be copied. |
| n | Number of bytes to copy from src to dest. |
| void * tiny_memmove | ( | void * | dest, |
| const void * | src, | ||
| size_t | n ) |
Replicates the behavior of the standard memmove function, copying n bytes from src to dest. Unlike memcpy, memmove is safe to use when the source and destination memory areas overlap.
O(n) time complexity, where n is the number of bytes to copy.
| dest | Destination buffer where the content is to be copied. |
| src | Source buffer from which the content is to be copied. |
| n | Number of bytes to copy from src to dest. |
| void * tiny_memset | ( | void * | s, |
| int | c, | ||
| size_t | n ) |
Replicates the behavior of the standard memset function, filling the first n bytes of the memory area pointed to by s with the constant byte c.
O(n) time complexity, where n is the number of bytes to set.
| s | Pointer to the memory area to be filled. |
| c | Constant byte value to fill the memory area with. |
| n | Number of bytes to fill in the memory area. |
| void * tiny_realloc | ( | void * | pointer, |
| size_t | size ) |
Resizes a block, moving it only when it cannot grow in place.
A block whose successor is free absorbs it rather than moving, which is what keeps an append heavy TinyWriter from copying on every doubling.
| pointer | Block to resize, or NULL to allocate. |
| size | New size in bytes. Zero frees the block and returns NULL. |