1 /*
2  * Copyright (C) 2016 Y.Sugahara (moveccr)
3  * Copyright (C) 2021 Tetsuya Isaki
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
21  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #pragma once
28 
29 #include "sayaka.h"
30 #include "Image.h"
31 #include <vector>
32 
33 // 減色モード
34 enum ReductorReduceMode {
35 	Fast,			// 速度優先法
36 	Simple,			// 単純一致法
37 	HighQuality,	// 二次元誤差分散法
38 };
39 
40 // カラーモード
41 enum ReductorColorMode {
42 	RCM_Mono,
43 	RCM_Gray,
44 	RCM_GrayMean,
45 	RCM_Fixed8,
46 	RCM_FixedX68k,
47 	RCM_FixedANSI16,
48 	RCM_Fixed256,
49 	RCM_Fixed256RGBI,
50 	RCM_Custom,
51 
52 	Mono			= RCM_Mono,
53 	Gray			= RCM_Gray,
54 	GrayMean		= RCM_GrayMean,
55 	Fixed8			= RCM_Fixed8,
56 	FixedX68k		= RCM_FixedX68k,
57 	FixedANSI16		= RCM_FixedANSI16,
58 	Fixed256		= RCM_Fixed256,
59 	Fixed256RGBI	= RCM_Fixed256RGBI,
60 	Custom			= RCM_Custom,
61 };
62 
63 // ファインダーモード
64 enum ReductorFinderMode {
65 	RFM_Default,
66 	RFM_HSV,
67 };
68 
69 // リターンコード
70 enum ReductorImageCode {
71 	RIC_OK = 0,
72 	RIC_ARG_NULL = 1,
73 	RIC_ABORT_JPEG = 2,
74 };
75 
76 // 誤差拡散アルゴリズム
77 enum ReductorDiffuseMethod {
78 	RDM_FS,			// Floyd Steinberg
79 	RDM_ATKINSON,	// Atkinson
80 	RDM_JAJUNI,		// Jarvis, Judice, Ninke
81 	RDM_STUCKI,		// Stucki
82 	RDM_BURKES,		// Burkes
83 	RDM_2,			// (x+1,y), (x,y+1)
84 	RDM_3,			// (x+1,y), (x,y+1), (x+1,y+1)
85 	RDM_RGB,		// RGB color sepalated
86 };
87 
88 // ----- 色の型
89 
90 struct ColorRGBint {
91 	int r;
92 	int g;
93 	int b;
94 };
95 
96 struct ColorRGBuint8 {
97 	uint8_t r;
98 	uint8_t g;
99 	uint8_t b;
100 };
101 
102 struct ColorRGBint8 {
103 	int8_t r;
104 	int8_t g;
105 	int8_t b;
106 };
107 
108 struct ColorRGBint16 {
109 	int16_t r;
110 	int16_t g;
111 	int16_t b;
112 };
113 
114 struct ColorHSVuint8 {
115 	uint8_t h;	// 0..239, 255=gray
116 	uint8_t s;	// 0..255
117 	uint8_t v;	// 0..255
118 };
119 
120 class ImageReductor
121 {
122 	using FindColorFunc_t = int (ImageReductor::*)(ColorRGBuint8);
123 
124  public:
125 	// デバッグレベル設定
126 	void Init(const Diag& diag);
127 
128 	// パレット数を取得
GetPaletteCount()129 	int GetPaletteCount() const { return PaletteCount; }
130 
131 	// n 番目のパレットデータを取得
GetPalette(int n)132 	ColorRGBuint8 GetPalette(int n) const { return Palette[n]; }
133 
134 	// カラーモードを設定する。
135 	// 変換関数を呼び出す前に、必ずカラーモードを設定すること。
136 	// count はグレースケールでのみ使用。
137 	void SetColorMode(ReductorColorMode mode, ReductorFinderMode finder,
138 		int count = 0);
139 
140 	// ノイズ付加モードを設定する
SetAddNoiseLevel(int level)141 	void SetAddNoiseLevel(int level) {
142 		AddNoiseLevel = level;
143 	}
144 
145 	// 変換
146 	void Convert(ReductorReduceMode mode, Image& img,
147 		std::vector<uint8_t>& dst, int toWidth, int toHeight);
148 
149 	void ColorFactor(float factor);
150 
151 	// High 誤差分散アルゴリズム
152 	ReductorDiffuseMethod HighQualityDiffuseMethod = RDM_FS;
153 
154  private:
155 	int PaletteCount {};
156 
157 	const ColorRGBuint8 *Palette {};
158 
159 	int AddNoiseLevel {};
160 
161 	// 可変パレット用バッファ
162 	ColorRGBuint8 Palette_Custom[256] {};
163 
164 	// 色変換関数の関数ポインタ
165 	FindColorFunc_t ColorFinder {};
166 
167 	// 固定2色パレット
168 	static const ColorRGBuint8 Palette_Mono[];
169 	int FindColor_Mono(ColorRGBuint8 c);
170 
171 	// グレースケールパレット
172 	void SetPalette_Gray(int count);
173 	int FindColor_Gray(ColorRGBuint8 c);
174 	int FindColor_GrayMean(ColorRGBuint8 c);
175 
176 	// 固定8色パレット
177 	static const ColorRGBuint8 Palette_Fixed8[];
178 	int FindColor_Fixed8(ColorRGBuint8 c);
179 
180 	// X68k 固定 16 色パレット
181 	static const ColorRGBuint8 Palette_FixedX68k[];
182 	int FindColor_FixedX68k(ColorRGBuint8 c);
183 
184 	// ANSI 固定 16 色パレット
185 	static const ColorRGBuint8 Palette_FixedANSI16[];
186 	int FindColor_FixedANSI16(ColorRGBuint8 c);
187 
188 	// 固定 256 色 (RGB) パレット
189 	void SetPalette_Fixed256();
190 	int FindColor_Fixed256(ColorRGBuint8 c);
191 
192 	// 固定 256 色 (RGBI) パレット
193 	void SetPalette_Fixed256RGBI();
194 	int FindColor_Fixed256RGBI(ColorRGBuint8 c);
195 
196 	// 円錐型 HSV パレット
197 	int FindColor_HSV(ColorRGBuint8 c);
198 	static ColorHSVuint8 RGBtoHSV(ColorRGBuint8 c);
199 	void CreateHSVPalette();
200 	static int FindColor_HSV_subr(ColorHSVuint8 hsvpal, ColorHSVuint8 hsv);
201 	ColorHSVuint8 HSVPalette[256];
202 
203 	//
204 	// 変換関数
205 	//
206 
207 	static uint8_t Saturate_uint8(int x);
208 	static int RoundDownPow2(int x);
209 	static int rnd(int level);
210 
211 	// 高速変換を行う
212 	void ConvertFast(Image& img, std::vector<uint8_t>& dst,
213 		int toWidth, int toHeight);
214 
215 	// 単純変換を行う
216 	void ConvertSimple(Image& img, std::vector<uint8_t>& dst,
217 		int toWidth, int toHeight);
218 
219 	// 高品質変換を行う
220 	void ConvertHighQuality(Image& img, std::vector<uint8_t>& dst,
221 		int toWidth, int toHeight);
222 
223 	static int16_t Saturate_adderr(int16_t a, int b);
224 	static void set_err(ColorRGBint16 eb[], int x, ColorRGBint col, int ratio);
225 
226 	Diag diag {};
227 
228  public:
229 	// enum 対応
230 	static const char *RRM2str(ReductorReduceMode n);
231 	static const char *RCM2str(ReductorColorMode n);
232 	static const char *RFM2str(ReductorFinderMode n);
233 	static const char *RDM2str(ReductorDiffuseMethod n);
234 	static const char *RAX2str(ResizeAxisMode n);
235 };
236