|
|
|
|
.\" Automatically generated by Pandoc 2.13
|
|
|
|
|
.\"
|
|
|
|
|
.TH "DIDDER" "1" "April 30, 2021" "didder " "User Manual"
|
|
|
|
|
.hy
|
|
|
|
|
.SH NAME
|
|
|
|
|
.PP
|
|
|
|
|
didder - dither images
|
|
|
|
|
.SH SYNOPSIS
|
|
|
|
|
.PP
|
|
|
|
|
\f[B]didder\f[R] [global options] command [command options]
|
|
|
|
|
[arguments\&...]
|
|
|
|
|
.SH DESCRIPTION
|
|
|
|
|
.PP
|
|
|
|
|
Dither images with a variety of algorithms and processing options.
|
|
|
|
|
.PP
|
|
|
|
|
Mandatory global flags are \f[B]--palette\f[R], \f[B]--in\f[R], and
|
|
|
|
|
\f[B]--out\f[R], all others are optional.
|
|
|
|
|
Each command represents a dithering algorithm or set of algorithms to
|
|
|
|
|
apply to the input image(s).
|
|
|
|
|
.PP
|
|
|
|
|
The most important section in this manual is the \f[B]TIPS\f[R] one.
|
|
|
|
|
Make sure you check it out.
|
|
|
|
|
.PP
|
|
|
|
|
Homepage: <https://github.com/makeworld-the-better-one/didder>
|
|
|
|
|
.SH GLOBAL OPTIONS
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-i\f[R], \f[B]--in\f[R] \f[I]PATH\f[R]
|
|
|
|
|
Set the input file.
|
|
|
|
|
This flag can be used multiple times to dither multiple images with the
|
|
|
|
|
same palette and method.
|
|
|
|
|
A \f[I]PATH\f[R] of \[aq]\f[B]-\f[R]\[cq] stands for standard input.
|
|
|
|
|
.RS
|
|
|
|
|
.PP
|
|
|
|
|
The input file path can also be parsed as a glob.
|
|
|
|
|
This will only happen if the path contains an asterisk.
|
|
|
|
|
For example \f[B]-i \[aq]*.jpg\[cq]\f[R] will select all the .jpg files
|
|
|
|
|
in the current directory as input.
|
|
|
|
|
See this page for more info on glob pattern matching:
|
|
|
|
|
<https://golang.org/pkg/path/filepath/#Match>
|
|
|
|
|
.RE
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-o\f[R], \f[B]--out\f[R] \f[I]PATH\f[R]
|
|
|
|
|
Set the output file or directory.
|
|
|
|
|
A \f[I]PATH\f[R] of \[aq]\f[B]-\f[R]\[cq] stands for standard output.
|
|
|
|
|
.RS
|
|
|
|
|
.PP
|
|
|
|
|
If \f[I]PATH\f[R] is an existing directory, then for each image input,
|
|
|
|
|
an output file with the same name (but possibly different extension)
|
|
|
|
|
will be created in that directory.
|
|
|
|
|
.PP
|
|
|
|
|
If \f[I]PATH\f[R] is a file, that ends in .gif (or \f[B]--format
|
|
|
|
|
gif\f[R] is set) then multiple input files will be combined into an
|
|
|
|
|
animated GIF.
|
|
|
|
|
.RE
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-p\f[R], \f[B]--palette\f[R] \f[I]COLORS\f[R]
|
|
|
|
|
Set the color palette used for dithering.
|
|
|
|
|
Colors are entered as a single quoted argument, with each color
|
|
|
|
|
separated by a space.
|
|
|
|
|
Colors can be formatted as RGB tuples (comma separated), hex codes
|
|
|
|
|
(case-insensitive, with or without the `#'), a single number from 0-255
|
|
|
|
|
for grayscale, or a color name from the SVG 1.1 spec (aka the HTML or
|
|
|
|
|
W3C color names).
|
|
|
|
|
All colors are interpreted in the sRGB colorspace.
|
|
|
|
|
.RS
|
|
|
|
|
.PP
|
|
|
|
|
A list of all color names is available at
|
|
|
|
|
<https://www.w3.org/TR/SVG11/types.html#ColorKeywords>
|
|
|
|
|
.PP
|
|
|
|
|
Images are converted to grayscale automatically if the palette is
|
|
|
|
|
grayscale.
|
|
|
|
|
This produces more correct results.
|
|
|
|
|
.RE
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-r\f[R], \f[B]--recolor\f[R] \f[I]COLORS\f[R]
|
|
|
|
|
Set the color palette used for replacing the dithered color palette
|
|
|
|
|
after dithering.
|
|
|
|
|
The argument syntax is the same as \f[B]--palette\f[R].
|
|
|
|
|
.RS
|
|
|
|
|
.PP
|
|
|
|
|
The \f[B]--recolor\f[R] flag exists because when palettes that are
|
|
|
|
|
severely limited in terms of RGB spread are used, accurately
|
|
|
|
|
representing the image colors with the desired palette is impossible.
|
|
|
|
|
Instead of accuracy of color, the new goal is accuracy of luminance, or
|
|
|
|
|
even just accuracy of contrast.
|
|
|
|
|
For example, the original Nintendo Game Boy used a solely green palette:
|
|
|
|
|
<https://en.wikipedia.org/wiki/List_of_video_game_console_palettes#Game_Boy>.
|
|
|
|
|
By setting \f[B]--palette\f[R] to shades of gray and then
|
|
|
|
|
\f[B]--recolor\f[R]-ing to the desired shades of green, input images
|
|
|
|
|
will be converted to grayscale automatically and then dithered in one
|
|
|
|
|
dimension (gray), rather than trying to dither a color image (three
|
|
|
|
|
dimensions, RGB) into a one dimensional green palette.
|
|
|
|
|
This is similar to \[lq]hue shifting\[rq] or \[lq]colorizing\[rq] an
|
|
|
|
|
image in image editing software.
|
|
|
|
|
.PP
|
|
|
|
|
For these situations, \f[B]--recolor\f[R] should usually be a palette
|
|
|
|
|
made up of one hue, and \f[B]--palette\f[R] should be the grayscale
|
|
|
|
|
version of that palette.
|
|
|
|
|
The \f[B]--palette\f[R] could also be just equally spread grayscale
|
|
|
|
|
values, which would increase the contrast but make the luminance
|
|
|
|
|
inaccurate.
|
|
|
|
|
.PP
|
|
|
|
|
Recoloring can also be useful for increasing contrast on a strange
|
|
|
|
|
palette, like: \f[B]--palette \[aq]black white\[cq] --recolor
|
|
|
|
|
\[aq]indigo LimeGreen\[cq]\f[R].
|
|
|
|
|
Setting just \f[B]--palette \[aq]indigo LimeGreen\[cq]\f[R] would give
|
|
|
|
|
bad (low contrast) results because that palette is not that far apart in
|
|
|
|
|
RGB space.
|
|
|
|
|
These \[lq]bad results\[rq] are much more pronounced when the input
|
|
|
|
|
image is in color, because three dimensions are being reduced.
|
|
|
|
|
.RE
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-s\f[R], \f[B]--strength\f[R] \f[I]DECIMAL/PERCENT\f[R]
|
|
|
|
|
Set the strength of dithering.
|
|
|
|
|
This will affect every command except \f[B]random\f[R].
|
|
|
|
|
Decimal format is -1.0 to 1.0, and percentage format is -100% or 100%.
|
|
|
|
|
The range is not limited.
|
|
|
|
|
A zero value will be ignored.
|
|
|
|
|
Defaults to 100%, meaning that the dithering is applied at full
|
|
|
|
|
strength.
|
|
|
|
|
.RS
|
|
|
|
|
.PP
|
|
|
|
|
Reducing the strength is often visibly similar to reducing contrast.
|
|
|
|
|
With the \f[B]edm\f[R] command, \f[B]--strength\f[R] can be used to
|
|
|
|
|
reduce noise, when set to a value around 80%.
|
|
|
|
|
.PP
|
|
|
|
|
When using the \f[B]bayer\f[R] command with a grayscale palette, usually
|
|
|
|
|
100% is fine, but for 4x4 matrices or smaller, you may need to reduce
|
|
|
|
|
the strength.
|
|
|
|
|
For \f[B]bayer\f[R] (and by extension \f[B]odm\f[R]) color palette
|
|
|
|
|
images, several sites recommend 64% strength (written as 256/4).
|
|
|
|
|
This is often a good default for \f[B]bayer\f[R]/\f[B]odm\f[R] dithering
|
|
|
|
|
color images, as 100% will distort colors too much.
|
|
|
|
|
Do not use the default of 100% for Bayer dithering color images.
|
|
|
|
|
.RE
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-j\f[R], \f[B]--threads\f[R] \f[I]NUM\f[R]
|
|
|
|
|
Set the number of threads used.
|
|
|
|
|
By default a thread will be created for each CPU.
|
|
|
|
|
As dithering is a CPU-bound operation, going above this will not improve
|
|
|
|
|
performance.
|
|
|
|
|
This flag does not affect \f[B]edm\f[R], as error diffusion dithering
|
|
|
|
|
cannot be parallelized.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-g\f[R], \f[B]--grayscale\f[R]
|
|
|
|
|
Make input image(s) grayscale before dithering.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]--saturation\f[R] \f[I]DECIMAL/PERCENT\f[R]
|
|
|
|
|
Change input image(s) saturation before dithering.
|
|
|
|
|
Decimal range is -1.0 to 1.0, percentage range is -100% or 100%.
|
|
|
|
|
Values that exceed the range will be rounded down.
|
|
|
|
|
-1.0 or -100% saturation is equivalent to \f[B]--grayscale\f[R].
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]--brightness\f[R] \f[I]DECIMAL/PERCENT\f[R]
|
|
|
|
|
Change input image(s) saturation before dithering.
|
|
|
|
|
Decimal range is -1.0 to 1.0, percentage range is -100% or 100%.
|
|
|
|
|
Values that exceed the range will be rounded down.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]--contrast\f[R] \f[I]DECIMAL/PERCENT\f[R]
|
|
|
|
|
Change input image(s) saturation before dithering.
|
|
|
|
|
Decimal range is -1.0 to 1.0, percentage range is -100% or 100%.
|
|
|
|
|
Values that exceed the range will be rounded down.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]--no-exif-rotation\f[R]
|
|
|
|
|
Disable using the EXIF rotation flag in image metadata to rotate the
|
|
|
|
|
image before processing.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-f\f[R], \f[B]--format\f[R] \f[I]FORMAT\f[R]
|
|
|
|
|
Set the output file format.
|
|
|
|
|
Valid options are \[aq]png\[cq] and \[aq]gif\[cq].
|
|
|
|
|
It will auto detect from filename when possible, so usually this does
|
|
|
|
|
not need to be set.
|
|
|
|
|
If \f[B]-o\f[R] is \[aq]\f[B]-\f[R]\[cq] or a directory, then PNG files
|
|
|
|
|
will be outputted by default.
|
|
|
|
|
So this flag can be used to force GIF output instead.
|
|
|
|
|
If your output file has an extension that is not .png or .gif the format
|
|
|
|
|
will need to be specified.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]--no-overwrite\f[R]
|
|
|
|
|
Setting this flag means the program will stop before overwriting an
|
|
|
|
|
existing file.
|
|
|
|
|
Any files written before that one was encountered will stay in place.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-c\f[R], \f[B]--compression\f[R] \f[I]TYPE\f[R]
|
|
|
|
|
Set the type of PNG compression.
|
|
|
|
|
Options are \[aq]default\[cq], \[aq]no\[cq], \[aq]speed\[cq], and
|
|
|
|
|
\[aq]size\[cq].
|
|
|
|
|
This flag is ignored for non-PNG output.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]--fps\f[R] \f[I]DECIMAL\f[R]
|
|
|
|
|
Set frames per second for animated GIF output.
|
|
|
|
|
Note that not all FPS values can be represented by the GIF format, and
|
|
|
|
|
so the closest possible one will be chosen.
|
|
|
|
|
This flag has no default, and is required when animated GIFs are being
|
|
|
|
|
outputted.
|
|
|
|
|
This flag is ignored for non animated GIF output.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-l\f[R], \f[B]--loop\f[R] \f[I]NUM\f[R]
|
|
|
|
|
Set the number of times animated GIF output should loop.
|
|
|
|
|
0 is the default, and means infinite looping.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-x\f[R], \f[B]--width\f[R] \f[I]NUM\f[R]
|
|
|
|
|
Set the width the input image(s) will be resized to, before dithering.
|
|
|
|
|
Aspect ratio will be maintained if \f[B]--height\f[R] is not specified
|
|
|
|
|
as well.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-y\f[R], \f[B]--height\f[R] \f[I]NUM\f[R]
|
|
|
|
|
Set the height the input image(s) will be resized to, before dithering.
|
|
|
|
|
Aspect ratio will be maintained if \f[B]--width\f[R] is not specified as
|
|
|
|
|
well.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-u\f[R], \f[B]--upscale\f[R] \f[I]NUM\f[R]
|
|
|
|
|
Scale image up after dithering.
|
|
|
|
|
So \[aq]2\[cq] will make the output two times as big as the input (after
|
|
|
|
|
\f[B]-x\f[R] and/or \f[B]-y\f[R]).
|
|
|
|
|
Only integers are allowed, as scaling up by a non-integer amount would
|
|
|
|
|
distort the dithering pattern and introduce artifacts.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-v\f[R], \f[B]--version\f[R]
|
|
|
|
|
Get version information.
|
|
|
|
|
.SH COMMANDS
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]random\f[R]
|
|
|
|
|
- grayscale and RGB random dithering
|
|
|
|
|
.RS
|
|
|
|
|
.PP
|
|
|
|
|
Accepts two arguments (min and max) for RGB or grayscale, or six
|
|
|
|
|
(min/max for each channel) to control each RGB channel.
|
|
|
|
|
Arguments can be separated by commas or spaces.
|
|
|
|
|
.PP
|
|
|
|
|
-0.5,0.5 is a good default.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-s\f[R], \f[B]--seed\f[R] \f[I]DECIMAL\f[R]
|
|
|
|
|
Set the seed for randomization.
|
|
|
|
|
This will also only use one thread, to keep output deterministic.
|
|
|
|
|
By default a different seed is chosen each time.
|
|
|
|
|
.RE
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]bayer\f[R]
|
|
|
|
|
- Bayer matrix ordered dithering
|
|
|
|
|
.RS
|
|
|
|
|
.PP
|
|
|
|
|
Requires two arguments, for the X and Y dimension of the matrix.
|
|
|
|
|
They can be separated by a space, comma, or \[aq]x\[cq].
|
|
|
|
|
Both arguments must be a power of two, with the exception of: 3x5, 5x3,
|
|
|
|
|
and 3x3.
|
|
|
|
|
.RE
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]odm\f[R]
|
|
|
|
|
- Ordered Dither Matrix
|
|
|
|
|
.RS
|
|
|
|
|
.PP
|
|
|
|
|
Select or provide an ordered dithering matrix.
|
|
|
|
|
This only takes one argument, but there a few types available:
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
A preprogrammed matrix name
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
Inline JSON of a custom matrix
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
Or a path to JSON for your custom matrix.
|
|
|
|
|
\[aq]\f[B]-\f[R]\[cq] means standard input.
|
|
|
|
|
.PP
|
|
|
|
|
Here are all the built-in ordered dithering matrices.
|
|
|
|
|
You can find details on these matrices here:
|
|
|
|
|
<https://github.com/makeworld-the-better-one/dither/blob/v2.0.0/ordered_ditherers.go>
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDot4x4
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDotDiagonal8x8
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
Vertical5x3
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
Horizontal3x5
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDotDiagonal6x6
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDotDiagonal8x8_2
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDotDiagonal16x16
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDot6x6
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDotSpiral5x5
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDotHorizontalLine
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDotVerticalLine
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDot8x8
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDot6x6_2
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDot6x6_3
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
ClusteredDotDiagonal8x8_3
|
|
|
|
|
.PP
|
|
|
|
|
Their names are case-insensitive, and hyphens and underscores are
|
|
|
|
|
treated the same.
|
|
|
|
|
.PP
|
|
|
|
|
The JSON format (whether inline or in a file) looks like the below.
|
|
|
|
|
The matrix must be \[lq]rectangular\[rq], meaning each array must have
|
|
|
|
|
the same length.
|
|
|
|
|
More information how to use a custom matrix can be found here:
|
|
|
|
|
<https://pkg.go.dev/github.com/makeworld-the-better-one/dither/v2#OrderedDitherMatrix>
|
|
|
|
|
.RE
|
|
|
|
|
.IP
|
|
|
|
|
.nf
|
|
|
|
|
\f[C]
|
|
|
|
|
{
|
|
|
|
|
\[dq]matrix\[dq]: [
|
|
|
|
|
[12, 5, 6, 13],
|
|
|
|
|
[4, 0, 1, 7],
|
|
|
|
|
[11, 3, 2, 8],
|
|
|
|
|
[15, 10, 9, 14]
|
|
|
|
|
],
|
|
|
|
|
\[dq]max\[dq]: 16
|
|
|
|
|
}
|
|
|
|
|
\f[R]
|
|
|
|
|
.fi
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]edm\f[R]
|
|
|
|
|
- Error Diffusion Matrix
|
|
|
|
|
.RS
|
|
|
|
|
.PP
|
|
|
|
|
Select or provide an error diffusion matrix.
|
|
|
|
|
This only takes one argument, but there a few types available:
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
A preprogrammed matrix name
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
Inline JSON of a custom matrix
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
Or a path to JSON for your custom matrix.
|
|
|
|
|
\[aq]\f[B]-\f[R]\[cq] means stdin.
|
|
|
|
|
.PP
|
|
|
|
|
Here are all the built-in error diffusion matrices.
|
|
|
|
|
You can find details on these matrices here:
|
|
|
|
|
<https://github.com/makeworld-the-better-one/dither/blob/v2.0.0/error_diffusers.go>
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
Simple2D
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
FloydSteinberg
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
FalseFloydSteinberg
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
JarvisJudiceNinke
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
Atkinson
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
Stucki
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
Burkes
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
Sierra (or Sierra3)
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
TwoRowSierra (or Sierra2)
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
SierraLite (or Sierra2_4A)
|
|
|
|
|
.PD 0
|
|
|
|
|
.P
|
|
|
|
|
.PD
|
|
|
|
|
.IP \[bu] 2
|
|
|
|
|
StevenPigeon
|
|
|
|
|
.PP
|
|
|
|
|
Their names are case-insensitive, and hyphens and underscores are
|
|
|
|
|
treated the same.
|
|
|
|
|
.PP
|
|
|
|
|
The JSON format (whether inline or in a file) for a custom matrix is
|
|
|
|
|
very simple, just a 2D array.
|
|
|
|
|
The matrix must be \[lq]rectangular\[rq], meaning each array must have
|
|
|
|
|
the same length.
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]-s\f[R], \f[B]--serpentine\f[R]
|
|
|
|
|
Enable serpentine dithering, which \[lq]snakes\[rq] back and forth when
|
|
|
|
|
moving down the image, instead of going left-to-right each time.
|
|
|
|
|
This can reduce artifacts or patterns in the noise.
|
|
|
|
|
.RE
|
|
|
|
|
.SH TIPS
|
|
|
|
|
.PP
|
|
|
|
|
Read about \f[B]--strength\f[R] if you haven\[cq]t already.
|
|
|
|
|
.PP
|
|
|
|
|
Read about \f[B]--recolor\f[R] if you haven\[cq]t already.
|
|
|
|
|
.PP
|
|
|
|
|
It\[cq]s easy to mess up a dithered image by scaling it manually.
|
|
|
|
|
It\[cq]s best to scale the image to the size you want before dithering
|
|
|
|
|
(externally, or with \f[B]--width\f[R] and/or \f[B]--height\f[R]), and
|
|
|
|
|
then leave it.
|
|
|
|
|
.PP
|
|
|
|
|
If you need to scale it up afterward, use \f[B]--upscale\f[R], rather
|
|
|
|
|
than another tool.
|
|
|
|
|
This will prevent image artifacts or blurring.
|
|
|
|
|
.PP
|
|
|
|
|
Be wary of environments where you can\[cq]t make sure an image will be
|
|
|
|
|
displayed at 100% size, pixel for pixel.
|
|
|
|
|
Make sure nearest-neighbor scaling is being used at least.
|
|
|
|
|
.PP
|
|
|
|
|
Dithered images must only be encoded in a lossless image format.
|
|
|
|
|
This is why the tool only outputs PNG or GIF.
|
|
|
|
|
.PP
|
|
|
|
|
To increase the dithering artifacts for aesthetic effect, you can
|
|
|
|
|
downscale the image before dithering and upscale after.
|
|
|
|
|
Like if the image is 1000 pixels tall, your command can look like
|
|
|
|
|
\f[B]didder \[en]height 500 \[en]upscale 2 [\&...]\f[R].
|
|
|
|
|
Depending on the input image size and what final size you want, you can
|
|
|
|
|
of course just upscale as well.
|
|
|
|
|
.PP
|
|
|
|
|
If your palette (original or recolor) is low-spread, meaning it
|
|
|
|
|
doesn\[cq]t span much of the available shades of a single hue or the
|
|
|
|
|
entire RGB space, you can use flags like \f[B]--brightness\f[R],
|
|
|
|
|
\f[B]--contrast\f[R], and \f[B]--saturation\f[R] to improve the way
|
|
|
|
|
dithered images turn out.
|
|
|
|
|
For example, if your palette is dark, you can turn up the brightness.
|
|
|
|
|
.SH EXAMPLES
|
|
|
|
|
.TP
|
|
|
|
|
\f[B]didder \[en]palette `black white' -i input.jpg -o test.png bayer 16x16\f[R]
|
|
|
|
|
This command dithers \f[C]input.jpg\f[R] to just use black and white
|
|
|
|
|
(implicitly converting to grayscale first), using a 16x16 Bayer matrix.
|
|
|
|
|
The result is written to \f[C]test.png\f[R].
|
|
|
|
|
.PP
|
|
|
|
|
TODO
|
|
|
|
|
.SH REPORTING BUGS
|
|
|
|
|
.PP
|
|
|
|
|
Any bugs can be reported by creating an issue on GitHub:
|
|
|
|
|
<https://github.com/makeworld-the-better-one/didder>
|