Skip to content

Commit b9483fa

Browse files
committed
Add Thresholds concept
1 parent 2a114d5 commit b9483fa

File tree

3 files changed

+44
-30
lines changed

3 files changed

+44
-30
lines changed

src/dither.nim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import dither/[ordered, types, palette, diffusion, quantizer, matrix]
2-
export ordered, types, palette, diffusion, quantizer, matrix
1+
import dither/[ordered, types, palette, diffusion, quantizer, algorithms]
2+
export ordered, types, palette, diffusion, quantizer, algorithms
33

44
proc dither*(input: InputImage, output: var OutputImage, algorithm: DitherModes, palette: Palette) =
55
## Applies the a dithering algorithm to `input` and writes it to `output`
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,38 @@ type
55
inset*: int
66
denominator*: int
77

8+
ThresholdMatrix*[N: static int] = array[N, array[N, int]]
9+
## Uses a matrix of integers as a threshold map for ordered dithering
10+
811
proc matrix[Rows: static int, Cols: static int](inset, denom: int; data: array[Rows, array[Cols, int]]): auto =
912
return DiffusionMatrix[Rows, Cols](data: data, inset: inset, denominator: denom)
1013

14+
const Bayer2x2*: ThresholdMatrix[2] = [
15+
[ 0, 2 ],
16+
[ 3, 1 ]
17+
]
18+
## Bayer 2x2 dithering
19+
20+
const Bayer4x4*: ThresholdMatrix[4] = [
21+
[ 1, 9, 3, 11 ],
22+
[ 13, 5, 15, 7 ],
23+
[ 4, 12, 2, 10 ],
24+
[ 16, 8, 14, 6 ]
25+
]
26+
## Bayer 4x4 dithering
27+
28+
const Bayer8x8*: ThresholdMatrix[8] = [
29+
[ 0, 32, 8, 40, 2, 34, 10, 42],
30+
[48, 16, 56, 24, 50, 18, 58, 26],
31+
[12, 44, 4, 36, 14, 46, 6, 38],
32+
[60, 28, 52, 20, 62, 30, 54, 22],
33+
[ 3, 35, 11, 43, 1, 33, 9, 41],
34+
[51, 19, 59, 27, 49, 17, 57, 25],
35+
[15, 47, 7, 39, 13, 45, 5, 37],
36+
[63, 31, 55, 23, 61, 29, 53, 21]
37+
]
38+
## Bayer 8x8 dithering
39+
1140
const FloydSteinberg* = matrix[2, 3](1, 16, [
1241
[ 0, 0, 7 ],
1342
[ 3, 5, 1 ]
@@ -41,6 +70,10 @@ const Burkes* = matrix[2, 5](2, 32, [
4170
])
4271
## Burkes dithering
4372

73+
proc maxThreshold*[N: static int](thresholds: ThresholdMatrix[N]): int = N * N
74+
75+
proc threshold*[N: static int](thresholds: ThresholdMatrix[N], x, y: int): int = thresholds[y mod N][x mod N]
76+
4477
proc rows*[Rows: static int, Cols: static int](matrix: DiffusionMatrix[Rows, Cols]): int =
4578
## The number of rows in this matrix
4679
return Rows

src/dither/ordered.nim

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,29 @@
11
import types
22

3-
type ThresholdMap*[N: static int] = array[N, array[N, int]]
3+
type
4+
Thresholds* = concept t
5+
## Describes the values to add that vary the colors at different offsets
6+
t.maxThreshold is int
7+
t.threshold(int, int) is int
48

5-
const Bayer2x2*: ThresholdMap[2] = [
6-
[ 0, 2 ],
7-
[ 3, 1 ]
8-
]
9-
10-
const Bayer4x4*: ThresholdMap[4] = [
11-
[ 1, 9, 3, 11 ],
12-
[ 13, 5, 15, 7 ],
13-
[ 4, 12, 2, 10 ],
14-
[ 16, 8, 14, 6 ]
15-
]
16-
17-
const Bayer8x8*: ThresholdMap[8] = [
18-
[ 0, 32, 8, 40, 2, 34, 10, 42],
19-
[48, 16, 56, 24, 50, 18, 58, 26],
20-
[12, 44, 4, 36, 14, 46, 6, 38],
21-
[60, 28, 52, 20, 62, 30, 54, 22],
22-
[ 3, 35, 11, 43, 1, 33, 9, 41],
23-
[51, 19, 59, 27, 49, 17, 57, 25],
24-
[15, 47, 7, 39, 13, 45, 5, 37],
25-
[63, 31, 55, 23, 61, 29, 53, 21]
26-
]
27-
28-
proc orderedDither*[N, P](
9+
proc orderedDither*[P](
2910
input: InputImage[P],
3011
output: var OutputImage[P],
3112
palette: Palette[P],
32-
thresholds: ThresholdMap[N]
13+
thresholds: Thresholds
3314
) =
3415
## Ordered dithering
3516
## * https://en.wikipedia.org/wiki/Ordered_dithering`
3617
## * https://bisqwit.iki.fi/story/howto/dither/jy/
3718

38-
let maxThresholdMap = N * N
19+
let maxThresholdMap = thresholds.maxThreshold
3920

4021
# The likely distance between colors in the palette
4122
let threshold = palette.approxMaxColorDistance
4223

4324
for y in 0..<input.height:
4425
for x in 0..<input.width:
45-
let factor = thresholds[y mod N][x mod N]
26+
let factor = thresholds.threshold(x, y)
4627
let actualPixel = input.getPixel(x, y)
4728
let adjustdPixel = actualPixel + (factor * threshold div maxThresholdMap)
4829
let final = palette.nearestColor(adjustdPixel)

0 commit comments

Comments
 (0)