59 lines
2.9 KiB
C
59 lines
2.9 KiB
C
#ifndef DitherPixels_h
|
||
#define DitherPixels_h
|
||
#include <stdint.h>
|
||
#include <stddef.h>
|
||
|
||
// The dither styles, in the order the Filter panel lists them.
|
||
enum {
|
||
DITHER_ATKINSON, DITHER_FLOYD_STEINBERG,
|
||
DITHER_BAYER_2, DITHER_BAYER_4, DITHER_BAYER_8,
|
||
DITHER_DOTS, DITHER_LINES, DITHER_DIAMONDS,
|
||
DITHER_PATTERNS, DITHER_GLYPHS, DITHER_SCANLINES
|
||
};
|
||
|
||
typedef struct {
|
||
int style;
|
||
// Tones per channel for diffusion and ordered styles, 2–8. Two is pure 1-bit.
|
||
int levels;
|
||
// How much of each pixel's error diffusion passes on, 0–1.
|
||
float diffusion;
|
||
// −1…1: darker (more ink) or lighter, and flatter or punchier, before dithering.
|
||
float density;
|
||
float contrast;
|
||
// Halftone and glyph cells, in pixels (scanlines: the distance between lines), and the halftone screen's angle in
|
||
// radians.
|
||
int cell;
|
||
float angle;
|
||
// Halftone dots, patterns and glyphs mark the light tones on the dark color instead of the dark on the light.
|
||
int lightOnDark;
|
||
// 0: the result is made of `dark` and `light` (straight sRGB). 1: it keeps the image's own colors.
|
||
int originalColors;
|
||
uint8_t dark[3];
|
||
uint8_t light[3];
|
||
// Glyphs: `glyphCount` coverage maps of `glyphWidth` × `glyphHeight` bytes (255 is fully inked), from least
|
||
// inked to most, with each map's mean coverage (0–1) in `glyphCoverage`. The image is laid out in cells that size,
|
||
// like lines of monospaced text.
|
||
int glyphWidth;
|
||
int glyphHeight;
|
||
const uint8_t *glyphs;
|
||
const float *glyphCoverage;
|
||
int glyphCount;
|
||
// Scanlines: how far each line breaks into round dots (0–1), and how many pixels its wobble pushes it sideways.
|
||
float dots;
|
||
float wobble;
|
||
} DitherParams;
|
||
|
||
// Dithers premultiplied RGBA pixels (4 bytes per pixel, `stride` bytes per row) in place. Alpha is kept and fully
|
||
// transparent pixels are left alone. Returns 0 if working memory couldn't be had.
|
||
int dither_apply(uint8_t *rgba, size_t width, size_t height, size_t stride, const DitherParams *params);
|
||
// Turns each `block` × `block` square of premultiplied RGBA pixels into a round dot in its own color on `gap` (straight
|
||
// sRGB), like the lit pixels of a dot-matrix screen. The dot's edge is smoothed and alpha is kept.
|
||
void dither_dots(uint8_t *rgba, size_t width, size_t height, size_t stride, int block, const uint8_t *gap);
|
||
// Adds `glow` (premultiplied RGBA, same layout) over the pixels at `amount`, never past their own alpha.
|
||
void dither_glow(uint8_t *rgba, const uint8_t *glow, size_t width, size_t height, size_t stride, float amount);
|
||
// Rounds 16-bit premultiplied RGBA (`width` × `height`, tightly packed) to 8 bits into `rgba` (`stride` bytes per
|
||
// row), adding noise of about one 8-bit step first so smooth gradients don't come out in steps. The noise is fixed per
|
||
// pixel, so the same input always gives the same output.
|
||
void dither_quantize16(const uint16_t *wide, uint8_t *rgba, size_t width, size_t height, size_t stride);
|
||
#endif
|