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