rixmap 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,351 @@
1
+ // -*- coding: utf-8 -*-
2
+ /**
3
+ * 画像形式情報クラスデータ定義ヘッダ
4
+ */
5
+ #pragma once
6
+ #include "common.hxx"
7
+ #include "channel.hxx"
8
+
9
+ namespace Rixmap {
10
+
11
+ // 画像形式マスク
12
+ const uint32_t MODE_ALPHA_MASK = 0x80000000;
13
+ const uint32_t MODE_TYPE_MASK = 0x70000000;
14
+ const uint32_t MODE_TYPE_NONE = 0x00000000;
15
+ const uint32_t MODE_TYPE_INDEXED = 0x10000000;
16
+ const uint32_t MODE_TYPE_GRAYSCALE = 0x20000000;
17
+ const uint32_t MODE_TYPE_RGB = 0x30000000;
18
+
19
+ /**
20
+ * 画像種別とか
21
+ *
22
+ * 仕様ってかフォーマット.
23
+ * 表示はビットストリングですよっと.
24
+ *
25
+ * ### パレット形式用
26
+ * 0001dddd dddd0000 00000000 000iiiii
27
+ *
28
+ * d (8bits): 全体ビット数
29
+ * i (5bits): パレットインデックスに使うビット数
30
+ *
31
+ * ### グレイスケール形式
32
+ * f010dddd ddddaaaa a0000000 000ggggg
33
+ *
34
+ * f (1bits): αチャンネルがあるなら1
35
+ * d (8bits): 全体ビット数
36
+ * a (5bits): αチャンネル用ビット数. αチャンネルがない場合は0
37
+ * g (5bits): グレースケール値に使うビット数
38
+ *
39
+ * ### RGBカラー形式
40
+ * f011dddd ddddaaaa arrrrrgg gggbbbbb
41
+ *
42
+ * f (1bits): αチャンネルがあるなら1
43
+ * d (8bits): 全体ビット数
44
+ * a (5bits): αチャンネル用ビット数. αチャンネルがない場合は0
45
+ * r (5bits): 赤要素用ビット数
46
+ * g (5bits): 緑要素用ビット数
47
+ * b (5bits): 青要素用ビット数
48
+ *
49
+ */
50
+ enum class Mode : uint32_t {
51
+ NONE = 0x00000000, // 未設定
52
+ INDEXED = 0x10800008, // 8bit INDEXED (PALETTE)
53
+ GRAYSCALE = 0x20800008, // 8bit LUMINANCE (GRAYSCALE)
54
+ GRAYALPHA = 0xA1040008, // 8bit LUMINANCE with 8bit ALPHA
55
+ RGB = 0x31802108, // 24bit RGB (Full Color)
56
+ RGBA = 0xB2042108, // 24bit RGB with 8bit ALPHA (True Color)
57
+ };
58
+
59
+ //// 以下旧定義. 消すの持ったいないのでとりあえず残しておく(;^ω^)
60
+ //enum class Mode : uint32_t {
61
+ // NONE = 0x00000000, // 未設定
62
+ // PALETTE1 = 0x10100001, // 1bit PALETTE (Monochrome)
63
+ // PALETTE2 = 0x10200002, // 2bit PALETTE
64
+ // PALETTE3 = 0x10300003, // 3bit PALETTE (Internal)
65
+ // PALETTE4 = 0x10400004, // 4bit PALETTE
66
+ // PALETTE5 = 0x10500005, // 5bit PALETTE (Internal)
67
+ // PALETTE6 = 0x10600006, // 6bit PALETTE (Internal)
68
+ // PALETTE7 = 0x10700007, // 7bit PALETTE (Internal)
69
+ // PALETTE8 = 0x10800008, // 8bit PALETTE
70
+ // GRAYSCALE8 = 0x20800008, // 8bit LUMINANCE (GRAYSCALE)
71
+ // ALPHAGRAY16 = 0xA1040008, // 8bit LUMINANCE with 8bit ALPHA
72
+ // RGB555 = 0x310014A5, // 16bit RGB (5bit R, G and B)
73
+ // RGB565 = 0x310014C5, // 16bit RGB (5bit R, 6bit G and 5bit B)
74
+ // RGB24 = 0x31802108, // 24bit RGB (Full Color)
75
+ // ARGB32 = 0xB2042108, // 24bit RGB with 8bit ALPHA (True Color)
76
+ //};
77
+
78
+ // コンテナ型
79
+ typedef std::vector<Channel> ChannelArray;
80
+ typedef std::map<Channel, int16_t> ChannelDepthMap;
81
+
82
+ /*
83
+ * 画像形式名対応表
84
+ */
85
+ const std::map<Mode, std::string> MODE_NAMES = {
86
+ {Mode::NONE, "NONE"},
87
+ {Mode::INDEXED, "INDEXED"},
88
+ {Mode::GRAYSCALE, "GRAYSCALE"},
89
+ {Mode::GRAYALPHA, "GRAYALPHA"},
90
+ {Mode::RGB, "RGB"},
91
+ {Mode::RGBA, "RGBA"}
92
+ };
93
+
94
+ /**
95
+ * 画像形式情報クラス
96
+ */
97
+ class ModeInfo {
98
+ public: // 公開クラスメンバ関数
99
+ static inline const std::string& GetModeName(Mode mode) { return MODE_NAMES.at(mode); }
100
+ static inline Mode GetModeByName(const std::string& name) {
101
+ for (auto it = MODE_NAMES.begin(); it != MODE_NAMES.end(); it++) {
102
+ const std::string& entry = it->second;
103
+ if (name == entry) {
104
+ return it->first;
105
+ }
106
+ }
107
+ return Mode::NONE;
108
+ }
109
+
110
+ protected: // 限定公開メンバ
111
+ // 基本情報
112
+ Mode _mode; // 画像形式本体
113
+ ChannelArray _channels; // 内包しているチャンネルリスト
114
+
115
+ // 追加情報 (キャッシュみたいなもんです)
116
+ uint32_t _type; // 画像形式種別 (パレット形式 / グレースケール / RGBカラー) の区別用
117
+ std::string _name; // 画像形式名
118
+ int16_t _depth; // 画像形式の全体ビット数
119
+ ChannelDepthMap _depths; // 各チャンネルのビット数
120
+ bool _hasAlpha; // 透明度をサポートしているかどうか
121
+
122
+ public: // コンストラクタ
123
+ /**
124
+ * デフォルトコンストラクタ.
125
+ */
126
+ ModeInfo(Mode mode = Mode::NONE) : _mode(mode), _channels(), _depth(0), _depths() {
127
+ this->refresh();
128
+ }
129
+
130
+ /**
131
+ * コピーコンストラクタ
132
+ */
133
+ ModeInfo(const ModeInfo& info) : _mode(info._mode), _channels(), _depth(0), _depths() {
134
+ // 再初期化するんでコピーじゃない気もする
135
+ this->refresh();
136
+ }
137
+
138
+ /**
139
+ * デストラクタ.
140
+ */
141
+ virtual ~ModeInfo() {
142
+ this->_channels.clear();
143
+ this->_name.clear();
144
+ this->_depths.clear();
145
+ }
146
+
147
+ public: // プロパティメンバ関数
148
+ /**
149
+ * 現在の画像形式値を返します.
150
+ */
151
+ inline Mode getMode() const { return this->_mode; }
152
+
153
+ /**
154
+ * 画像形式値を再設定します.
155
+ */
156
+ inline void setMode(Mode mode) {
157
+ Mode current = this->_mode;
158
+ try {
159
+ this->_mode = mode;
160
+ this->refresh();
161
+ } catch (...) {
162
+ // 例外起きたら戻す
163
+ this->_mode = current;
164
+ throw; // 再投げ
165
+ }
166
+ }
167
+
168
+ /**
169
+ * 画像形式値を整数値として取得します.
170
+ */
171
+ inline uint8_t getValue() const { return static_cast<uint32_t>(this->_mode); }
172
+
173
+ /**
174
+ * 画像種別を取得します.
175
+ */
176
+ inline uint32_t getType() const { return this->_type; }
177
+
178
+ /**
179
+ * 含まれているチャンネルリストを返します.
180
+ * 一応ピクセルを配列データにしたときの並び順です. たぶん.
181
+ */
182
+ inline const ChannelArray& getChannels() const { return this->_channels; }
183
+
184
+ /**
185
+ * チャンネル数を返します.
186
+ */
187
+ inline size_t getChannelCount() const { return this->_channels.size(); }
188
+
189
+ /**
190
+ * ピクセルあたりのビット数を返します.
191
+ */
192
+ inline int16_t getDepth() const { return this->_depth; }
193
+
194
+ /**
195
+ * 含まれるチャンネル毎のビット数を返します.
196
+ */
197
+ inline const ChannelDepthMap& getDepths() const { return this->_depths; }
198
+
199
+ /**
200
+ * 画像形式名を文字列で返します.
201
+ */
202
+ inline const std::string& getName() const { return this->_name; }
203
+
204
+ /**
205
+ * 透明度をサポートしているかを返します.
206
+ */
207
+ inline bool hasAlpha() const { return this->_hasAlpha; }
208
+
209
+ public: // 公開メンバ関数
210
+ /**
211
+ * インデックスカラー形式ならtrueを返します.
212
+ */
213
+ inline bool isIndexedType() const { return (this->_type == MODE_TYPE_INDEXED); }
214
+
215
+ /**
216
+ * グレースケールカラー形式ならtrueを返します.
217
+ */
218
+ inline bool isGrayScaleType() const { return (this->_type == MODE_TYPE_GRAYSCALE); }
219
+
220
+ /**
221
+ * RGBカラー形式ならtrueを返します.
222
+ */
223
+ inline bool isRGBType() const { return (this->_type == MODE_TYPE_RGB); }
224
+
225
+ /**
226
+ * この画像形式が指定したチャンネルを持っているかどうかを返します.
227
+ */
228
+ inline bool has(Channel channel) const {
229
+ for (auto it = this->_channels.begin(); it != this->_channels.end(); it++) {
230
+ if (*it == channel) {
231
+ return true;
232
+ }
233
+ }
234
+ return false;
235
+ }
236
+
237
+ public: // 演算子オーバーロード
238
+ inline bool operator==(const ModeInfo& info) const { return (this->_mode == info._mode); }
239
+ inline bool operator!=(const ModeInfo& info) const { return (this->_mode != info._mode); }
240
+ //friend bool operator==(const ModeInfo& lhs, const ModeInfo& rhs);
241
+ //friend bool operator!=(const ModeInfo& lhs, const ModeInfo& rhs);
242
+
243
+ /**
244
+ * 代入演算子定義
245
+ */
246
+ inline ModeInfo& operator=(const ModeInfo& info) {
247
+ this->setMode(info._mode);
248
+ return *this;
249
+ }
250
+
251
+ inline ModeInfo& operator=(Mode mode) {
252
+ this->setMode(mode);
253
+ return *this;
254
+ }
255
+
256
+ private: // 非公開メンバ関数
257
+ /**
258
+ * 現在の画像形式値から、ほかのメンバを初期化します.
259
+ */
260
+ void refresh() {
261
+ // 整数値にする
262
+ uint32_t value = static_cast<uint32_t>(this->_mode);
263
+
264
+ // マスクデータを解凍
265
+ uint32_t type = (value & MODE_TYPE_MASK);
266
+ uint32_t alpha = (value & MODE_ALPHA_MASK);
267
+ uint32_t depth = (value & 0x0FF00000) >> 20;
268
+ uint32_t channel0 = (value & 0x000F8000) >> 15; // 透明度用
269
+ uint32_t channel1 = (value & 0x00007C00) >> 10; // 赤要素用
270
+ uint32_t channel2 = (value & 0x000003E0) >> 5; // 緑要素用
271
+ uint32_t channel3 = (value & 0x0000001F); // 青要素 / パレットインデックス / 輝度値用
272
+ bool hasAlpha = (alpha != 0);
273
+
274
+ // 種類ごとに処理
275
+ // (不明なのが来たら例外出す)
276
+ switch (type) {
277
+ case MODE_TYPE_INDEXED:
278
+ // パレット形式
279
+ this->_channels.clear();
280
+ this->_channels.push_back(Channel::PALETTE);
281
+ this->_depths[Channel::PALETTE] = channel3;
282
+ break;
283
+
284
+ case MODE_TYPE_GRAYSCALE:
285
+ // グレースケール形式
286
+ this->_channels.clear();
287
+ this->_channels.push_back(Channel::LUMINANCE);
288
+ this->_depths[Channel::PALETTE] = channel3;
289
+ break;
290
+
291
+ case MODE_TYPE_RGB:
292
+ // RGBカラー形式
293
+ this->_channels.clear();
294
+ this->_channels.push_back(Channel::RED);
295
+ this->_channels.push_back(Channel::GREEN);
296
+ this->_channels.push_back(Channel::BLUE);
297
+ this->_depths[Channel::RED ] = channel1;
298
+ this->_depths[Channel::GREEN] = channel2;
299
+ this->_depths[Channel::BLUE ] = channel3;
300
+ break;
301
+
302
+ case MODE_TYPE_NONE:
303
+ // 空形式. なんもない
304
+ this->_channels.clear();
305
+ break;
306
+
307
+ default:
308
+ // 謎形式. 例外投げる(/・ω・)/
309
+ {
310
+ std::ostringstream msg;
311
+ msg << "Unsupported mode: " << std::hex << std::showbase << value;
312
+ throw std::invalid_argument(msg.str());
313
+ }
314
+ }
315
+
316
+ // 透明度
317
+ if (hasAlpha) {
318
+ this->_channels.push_back(Channel::ALPHA);
319
+ this->_depths[Channel::ALPHA] = channel0;
320
+ }
321
+
322
+ // 共通設定
323
+ this->_type = type;
324
+ this->_hasAlpha = hasAlpha;
325
+ this->_depth = depth;
326
+ this->_name = MODE_NAMES.at(this->_mode);
327
+ }
328
+ };
329
+
330
+ /*
331
+ * グローバル演算子オーバーロード
332
+ */
333
+ //inline bool operator==(const ModeInfo& lhs, const ModeInfo& rhs) { return (lhs._mode == rhs._mode); }
334
+ //inline bool operator!=(const ModeInfo& lhs, const ModeInfo& rhs) { return (lhs._mode != rhs._mode); }
335
+
336
+ /**
337
+ * 画像形式データクラス.
338
+ */
339
+ class ModeData : public ModeInfo {
340
+ public: // コンストラクタ
341
+ ModeData(Mode mode = Mode::NONE) : ModeInfo(mode) {}
342
+ ModeData(const ModeInfo& info) : ModeInfo(info) {}
343
+ ModeData(const ModeData& data) : ModeInfo(data._mode) {}
344
+ virtual ~ModeData() {}
345
+ };
346
+ }
347
+
348
+
349
+ //============================================================================//
350
+ // $Id: mode.hxx,v add33526d522 2014/04/19 16:27:29 chikuchikugonzalez $
351
+ // vim: set sts=4 ts=4 sw=4 expandtab foldmethod=marker:
@@ -0,0 +1,220 @@
1
+ // -*- coding: utf-8 -*-
2
+ /**
3
+ * パレット情報クラスデータ定義ヘッダ
4
+ */
5
+ #pragma once
6
+ #include "common.hxx"
7
+ #include "color.hxx"
8
+
9
+ namespace Rixmap {
10
+ // コンテナ型を定義
11
+ typedef std::vector<Color> ColorArray;
12
+
13
+ /**
14
+ * パレット情報クラスデータ
15
+ */
16
+ class PaletteData {
17
+ private: // 非公開メンバ
18
+ ColorArray _colors; // カラーリスト
19
+ Color _default; // デフォルトカラー
20
+
21
+ public: // コンストラクタとか
22
+ /**
23
+ * デフォルトコンストラクタ.
24
+ */
25
+ PaletteData(size_t size = 256, const Color defaultColor = Color(0, 0, 0, 255)) : _colors(), _default(defaultColor) {
26
+ this->_colors.resize(size);
27
+ for (size_t i = 0; i < size; i++) {
28
+ this->_colors[i] = this->_default;
29
+ }
30
+ }
31
+
32
+ /**
33
+ * カラーリストから初期化
34
+ */
35
+ PaletteData(const ColorArray& colors, const Color defaultColor = Color(0, 0, 0, 255)) : _colors(colors), _default(defaultColor) {}
36
+
37
+ /**
38
+ * コピーコンストラクタ
39
+ */
40
+ PaletteData(const PaletteData& palette) : _colors(palette._colors), _default(palette._default) {}
41
+
42
+ /**
43
+ * デストラクタ
44
+ */
45
+ ~PaletteData() {}
46
+
47
+ public: // プロパティメンバ関数
48
+ /**
49
+ * 内部カラーリストへの参照を返します.
50
+ */
51
+ inline const ColorArray& getColors() const { return this->_colors; }
52
+
53
+ /**
54
+ * カラーリストを更新します.
55
+ * パレットサイズは変更されません.
56
+ */
57
+ void setColors(const ColorArray& src) {
58
+ size_t srclen = src.size();
59
+ size_t dstlen = this->_colors.size();
60
+
61
+ // バッファを作成
62
+ ColorArray buf(dstlen, this->_default);
63
+
64
+ // データを複製
65
+ size_t len = (srclen <= dstlen) ? srclen : dstlen;
66
+ for (size_t i = 0; i < len; i++) {
67
+ buf[i] = src[i];
68
+ }
69
+
70
+ // 入れ替え
71
+ buf.swap(this->_colors);
72
+ }
73
+
74
+ /**
75
+ * カラーリストサイズを返します.
76
+ */
77
+ inline size_t getSize() const { return this->_colors.size(); }
78
+
79
+ /**
80
+ * #at メソッドにおいて存在しないオフセットを指定した場合のデフォルトカラーを取得します.
81
+ */
82
+ inline const Color& getDefaultColor() const { return this->_default; }
83
+
84
+ /**
85
+ * #at メソッドで返されるデフォルトカラーを設定します.
86
+ */
87
+ inline void setDefaultColor(const Color& color) { this->_default = color; }
88
+
89
+ public: // メンバ関数
90
+ /**
91
+ * 指定したオフセットのカラーデータを取得します.
92
+ * オフセットが範囲外の場合はデフォルトカラーを返します.
93
+ */
94
+ inline Color& at(size_t offset) {
95
+ if (/* 0 <= offset && */ offset <= this->_colors.size()) {
96
+ return this->_colors[offset];
97
+ } else {
98
+ return this->_default;
99
+ }
100
+ }
101
+ inline const Color& at(size_t offset) const { return this->at(offset); }
102
+
103
+ /**
104
+ * 指定したオフセットのカラーデータを取得します.
105
+ * オフセットが範囲外の場合は例外を送出します.
106
+ */
107
+ inline Color& get(size_t offset) {
108
+ if (/* 0 <= offset && */ offset <= this->_colors.size()) {
109
+ return this->_colors[offset];
110
+ } else {
111
+ std::ostringstream msg;
112
+ msg << "offsetis out of range: " << offset << " for 0.." << this->_colors.size();
113
+ throw std::out_of_range(msg.str());
114
+ }
115
+ }
116
+ inline const Color& get(size_t offset) const { return this->get(offset); }
117
+
118
+ /**
119
+ * 指定したオフセットのカラーデータを変更します.
120
+ * オフセットが範囲外の場合は例外を送出します.
121
+ */
122
+ inline void set(size_t offset, const Color& color) {
123
+ if (/* 0 <= offset && */ offset <= this->_colors.size()) {
124
+ this->_colors[offset] = color;
125
+ } else {
126
+ std::ostringstream msg;
127
+ msg << "offsetis out of range: " << offset << " for 0.." << this->_colors.size();
128
+ throw std::out_of_range(msg.str());
129
+ }
130
+ }
131
+
132
+ /**
133
+ * パレットサイズを変更します.
134
+ */
135
+ void resize(size_t size) {
136
+ // バッファ
137
+ ColorArray buf(size, this->_default);
138
+
139
+ // バッファへコピーする長さを決定
140
+ size_t cursize = this->getSize();
141
+ size_t length = (size <= cursize) ? size : cursize;
142
+ for (size_t i = 0; i < length; i++) {
143
+ buf[i] = this->_colors[i];
144
+ }
145
+
146
+ // 入れ替え
147
+ buf.swap(this->_colors);
148
+ }
149
+
150
+ public: // メンバ関数
151
+ /**
152
+ * 指定した色に最も近い色のオフセットを返します.
153
+ *
154
+ * @param [const Color&] search 探す色
155
+ */
156
+ inline size_t closest(const Color& search) const {
157
+ // MinGW x86-64のRubyだとpowがマクロ定義されているため、std::powが動かなくなる問題の対策
158
+ using namespace std;
159
+ size_t length = this->getSize();
160
+ size_t offset = 0;
161
+ double colorDistance = DBL_MAX;
162
+ //double alphaDistance = DBL_MAX;
163
+
164
+ for (size_t i = 0; i < length; i++) {
165
+ const Color& color = this->_colors[i];
166
+ double distance = color.distance(search);
167
+ if (distance == 0.0) {
168
+ offset = i;
169
+ break;
170
+ } else if (colorDistance > distance) {
171
+ offset = i;
172
+ colorDistance = distance;
173
+ }
174
+ }
175
+
176
+ return offset;
177
+ }
178
+
179
+ /**
180
+ * 指定した色に最も近い色を返します.
181
+ *
182
+ * @param [const Color&] search 探す色
183
+ */
184
+ inline const Color& nearby(const Color& search) const {
185
+ size_t offset = this->closest(search);
186
+ return this->_colors[offset];
187
+ }
188
+
189
+ public: // 演算子オーバーロード
190
+ /**
191
+ * 配列アクセス演算子
192
+ */
193
+ inline Color& operator[](size_t offset) { return this->at(offset); }
194
+ inline const Color& operator[](size_t offset) const { return this->at(offset); }
195
+
196
+ /**
197
+ * 等値比較演算子.
198
+ */
199
+ inline bool operator==(const PaletteData& palette) {
200
+ if (this->_colors.size() == palette._colors.size()) {
201
+ size_t size = this->_colors.size();
202
+ for (size_t i = 0; i < size; i++) {
203
+ if (this->_colors[i] != palette._colors[i]) {
204
+ return false;
205
+ }
206
+ }
207
+ return true;
208
+ } else {
209
+ return false;
210
+ }
211
+ }
212
+
213
+ inline bool operator!=(const PaletteData& palette) { return !(*this == palette); }
214
+ };
215
+ }
216
+
217
+
218
+ //============================================================================//
219
+ // $Id: palette.hxx,v 5b9a0968eca5 2014/04/20 13:37:36 chikuchikugonzalez $
220
+ // vim: set sts=4 ts=4 sw=4 expandtab foldmethod=marker:
data/src/rixmap.hxx ADDED
@@ -0,0 +1,19 @@
1
+ // -*- coding: utf-8 -*-
2
+ /**
3
+ * Rixmapライブラリ基本ヘッダ
4
+ */
5
+ #pragma once
6
+ #include <ruby.h>
7
+ #include "config.h"
8
+ #include "rixmap/common.hxx"
9
+ #include "rixmap/binary.hxx"
10
+ #include "rixmap/channel.hxx"
11
+ #include "rixmap/mode.hxx"
12
+ #include "rixmap/color.hxx"
13
+ #include "rixmap/palette.hxx"
14
+ #include "rixmap/image.hxx"
15
+
16
+
17
+ //============================================================================//
18
+ // $Id: rixmap.hxx,v add33526d522 2014/04/19 16:27:29 chikuchikugonzalez $
19
+ // vim: set sts=4 ts=4 sw=4 expandtab foldmethod=marker: