import IImageData from '../model/IImageData' ; import Pixels from '../model/Pixels' ; /**
 * Apply ordered dithering to an image.
 */ export default class OrderedDither { public static presets : { [ key ] : number [ ] [ ] ; } = { bayer2x2 : [ [ 1 , 3 ] , [ 4 , 2 ] ] , bayer4x4 : [ [ 1 , 9 , 3 , 11 ] , [ 13 , 5 , 15 , 7 ] , [ 4 , 12 , 2 , 10 ] , [ 16 , 8 , 14 , 6 ] ] , bayer8x8 : [ [ 1 , 49 , 13 , 61 , 4 , 52 , 16 , 64 ] , [ 33 , 17 , 45 , 29 , 36 , 20 , 48 , 31 ] , [ 9 , 57 , 5 , 53 , 12 , 60 , 8 , 56 ] , [ 41 , 25 , 37 , 21 , 44 , 28 , 40 , 24 ] , [ 3 , 51 , 15 , 63 , 2 , 50 , 14 , 62 ] , [ 35 , 19 , 47 , 31 , 34 , 18 , 46 , 30 ] , [ 11 , 59 , 7 , 55 , 10 , 58 , 6 , 54 ] , [ 43 , 27 , 39 , 23 , 42 , 26 , 38 , 22 ] ] , none : [ [ 0 ] ] , test : [ [ 1 , 2 , 3 , 4 ] , [ 12 , 13 , 14 , 5 ] , [ 11 , 16 , 15 , 6 ] , [ 10 , 9 , 8 , 7 ] ] , test2 : [ [ 1 , 5 , 6 , 2 ] , [ 9 , 13 , 14 , 11 ] , [ 10 , 16 , 15 , 12 ] , [ 3 , 7 , 8 , 4 ] ] , test3 : [ [ 1 , 2 , 3 , 4 , 33 , 34 , 35 , 36 ] , [ 5 , 6 , 7 , 8 , 37 , 38 , 39 , 40 ] , [ 9 , 10 , 11 , 12 , 41 , 42 , 43 , 44 ] , [ 13 , 14 , 15 , 16 , 45 , 46 , 47 , 48 ] , [ 49 , 50 , 51 , 52 , 17 , 18 , 19 , 20 ] , [ 53 , 54 , 55 , 56 , 21 , 22 , 23 , 24 ] , [ 57 , 58 , 59 , 60 , 25 , 26 , 27 , 28 ] , [ 61 , 62 , 63 , 64 , 29 , 30 , 31 , 32 ] ] , test4 : [ [ 32 , 16 , 8 , 16 ] , [ 16 , 32 , 0 , 8 ] , [ 8 , 16 , 32 , 16 ] , [ 0 , 0 , 0 , 32 ] , [ 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 ] , [ 8 , 0 , 0 , 0 ] , [ 16 , 8 , 0 , 8 ] ] , test5 : [ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] , test6 : [ [ 27 , 49 , 50 , 51 , 52 , 53 , 54 , 28 ] , [ 64 , 17 , 37 , 6 , 7 , 38 , 18 , 55 ] , [ 22 , 48 , 5 , 29 , 30 , 8 , 39 , 23 ] , [ 47 , 16 , 36 , 1 , 2 , 31 , 9 , 40 ] , [ 46 , 15 , 35 , 4 , 3 , 32 , 10 , 41 ] , [ 21 , 45 , 14 , 34 , 33 , 11 , 42 , 24 ] , [ 63 , 20 , 44 , 13 , 12 , 43 , 19 , 56 ] , [ 26 , 62 , 61 , 60 , 59 , 58 , 57 , 25 ] ] , test7 : [ [ 0 , 0 , 0 , 0 , 12 , 27 , 57 , 0 ] , [ 0 , 0 , 0 , 13 , 28 , 58 , 27 , 10 ] , [ 0 , 0 , 14 , 29 , 59 , 28 , 11 , 0 ] , [ 0 , 15 , 30 , 60 , 29 , 12 , 0 , 0 ] , [ 16 , 31 , 61 , 30 , 13 , 0 , 0 , 0 ] , [ 32 , 62 , 31 , 14 , 0 , 0 , 0 , 0 ] , [ 63 , 32 , 14 , 0 , 0 , 0 , 0 , 0 ] , [ 32 , 16 , 0 , 0 , 0 , 0 , 0 , 0 ] ] , test8 : [ [ 0 , 0 , 32 , 63 , 62 , 31 , 0 , 0 ] , [ 0 , 17 , 50 , 32 , 31 , 61 , 30 , 0 ] , [ 18 , 51 , 23 , 0 , 0 , 30 , 60 , 29 ] , [ 19 , 52 , 24 , 0 , 0 , 29 , 59 , 28 ] , [ 20 , 53 , 25 , 0 , 0 , 28 , 58 , 27 ] , [ 0 , 21 , 54 , 26 , 27 , 57 , 26 , 0 ] , [ 0 , 0 , 22 , 55 , 56 , 25 , 0 , 0 ] , [ 0 , 0 , 0 , 23 , 24 , 0 , 0 , 0 ] ] , test9 : [ [ 64 , 63 , 62 , 61 , 60 , 59 , 58 , 57 ] , [ 48 , 47 , 46 , 45 , 44 , 43 , 42 , 40 ] , [ 23 , 22 , 21 , 20 , 19 , 18 , 17 , 16 ] , [ 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ] , [ 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 ] , [ 31 , 30 , 29 , 28 , 27 , 26 , 25 , 24 ] , [ 39 , 38 , 37 , 36 , 35 , 34 , 33 , 32 ] , [ 56 , 55 , 54 , 53 , 52 , 51 , 50 , 49 ] ] } ; private readonly matrix : number [ ] [ ] = [ ] ; constructor ( normalizedMatrix , depth ) { const factor = 1 / ( normalizedMatrix . length * normalizedMatrix [ 0 ] . length ) ; this . matrix = normalizedMatrix . map ( ( row , rowIndex ) => { return normalizedMatrix [ rowIndex ] . map ( column => depth * ( factor * column - 0.5 ) ) ; } ) ; } public dither ( image ) { for ( let y = 0 ; y < image . height ; y += 1 ) { for ( let x = 0 ; x < image . width ; x += 1 ) { Pixels . poke ( image , x , y , this . offsetColor ( Pixels . peek ( image , x , y ) , x , y ) ) ; } } } private offsetColor ( color , x , y ) { const offset = this . matrix [ y % this . matrix . length ] [ x % this . matrix [ 0 ] . length ] ; return Pixels . add ( color , [ offset , offset , offset ] ) ; } }