Skip to content

Commit 5bb8a03

Browse files
committed
Initial commit
First set of files
1 parent 7c51c04 commit 5bb8a03

11 files changed

+700
-0
lines changed

Diff for: AtkinsonDithering.cs

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
This file implements error pushing of dithering via Atkinson kernel.
3+
4+
This is free and unencumbered software released into the public domain.
5+
*/
6+
7+
class AtkinsonDithering : DitheringBase
8+
{
9+
public AtkinsonDithering(FindColor colorfunc) : base(colorfunc)
10+
{
11+
this.methodLongName = "Atkinson";
12+
this.fileNameAddition = "_ATK";
13+
}
14+
15+
override protected void PushError(int x, int y, short[] quantError)
16+
{
17+
// Push error
18+
// X 1/8 1/8
19+
// 1/8 1/8 1/8
20+
// 1/8
21+
22+
int xMinusOne = x - 1;
23+
int xPlusOne = x + 1;
24+
int xPlusTwo = x + 2;
25+
int yPlusOne = y + 1;
26+
int yPlusTwo = y + 2;
27+
28+
float multiplier = 1.0f / 8.0f; // Atkinson Dithering has same multiplier for every item
29+
30+
// Current row
31+
int currentRow = y;
32+
if (this.IsValidCoordinate(xPlusOne, currentRow))
33+
{
34+
this.ModifyImageWithErrorAndMultiplier(xPlusOne, currentRow, quantError, multiplier);
35+
}
36+
37+
if (this.IsValidCoordinate(xPlusTwo, currentRow))
38+
{
39+
this.ModifyImageWithErrorAndMultiplier(xPlusTwo, currentRow, quantError, multiplier);
40+
}
41+
42+
// Next row
43+
currentRow = yPlusOne;
44+
if (this.IsValidCoordinate(xMinusOne, currentRow))
45+
{
46+
this.ModifyImageWithErrorAndMultiplier(xMinusOne, currentRow, quantError, multiplier);
47+
}
48+
49+
if (this.IsValidCoordinate(x, currentRow))
50+
{
51+
this.ModifyImageWithErrorAndMultiplier(x, currentRow, quantError, multiplier);
52+
}
53+
54+
if (this.IsValidCoordinate(xPlusOne, currentRow))
55+
{
56+
this.ModifyImageWithErrorAndMultiplier(xPlusOne, currentRow, quantError, multiplier);
57+
}
58+
59+
// Next row
60+
currentRow = yPlusTwo;
61+
if (this.IsValidCoordinate(x, currentRow))
62+
{
63+
this.ModifyImageWithErrorAndMultiplier(x, currentRow, quantError, multiplier);
64+
}
65+
}
66+
}
67+

