Skip to content

Commit e4fc33e

Browse files
committed
IntQuantizer and BlackAndWhiteIntPalette
1 parent 48c910c commit e4fc33e

File tree

6 files changed

+41
-23
lines changed

6 files changed

+41
-23
lines changed

src/dither/palette.nim

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ type
55
## A palette made of explicit colors
66
colors: seq[ColorRGBX]
77

8+
BlackAndWhiteIntPaletteObj = object
9+
10+
const BlackAndWhiteIntPalette* = BlackAndWhiteIntPaletteObj()
11+
## A palette that uses integers to represent shades of gray, but the output palette is only black and white
12+
813
proc palette*(colors: varargs[ColorRGBX]): FixedPalette =
14+
## Creates a palette from the given set of colors
915
FixedPalette(colors: colors.toSeq)
1016

1117
proc nearestColor*(palette: FixedPalette, color: ColorRGBX): ColorRGBX =
@@ -37,3 +43,10 @@ proc `+`*(color: ColorRGBX, scalar: int): ColorRGBX =
3743
## Add a scalar value to a color
3844
result = rgbx(color.r + scalar, color.g + scalar, color.b + scalar, color.a)
3945

46+
proc nearestColor*(palette: BlackAndWhiteIntPaletteObj, color: int): int =
47+
## Returns black or white, whichever is closest
48+
return if color > 128: 255 else: 0
49+
50+
proc approxMaxColorDistance*(palette: BlackAndWhiteIntPaletteObj): int = 128
51+
## Returns the maximum distance between colors
52+

src/dither/quantizer.nim

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ type
66
ColorQuantizeError = object
77
red, green, blue: int
88

9+
IntQuantizerObj = object
10+
911
const ColorQuantizer* = ColorQuantizeObj()
12+
## Quantizer that uses chroma to support RGB values
13+
14+
const IntQuantizer* = IntQuantizerObj()
15+
## Quantizer that uses integers to represent a gray scale
1016

1117
proc quantizeError*(q: ColorQuantizeObj; a, b: ColorRGBX): ColorQuantizeError =
1218
return ColorQuantizeError(red: a.r.int - b.r.int, green: a.g.int - b.g.int, blue: a.b.int - b.b.int)
@@ -24,3 +30,5 @@ proc `+`(a: uint8, b: SomeInteger): uint8 = clamp(a.int + b.int, 0, 255).uint8
2430

2531
proc `+`*(color: ColorRGBX, error: ColorQuantizeError): ColorRGBX =
2632
return rgbx(color.r + error.red, color.g + error.green, color.b + error.blue, color.a)
33+
34+
proc quantizeError*(q: IntQuantizerObj, a, b: int): int = a - b

tests/stubs.nim

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ type
77
OutputImage*[N: static int, T] = object
88
pixels: seq[array[N, T]]
99

10-
BlackAndWhite* = object
11-
12-
IntQuantizer* = object
13-
1410
proc newInput*[W: static int, T](pixels: varargs[array[W, T]]): auto = TestInput[W, T](pixels: pixels.toSeq)
1511

1612
proc width*[W: static int, T](image: TestInput[W, T]): int = W
@@ -19,13 +15,6 @@ proc height*[W: static int, T](image: TestInput[W, T]): int = image.pixels.len
1915

2016
proc getPixel*[W: static int, T](image: TestInput[W, T]; x, y: int): T = image.pixels[y][x]
2117

22-
proc nearestColor*(palette: BlackAndWhite, color: int): int =
23-
return if color > 128: 255 else: 0
24-
25-
proc quantError*(a, b: int): int = a - b
26-
27-
proc approxMaxColorDistance*(palette: BlackAndWhite): int = 128
28-
2918
proc newOutput*[N: static int, T](): auto = OutputImage[N, T](pixels: newSeq[array[N, T]]())
3019

