1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
package dither
// ErrorDiffusionMatrix holds the matrix for the error-diffusion type of dithering.
// An example of this would be Floyd-Steinberg or Atkinson.
//
// Zero values can be used to represent pixels that have already been processed.
// The current pixel is assumed to be the right-most zero value in the top row.
type ErrorDiffusionMatrix [][]float32
// CurrentPixel returns the index the current pixel.
// The current pixel is assumed to be the right-most zero value in the top row.
// In all matrixes that I have seen, the current pixel is always in the middle,
// but this function exists just in case.
//
// Therefore with an ErrorDiffusionMatrix named edm, the current pixel is at:
// edm[0][edm.CurrentPixel()]
//
// Usually you'll want to cache this value.
func (e ErrorDiffusionMatrix) CurrentPixel() int {
for i, v := range e[0] {
if v != 0 {
return i - 1
}
}
// The whole first line is zeros, which doesn't make sense
// Just default to returning the middle of the row.
return len(e[0]) / 2
}
// Offset will take the index of where you are in the matrix and return the
// offset from the current pixel. You have to pass the curPx value yourself
// to allow for caching, but it can be retrieved by calling CurrentPixel().
func (e ErrorDiffusionMatrix) Offset(x, y, curPx int) (int, int) {
return x - curPx, y
}
// ErrorDiffusionStrength modifies an existing error diffusion matrix so that it will
// be applied with the specified strength.
//
// strength is usually a value from 0 to 1.0, where 1.0 means 100% strength, and will
// not modify the matrix at all. It is inversely proportional to contrast - reducing the
// strength increases the contrast. It can be useful at values like 0.8 for reducing
// noise in the dithered image.
//
// See the documentation for Bayer for more details.
func ErrorDiffusionStrength(edm ErrorDiffusionMatrix, strength float32) ErrorDiffusionMatrix {
if strength == 1 {
return edm
}
dy := len(edm)
dx := len(edm[0])
edm2 := make(ErrorDiffusionMatrix, dy)
for y := 0; y < dy; y++ {
edm2[y] = make([]float32, dx)
for x := 0; x < dx; x++ {
edm2[y][x] = edm[y][x] * strength
}
}
return edm2
}
var Simple2D = ErrorDiffusionMatrix{
{0, 0.5},
{0.5, 0},
}
var FloydSteinberg = ErrorDiffusionMatrix{
{0, 0, 7.0 / 16},
{3.0 / 16, 5.0 / 16, 1.0 / 16},
}
var FalseFloydSteinberg = ErrorDiffusionMatrix{
{0, 3.0 / 8},
{3.0 / 8, 2.0 / 8},
}
var JarvisJudiceNinke = ErrorDiffusionMatrix{
{0, 0, 0, 7.0 / 48, 5.0 / 48},
{3.0 / 48, 5.0 / 48, 7.0 / 48, 5.0 / 48, 3.0 / 48},
{1.0 / 48, 3.0 / 48, 5.0 / 48, 3.0 / 48, 1.0 / 48},
}
var Atkinson = ErrorDiffusionMatrix{
{0, 0, 1.0 / 8, 1.0 / 8},
{1.0 / 8, 1.0 / 8, 1.0 / 8, 0},
{0, 1.0 / 8, 0, 0},
}
var Stucki = ErrorDiffusionMatrix{
{0, 0, 0, 8.0 / 42, 4.0 / 42},
{2.0 / 42, 4.0 / 42, 8.0 / 42, 4.0 / 42, 2.0 / 42},
{1.0 / 42, 2.0 / 42, 4.0 / 42, 2.0 / 42, 1.0 / 42},
}
var Burkes = ErrorDiffusionMatrix{
{0, 0, 0, 8.0 / 32, 4.0 / 32},
{2.0 / 32, 4.0 / 32, 8.0 / 32, 4.0 / 32, 2.0 / 32},
}
var Sierra = ErrorDiffusionMatrix{
{0, 0, 0, 5.0 / 32, 3.0 / 32},
{2.0 / 32, 4.0 / 32, 5.0 / 32, 4.0 / 32, 2.0 / 32},
{0, 2.0 / 32, 3.0 / 32, 2.0 / 32, 0},
}
// Sierra3 is another name for the original Sierra matrix.
var Sierra3 = Sierra
var TwoRowSierra = ErrorDiffusionMatrix{
{0, 0, 0, 4.0 / 16, 3.0 / 16},
{1.0 / 16, 2.0 / 16, 3.0 / 16, 2.0 / 16, 1.0 / 16},
}
// Sierra2 is another name for TwoRowSierra
var Sierra2 = TwoRowSierra
var SierraLite = ErrorDiffusionMatrix{
{0, 0, 2.0 / 4},
{1.0 / 4, 1.0 / 4, 0},
}
// Sierra2_4A (usually written as Sierra2-4A) is another name for SierraLite.
var Sierra2_4A = SierraLite
// StevenPigeon is an error diffusion matrix developed by Steven Pigeon.
// Source: https://hbfs.wordpress.com/2013/12/31/dithering/
var StevenPigeon = ErrorDiffusionMatrix{
{0, 0, 0, 2.0 / 14, 1.0 / 14},
{0, 2.0 / 14, 2.0 / 14, 2.0 / 14, 0},
{1.0 / 14, 0, 1.0 / 14, 0, 1.0 / 14},
}
|