Diff for: BurkesDithering.cs

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
This file implements error pushing of dithering via (Daniel) Burkes kernel.
3+
4+
This is free and unencumbered software released into the public domain.
5+
*/
6+
7+
class BurkesDithering : DitheringBase
8+
{
9+
public BurkesDithering(FindColor colorfunc) : base(colorfunc)
10+
{
11+
this.methodLongName = "Burkes";
12+
this.fileNameAddition = "_BUR";
13+
}
14+
15+
override protected void PushError(int x, int y, short[] quantError)
16+
{
17+
// Push error
18+
// X 8/32 4/32
19+
// 2/32 4/32 8/32 4/32 2/32
20+
21+
int xMinusOne = x - 1;
22+
int xMinusTwo = x - 2;
23+
int xPlusOne = x + 1;
24+
int xPlusTwo = x + 2;
25+
int yPlusOne = y + 1;
26+
27+
// Current row
28+
int currentRow = y;
29+
if (this.IsValidCoordinate(xPlusOne, currentRow))
30+
{
31+
this.ModifyImageWithErrorAndMultiplier(xPlusOne, currentRow, quantError, 8.0f / 32.0f);
32+
}
33+
34+
if (this.IsValidCoordinate(xPlusTwo, currentRow))
35+
{
36+
this.ModifyImageWithErrorAndMultiplier(xPlusTwo, currentRow, quantError, 4.0f / 32.0f);
37+
}
38+
39+
// Next row
40+
currentRow = yPlusOne;
41+
if (this.IsValidCoordinate(xMinusTwo, currentRow))
42+
{
43+
this.ModifyImageWithErrorAndMultiplier(xMinusTwo, currentRow, quantError, 2.0f / 32.0f);
44+
}
45+
46+
if (this.IsValidCoordinate(xMinusOne, currentRow))
47+
{
48+
this.ModifyImageWithErrorAndMultiplier(xMinusOne, currentRow, quantError, 4.0f / 32.0f);
49+
}
50+
51+
if (this.IsValidCoordinate(x, currentRow))
52+
{
53+
this.ModifyImageWithErrorAndMultiplier(x, currentRow, quantError, 8.0f / 32.0f);
54+
}
55+
56+
if (this.IsValidCoordinate(xPlusOne, currentRow))
57+
{
58+
this.ModifyImageWithErrorAndMultiplier(xPlusOne, currentRow, quantError, 4.0f / 32.0f);
59+
}
60+
61+
if (this.IsValidCoordinate(xPlusTwo, currentRow))
62+
{
63+
this.ModifyImageWithErrorAndMultiplier(xPlusTwo, currentRow, quantError, 2.0f / 32.0f);
64+
}
65+
}
66+
}
67+

Diff for: DitheringBase.cs

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
using UnityEngine;
2+
using System.Collections;
3+
4+
// This Delegate is used to find best suitable color from limited set of colors
5+
public delegate Color32 FindColor(Color32 original);
6+
7+
public abstract class DitheringBase {
8+
9+
protected int width;
10+
protected int height;
11+
12+
protected FindColor colorFunction = null;
13+
14+
protected string methodLongName = "";
15+
protected string fileNameAddition = "";
16+
17+
private Color32[] pixels = null;
18+
19+
public DitheringBase(FindColor colorfunc)
20+
{
21+
this.colorFunction = colorfunc;
22+
}
23+
24+
//
25+
public Texture2D DoDithering(Texture2D input)
26+
{
27+
this.width = input.width;
28+
this.height = input.height;
29+
30+
// Copy all pixels of input Texture2D to new array, which we are going to edit
31+
this.pixels = input.GetPixels32();
32+
33+
Color32 originalPixel = Color.white; // Default value isn't used
34+
Color32 newPixel = Color.white; // Default value isn't used
35+
short[] quantError = null; // Default values aren't used
36+
37+
for (int y = 0; y < this.height; y++)
38+
{
39+
for (int x = 0; x < this.width; x++)
40+
{
41+
originalPixel = this.pixels[GetIndexWith(x, y)];
42+
newPixel = this.colorFunction(originalPixel);
43+
44+
this.pixels[GetIndexWith(x, y)] = newPixel;
45+
46+
quantError = GetQuantError(originalPixel, newPixel);
47+
this.PushError(x, y, quantError);
48+
}
49+
}
50+
51+
// Create the texture we are going to return from pixels array
52+
Texture2D returnTexture = new Texture2D(width, height, TextureFormat.ARGB32, false);
53+
returnTexture.SetPixels32(this.pixels);
54+
returnTexture.Apply();
55+
56+
return returnTexture;
57+
}
58+
59+
// Implement this for every dithering method
60+
protected abstract void PushError(int x, int y, short[] quantError);
61+
62+
protected bool IsValidCoordinate(int x, int y)
63+
{
64+
return (0 <= x && x < this.width && 0 <= y && y < this.height);
65+
}
66+
67+
protected int GetIndexWith(int x, int y)
68+
{
69+
return y * this.width + x;
70+
}
71+
72+
public string GetMethodName()
73+
{
74+
return this.methodLongName;
75+
}
76+
77+
public string GetFilenameAddition()
78+
{
79+
return this.fileNameAddition;
80+
}
81+
82+
protected short[] GetQuantError(Color32 originalPixel, Color32 newPixel)
83+
{
84+
short[] returnValue = new short[4];
85+
86+
returnValue [0] = (short)(originalPixel.r - newPixel.r);
87+
returnValue [1] = (short)(originalPixel.g - newPixel.g);
88+
returnValue [2] = (short)(originalPixel.b - newPixel.b);
89+
returnValue [3] = (short)(originalPixel.a - newPixel.a);
90+
91+
return returnValue;
92+
}
93+
94+
public void ModifyImageWithErrorAndMultiplier(int x, int y, short[] quantError, float multiplier)
95+
{
96+
Color32 oldColor = this.pixels[GetIndexWith(x, y)];
97+
98+
// We limit the color here because we don't want the value go over 255 or under 0
99+
Color32 newColor = new Color32(
100+
GetLimitedValue(oldColor.r, Mathf.RoundToInt(quantError[0] * multiplier)),
101+
GetLimitedValue(oldColor.g, Mathf.RoundToInt(quantError[1] * multiplier)),
102+
GetLimitedValue(oldColor.b, Mathf.RoundToInt(quantError[2] * multiplier)),
103+
GetLimitedValue(oldColor.a, Mathf.RoundToInt(quantError[3] * multiplier)));
104+
105+
this.pixels[GetIndexWith(x, y)] = newColor;
106+
}
107+
108+
private static byte GetLimitedValue(byte original, int error)
109+
{
110+
int newValue = original + error;
111+
return (byte)Mathf.Clamp(newValue, byte.MinValue, byte.MaxValue);
112+
}
113+
}