3120
proc setPixel*[N: static int, T](img: var OutputImage[N, T]; x, y: int, color: T) =
@@ -41,6 +30,4 @@ proc `==`*[N: static int, M: static int, T](img: var OutputImage[N, T]; values:
4130
proc intArray*[N: static int](values: Slice[int]): array[N, int] =
4231
let increment = (values.b - values.a) / (N - 1)
4332
for i in 0..<N:
44-
result[i] = round(increment * i.float).toInt
45-
46-
proc quantizeError*(q: IntQuantizer, a, b: int): int = a - b
33+
result[i] = round(increment * i.float).toInt

tests/t_diffusion.nim

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ suite "Error diffusion dithering":
88
test "Can perform Floyd Steinberg dithering":
99
var output = newOutput[20, int]()
1010

11-
errorDiffusionDither(img, output, BlackAndWhite(), IntQuantizer(), FloydSteinberg)
11+
errorDiffusionDither(img, output, BlackAndWhiteIntPalette, IntQuantizer, FloydSteinberg)
1212

1313
check(output == [
1414
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 255, 0, 255, 0, 255],
@@ -26,7 +26,7 @@ suite "Error diffusion dithering":
2626
test "Can perform Jarvis, Judice, and Ninke dithering":
2727
var output = newOutput[20, int]()
2828

29-
errorDiffusionDither(img, output, BlackAndWhite(), IntQuantizer(), JarvisJudiceNinke)
29+
errorDiffusionDither(img, output, BlackAndWhiteIntPalette, IntQuantizer, JarvisJudiceNinke)
3030

3131
check(output == [
3232
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 255, 0],
@@ -44,7 +44,7 @@ suite "Error diffusion dithering":
4444
test "Can perform Stucki dithering":
4545
var output = newOutput[20, int]()
4646

47-
errorDiffusionDither(img, output, BlackAndWhite(), IntQuantizer(), Stucki)
47+
errorDiffusionDither(img, output, BlackAndWhiteIntPalette, IntQuantizer, Stucki)
4848

4949
check(output == [
5050
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 255, 0],
@@ -62,7 +62,7 @@ suite "Error diffusion dithering":
6262
test "Can perform Atkinson dithering":
6363
var output = newOutput[20, int]()
6464

65-
errorDiffusionDither(img, output, BlackAndWhite(), IntQuantizer(), Atkinson)
65+
errorDiffusionDither(img, output, BlackAndWhiteIntPalette, IntQuantizer, Atkinson)
6666

6767
check(output == [
6868
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 255],
@@ -80,7 +80,7 @@ suite "Error diffusion dithering":
8080
test "Can perform Burkes dithering":
8181
var output = newOutput[20, int]()
8282

83-
errorDiffusionDither(img, output, BlackAndWhite(), IntQuantizer(), Burkes)
83+
errorDiffusionDither(img, output, BlackAndWhiteIntPalette, IntQuantizer, Burkes)
8484

8585
check(output == [
8686
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 255, 0, 255, 0],

tests/t_ordered.nim

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ suite "Ordered dithering":
1212
intArray[10](0..255),
1313
)
1414

15-
img.orderedDither(output, BlackAndWhite(), Bayer2x2)
15+
img.orderedDither(output, BlackAndWhiteIntPalette, Bayer2x2)
1616

1717
check(output == [
1818
[ 0, 0, 0, 255, 0, 255, 255, 255, 255, 255],
@@ -33,7 +33,7 @@ suite "Ordered dithering":
3333
intArray[20](0..255),
3434
)
3535

36-
img.orderedDither(output, BlackAndWhite(), Bayer4x4)
36+
img.orderedDither(output, BlackAndWhiteIntPalette, Bayer4x4)
3737

3838
check(output == [
3939
[ 0, 0, 0, 0, 0, 255, 0, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
@@ -52,7 +52,7 @@ suite "Ordered dithering":
5252
intArray[10](0..100).toSeq.mapIt(intArray[20](it..(it + 128)))
5353
)
5454

55-
img.orderedDither(output, BlackAndWhite(), Bayer8x8)
55+
img.orderedDither(output, BlackAndWhiteIntPalette, Bayer8x8)
5656

5757
check(output == [
5858
[ 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 255, 0, 255, 0, 255, 255, 255],

tests/t_palette.nim

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,14 @@ suite "Fixed palette":
1313
check(palette.nearestColor(rgbx(100, 100, 100, 200)) == gray)
1414

1515
test "Can estimate the max distance between colors":
16-
check(palette.approxMaxColorDistance == 128)
16+
check(palette.approxMaxColorDistance == 128)
17+
18+
suite "Black and white int pallete":
19+
20+
test "Can return the nearest color":
21+
check(BlackAndWhiteIntPalette.nearestColor(10) == 0)
22+
check(BlackAndWhiteIntPalette.nearestColor(128) == 0)
23+
check(BlackAndWhiteIntPalette.nearestColor(200) == 255)
24+
25+
test "Can estimate the max distance between colors":
26+
check(BlackAndWhiteIntPalette.approxMaxColorDistance == 128)

0 commit comments

Comments
 (0)