1// Aseprite Render Library
2// Copyright (c) 2020 Igara Studio S.A.
3// Copyright (c) 2017 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifndef RENDER_DITHERING_MATRIX_H_INCLUDED
9#define RENDER_DITHERING_MATRIX_H_INCLUDED
10#pragma once
11
12#include <algorithm>
13#include <vector>
14
15namespace render {
16
17 class DitheringMatrix {
18 public:
19 DitheringMatrix()
20 : m_rows(1), m_cols(1)
21 , m_matrix(1, 1)
22 , m_maxValue(1) {
23 }
24
25 DitheringMatrix(int rows, int cols)
26 : m_rows(rows), m_cols(cols)
27 , m_matrix(rows*cols, 0)
28 , m_maxValue(1) {
29 }
30
31 int rows() const { return m_rows; }
32 int cols() const { return m_cols; }
33
34 int maxValue() const { return m_maxValue; }
35 void calcMaxValue() {
36 m_maxValue = *std::max_element(m_matrix.begin(),
37 m_matrix.end());
38 m_maxValue = std::max(m_maxValue, 1);
39 }
40
41 int operator()(int i, int j) const {
42 return m_matrix[(i%m_rows)*m_cols + (j%m_cols)];
43 }
44
45 int& operator()(int i, int j) {
46 return m_matrix[(i%m_rows)*m_cols + (j%m_cols)];
47 }
48
49 private:
50 int m_rows, m_cols;
51 std::vector<int> m_matrix;
52 int m_maxValue;
53 };
54
55 // Creates a Bayer dither matrix.
56 class BayerMatrix : public DitheringMatrix {
57 static int D2[4];
58
59 public:
60 BayerMatrix(int n) : DitheringMatrix(n, n) {
61 for (int i=0; i<n; ++i)
62 for (int j=0; j<n; ++j)
63 operator()(i, j) = Dn(i, j, n);
64
65 calcMaxValue();
66 }
67
68 private:
69 int Dn(int i, int j, int n) const {
70 ASSERT(i >= 0 && i < n);
71 ASSERT(j >= 0 && j < n);
72
73 if (n == 2)
74 return D2[i*2 + j];
75 else
76 return
77 + 4*Dn(i%(n/2), j%(n/2), n/2)
78 + Dn(i/(n/2), j/(n/2), 2);
79 }
80 };
81
82} // namespace render
83
84#endif
85