Diff for: FakeDithering.cs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
This file implements fake dithering, meaning NO dithering is done.
3+
4+
This is free and unencumbered software released into the public domain.
5+
*/
6+
7+
class FakeDithering : DitheringBase
8+
{
9+
public FakeDithering(FindColor colorfunc) : base(colorfunc)
10+
{
11+
this.methodLongName = "No dithering";
12+
this.fileNameAddition = "_NONE";
13+
}
14+
15+
override protected void PushError(int x, int y, short[] quantError)
16+
{
17+
// Don't do anything
18+
}
19+
}
20+

Diff for: FloydSteinbergDithering.cs

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
This file implements error pushing of dithering via (Robert) Floyd and (Louis) Steinberg kernel.
3+
This is free and unencumbered software released into the public domain.
4+
*/
5+
6+
public class FloydSteinbergDithering : DitheringBase
7+
{
8+
public FloydSteinbergDithering(FindColor colorfunc) : base(colorfunc)
9+
{
10+
this.methodLongName = "Floyd-Steinberg";
11+
this.fileNameAddition = "_FS";
12+
}
13+
14+
override protected void PushError(int x, int y, short[] quantError)
15+
{
16+
// Push error
17+
// X 7/16
18+
// 3/16 5/16 1/16
19+
20+
int xMinusOne = x - 1;
21+
int xPlusOne = x + 1;
22+
int yPlusOne = y + 1;
23+
24+
// Current row
25+
if (this.IsValidCoordinate(xPlusOne, y))
26+
{
27+
this.ModifyImageWithErrorAndMultiplier(xPlusOne, y, quantError, 7.0f / 16.0f);
28+
}
29+
30+
// Next row
31+
if (this.IsValidCoordinate(xMinusOne, yPlusOne))
32+
{
33+
this.ModifyImageWithErrorAndMultiplier(xMinusOne, yPlusOne, quantError, 3.0f / 16.0f);
34+
}
35+
36+
if (this.IsValidCoordinate(x, yPlusOne))
37+
{
38+
this.ModifyImageWithErrorAndMultiplier(x, yPlusOne, quantError, 5.0f / 16.0f);
39+
}
40+
41+
if (this.IsValidCoordinate(xPlusOne, yPlusOne))
42+
{
43+
this.ModifyImageWithErrorAndMultiplier(xPlusOne, yPlusOne, quantError, 1.0f / 16.0f);
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)