rixmap 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +3 -1
- data/lib/rixmap/format/bmp.rb +4 -1
- data/lib/rixmap/format/png/chunk.rb +178 -7
- data/lib/rixmap/format/png/imageio.rb +75 -7
- data/lib/rixmap/version.rb +3 -3
- data/spec/palette_spec.rb +19 -1
- data/src/rixmap/channel.hxx +106 -1
- data/src/rixmap/color.hxx +84 -14
- data/src/rixmap/image.hxx +205 -25
- data/src/rixmap/interpolator.hxx +29 -12
- data/src/rixmapcore.cxx +275 -210
- data/src/rixmapdeformation.cxx +4 -82
- data/src/rixmaphelper.cxx +501 -0
- data/src/rixmaphelper.hxx +82 -0
- data/src/rixmappool.cxx +65 -0
- data/src/rixmappool.hxx +69 -0
- data/test/test_png.rb +18 -5
- metadata +8 -3
- data/src/rixmap/helper.hxx +0 -347
data/src/rixmapdeformation.cxx
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
* Rixmap変形処理実装
|
4
4
|
*/
|
5
5
|
#include "rixmapdeformation.hxx"
|
6
|
+
#include "rixmaphelper.hxx"
|
6
7
|
|
7
8
|
//----------------------------------------------------------------------------//
|
8
9
|
// グローバル変数実体
|
@@ -12,11 +13,6 @@ VALUE cRixmapBaseDeformer = Qnil;
|
|
12
13
|
VALUE cRixmapAffineDeformer = Qnil;
|
13
14
|
VALUE cRixmapAffineMatrix = Qnil;
|
14
15
|
|
15
|
-
//VALUE cRixmapAffinePoint = Qnil;
|
16
|
-
//VALUE cRixmapAffineCenter = Qnil;
|
17
|
-
//VALUE cRixmapAffineScale = Qnil;
|
18
|
-
//VALUE cRixmapAffineTranslation = Qnil;
|
19
|
-
|
20
16
|
//----------------------------------------------------------------------------//
|
21
17
|
// 変換系クラス実装
|
22
18
|
//----------------------------------------------------------------------------//
|
@@ -247,7 +243,8 @@ static VALUE AffineDeformer_deform(int argc, VALUE* argv, VALUE self) {
|
|
247
243
|
}
|
248
244
|
|
249
245
|
// 保存先画像を作成
|
250
|
-
VALUE
|
246
|
+
VALUE srcMetadata = Rixmap::Helper::GetImageMetadata(*srcImage);
|
247
|
+
VALUE dstImageObject = RixmapImage_NewInstance(ipo->getPreferredMode(), newWidth, newHeight, srcMetadata);
|
251
248
|
Rixmap::ImageData* dstImage = rixmap_unwrap<Rixmap::ImageData>(dstImageObject);
|
252
249
|
|
253
250
|
// 移動先チャンネルリスト
|
@@ -523,44 +520,6 @@ static VALUE AffineMatrix_inspect(VALUE self) {
|
|
523
520
|
static_cast<int>(_this->getSkew()));
|
524
521
|
}
|
525
522
|
/* }}} */
|
526
|
-
///* Rixmap::Deformer::AffineMatrix::Point {{{ */
|
527
|
-
///**
|
528
|
-
// * @overload initialize(x=0.0, y=0.0)
|
529
|
-
// * 座標オブジェクトを初期化します.
|
530
|
-
// * @param [Float] x X軸方向データ
|
531
|
-
// * @param [Float] y Y軸方向データ
|
532
|
-
// * @return [void]
|
533
|
-
// */
|
534
|
-
//static VALUE AffinePoint_initialize(int argc, VALUE* argv, VALUE self) {
|
535
|
-
// VALUE argX = Qnil, argY = Qnil;
|
536
|
-
// rb_scan_args(argc, argv, "02", &argX, &argY);
|
537
|
-
//
|
538
|
-
// if (NIL_P(argX)) {
|
539
|
-
// rb_iv_set(self, "@x", DBL2NUM(0.0));
|
540
|
-
// } else {
|
541
|
-
// rb_iv_set(self, "@x", rb_Float(argX));
|
542
|
-
// }
|
543
|
-
// if (NIL_P(argY)) {
|
544
|
-
// rb_iv_set(self, "@y", DBL2NUM(0.0));
|
545
|
-
// } else {
|
546
|
-
// rb_iv_set(self, "@y", DBL2NUM(argY));
|
547
|
-
// }
|
548
|
-
//
|
549
|
-
// return self;
|
550
|
-
//}
|
551
|
-
//
|
552
|
-
///**
|
553
|
-
// * 座標オブジェクトの複製を初期化します.
|
554
|
-
// *
|
555
|
-
// * @param [Object] object 複製元
|
556
|
-
// * @return [void]
|
557
|
-
// */
|
558
|
-
//static VALUE AffinePoint_initializeCopy(VALUE self, VALUE argObject) {
|
559
|
-
// rb_iv_set(self, "@x", rb_iv_get(argObject, "@x"));
|
560
|
-
// rb_iv_set(self, "@y", rb_iv_get(argObject, "@y"));
|
561
|
-
// return self;
|
562
|
-
//}
|
563
|
-
///* }}} */
|
564
523
|
|
565
524
|
//----------------------------------------------------------------------------//
|
566
525
|
// 内部API実装
|
@@ -637,51 +596,14 @@ void RixmapDeformation_Init() {
|
|
637
596
|
rb_alias(cRixmapAffineMatrix, rb_intern("trans"), rb_intern("translation"));
|
638
597
|
rb_alias(cRixmapAffineMatrix, rb_intern("trans="), rb_intern("translation="));
|
639
598
|
|
640
|
-
// /**
|
641
|
-
// * Document-class: Rixmap::Deformer::AffineMatrix::Point
|
642
|
-
// *
|
643
|
-
// * アフィン変換用座標構造体.
|
644
|
-
// * FIXME 外出しするかも
|
645
|
-
// */
|
646
|
-
// cRixmapAffinePoint = rb_define_class_under(cRixmapAffineMatrix, "Point", rb_cObject);
|
647
|
-
// rb_define_private_method(cRixmapAffinePoint, "initialize", RUBY_METHOD_FUNC(AffinePoint_initialize), -1);
|
648
|
-
// rb_define_private_method(cRixmapAffinePoint, "initialize_copy", RUBY_METHOD_FUNC(AffinePoint_initializeCopy), 1);
|
649
|
-
// rb_define_attr(cRixmapAffinePoint, "x", 1, 1);
|
650
|
-
// rb_define_attr(cRixmapAffinePoint, "y", 1, 1);
|
651
|
-
//
|
652
|
-
// /**
|
653
|
-
// * Document-class: Rixmap::Deformer::AffineMatrix::Center
|
654
|
-
// *
|
655
|
-
// * アフィン変換用中央座標構造体.
|
656
|
-
// */
|
657
|
-
// cRixmapAffineCenter = rb_define_class_under(cRixmapAffineMatrix, "Center", cRixmapAffinePoint);
|
658
|
-
//
|
659
|
-
// /**
|
660
|
-
// * Document-class: Rixmap::Deformer::AffineMatrix::Scale
|
661
|
-
// *
|
662
|
-
// * アフィン変換用拡大率構造体.
|
663
|
-
// */
|
664
|
-
// cRixmapAffineScale = rb_define_class_under(cRixmapAffineMatrix, "Scale", cRixmapAffinePoint);
|
665
|
-
//
|
666
|
-
// /**
|
667
|
-
// * Document-class: Rixmap::Deformer::AffineMatrix::Translation
|
668
|
-
// *
|
669
|
-
// * アフィン変換用平行移動量構造体.
|
670
|
-
// */
|
671
|
-
// cRixmapAffineTranslation = rb_define_class_under(cRixmapAffineMatrix, "Translation", cRixmapAffinePoint);
|
672
|
-
|
673
599
|
// GCから保護しておく
|
674
600
|
rb_global_variable(&mRixmapDeformer);
|
675
601
|
rb_global_variable(&cRixmapBaseDeformer);
|
676
602
|
rb_global_variable(&cRixmapAffineDeformer);
|
677
603
|
rb_global_variable(&cRixmapAffineMatrix);
|
678
|
-
// rb_global_variable(&cRixmapAffinePoint);
|
679
|
-
// rb_global_variable(&cRixmapAffineCenter);
|
680
|
-
// rb_global_variable(&cRixmapAffineScale);
|
681
|
-
// rb_global_variable(&cRixmapAffineTranslation);
|
682
604
|
}
|
683
605
|
|
684
606
|
|
685
607
|
//============================================================================//
|
686
|
-
// $Id: rixmapdeformation.cxx,v
|
608
|
+
// $Id: rixmapdeformation.cxx,v 6e4defc69a98 2014/05/23 17:15:06 chikuchikugonzalez $
|
687
609
|
// vim: set sts=4 ts=4 sw=4 expandtab foldmethod=marker:
|
@@ -0,0 +1,501 @@
|
|
1
|
+
// -*- coding: utf-8 -*-
|
2
|
+
/**
|
3
|
+
* Rixmap実装用ヘルパー関数実装.
|
4
|
+
*/
|
5
|
+
#include "rixmaphelper.hxx"
|
6
|
+
|
7
|
+
/* Rixmap::Helper::UpdatePalette {{{ */
|
8
|
+
bool Rixmap::Helper::UpdatePalette(Rixmap::PaletteData* palette, long offset, VALUE object) {
|
9
|
+
Rixmap::Color color(0, 0, 0, 255);
|
10
|
+
|
11
|
+
// カラーオブジェクトを解析
|
12
|
+
if (RB_TYPE_P(object, T_STRING)) {
|
13
|
+
// Color.newを使ってオブジェクトを構築
|
14
|
+
VALUE objColor = rb_funcall(cRixmapColor, rb_intern("new"), 1, object);
|
15
|
+
Rixmap::ColorData* data = rixmap_unwrap<Rixmap::ColorData>(objColor);
|
16
|
+
color = data->getColor();
|
17
|
+
} else if (RTEST(rb_obj_is_kind_of(object, cRixmapColor))) {
|
18
|
+
// Rixmap::Colorそのもの
|
19
|
+
Rixmap::ColorData* data = rixmap_unwrap<Rixmap::ColorData>(object);
|
20
|
+
color = data->getColor();
|
21
|
+
} else {
|
22
|
+
// 配列から
|
23
|
+
VALUE aryColor = rb_Array(object);
|
24
|
+
long arylen = RARRAY_LEN(aryColor);
|
25
|
+
VALUE* aryptr = RARRAY_PTR(aryColor);
|
26
|
+
VALUE objColor = rb_funcall2(cRixmapColor, rb_intern("new"), arylen, aryptr);
|
27
|
+
Rixmap::ColorData* data = rixmap_unwrap<Rixmap::ColorData>(objColor);
|
28
|
+
color = data->getColor();
|
29
|
+
}
|
30
|
+
|
31
|
+
// 範囲チェック && 更新
|
32
|
+
// FIXME unsignedからsignedへの変換になってる
|
33
|
+
//long length = static_cast<long>(palette->getSize());
|
34
|
+
try {
|
35
|
+
palette->set(offset, color);
|
36
|
+
return true;
|
37
|
+
} catch (const std::out_of_range& e) {
|
38
|
+
// ( ´゚д゚`)エー
|
39
|
+
rb_warning(e.what());
|
40
|
+
return false;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
/* }}} */
|
44
|
+
/* Rixmap::Helper::LayoutChannels {{{ */
|
45
|
+
bool Rixmap::Helper::LayoutChannels(VALUE layout, Rixmap::ChannelArray& channels) {
|
46
|
+
if (NIL_P(layout)) {
|
47
|
+
return false;
|
48
|
+
}
|
49
|
+
|
50
|
+
Rixmap::ChannelArray dst;
|
51
|
+
if (RB_TYPE_P(layout, T_ARRAY)) {
|
52
|
+
// 配列の場合は各要素を文字列にして、その先頭を使う
|
53
|
+
long length = RARRAY_LEN(layout);
|
54
|
+
for (long i = 0; i < length; i++) {
|
55
|
+
VALUE item = rb_funcall(rb_String(rb_ary_entry(layout, i)), rb_intern("upcase"), 0);
|
56
|
+
long slen = RSTRING_LEN(item);
|
57
|
+
char* sptr = StringValuePtr(item);
|
58
|
+
if (slen > 0) {
|
59
|
+
// 先頭をチャンネルに
|
60
|
+
Rixmap::Channel channel = static_cast<Rixmap::Channel>(sptr[0]);
|
61
|
+
dst.push_back(channel);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
} else {
|
65
|
+
// 配列以外は文字列として扱い、各文字を使う
|
66
|
+
VALUE str = rb_funcall(rb_String(layout), rb_intern("upcase"), 0);
|
67
|
+
long slen = RSTRING_LEN(str);
|
68
|
+
char* sptr = StringValuePtr(str);
|
69
|
+
for (long i = 0; i < slen; i++) {
|
70
|
+
Rixmap::Channel channel = static_cast<Rixmap::Channel>(sptr[i]);
|
71
|
+
dst.push_back(channel);
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
// チャンネルリストが空の場合は失敗とみなす
|
76
|
+
if (dst.empty()) {
|
77
|
+
return false;
|
78
|
+
}
|
79
|
+
|
80
|
+
// 入れ替える
|
81
|
+
channels.insert(channels.end(), dst.begin(), dst.end());
|
82
|
+
return true;
|
83
|
+
}
|
84
|
+
/* }}} */
|
85
|
+
/* Rixmap::Helper::GetPixel {{{ */
|
86
|
+
VALUE Rixmap::Helper::GetPixel(Rixmap::ImageData* image, int32_t xpos, int32_t ypos) {
|
87
|
+
// TODO imageがNULLの時対策
|
88
|
+
|
89
|
+
// 範囲チェック
|
90
|
+
if (image->isOutside(xpos, ypos)) {
|
91
|
+
// 範囲外はnil
|
92
|
+
return Qnil;
|
93
|
+
}
|
94
|
+
|
95
|
+
const Rixmap::ChannelArray& channels = image->getModeInfo().getChannels();
|
96
|
+
size_t nchannel = channels.size();
|
97
|
+
|
98
|
+
if (nchannel == 0) {
|
99
|
+
// ない場合はnil
|
100
|
+
return Qnil;
|
101
|
+
} else if (nchannel == 1) {
|
102
|
+
// 一つの場合は整数値で返す
|
103
|
+
Rixmap::Channel channel = channels.at(0);
|
104
|
+
uint8_t value = image->get(channel, xpos, ypos);
|
105
|
+
return INT2FIX(value);
|
106
|
+
} else {
|
107
|
+
// それ以外は配列で返す
|
108
|
+
VALUE pixel = rb_ary_new2(nchannel);
|
109
|
+
for (size_t i = 0; i < nchannel; i++) {
|
110
|
+
Rixmap::Channel channel = channels.at(i);
|
111
|
+
uint8_t value = image->get(channel, xpos, ypos);
|
112
|
+
rb_ary_store(pixel, i, INT2FIX(value));
|
113
|
+
}
|
114
|
+
return pixel;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
/* }}} */
|
118
|
+
/* Rixmap::Helper::UpdatePixel {{{ */
|
119
|
+
void Rixmap::Helper::UpdatePixel(Rixmap::ImageData* image, int32_t xpos, int32_t ypos, VALUE pixel) {
|
120
|
+
// TODO imageがNULLの時対策
|
121
|
+
const Rixmap::ModeInfo& mode = image->getModeInfo();
|
122
|
+
|
123
|
+
// 範囲チェック
|
124
|
+
if (image->isInside(xpos, ypos)) {
|
125
|
+
if (RB_TYPE_P(pixel, T_ARRAY)) {
|
126
|
+
// 配列
|
127
|
+
const Rixmap::ChannelArray& channels = mode.getChannels();
|
128
|
+
for (size_t i = 0; i < channels.size(); i++) {
|
129
|
+
Rixmap::Channel channel = channels.at(i);
|
130
|
+
VALUE objItem = rb_ary_entry(pixel, i);
|
131
|
+
if (!NIL_P(objItem)) {
|
132
|
+
int value = ROUND2BYTE(NUM2INT(rb_Integer(objItem)));
|
133
|
+
image->set(channel, xpos, ypos, static_cast<uint8_t>(value));
|
134
|
+
}
|
135
|
+
}
|
136
|
+
} else if (RB_TYPE_P(pixel, T_FIXNUM) || RB_TYPE_P(pixel, T_FLOAT)) {
|
137
|
+
//} else if (RB_TYPE_P(pixel, T_FIXNUM) /* || RB_TYPE_P(pixel, T_BIGNUM) */) {
|
138
|
+
// 数値
|
139
|
+
int value = ROUND2BYTE(NUM2INT(rb_Integer(pixel)));
|
140
|
+
const Rixmap::ChannelArray& channels = mode.getChannels();
|
141
|
+
for (auto it = channels.begin(); it != channels.end(); it++) {
|
142
|
+
image->set(*it, xpos, ypos, static_cast<uint8_t>(value));
|
143
|
+
}
|
144
|
+
} else if (RTEST(rb_obj_is_kind_of(pixel, cRixmapColor))) {
|
145
|
+
// カラーオブジェクト
|
146
|
+
Rixmap::ColorData* col = rixmap_unwrap<Rixmap::ColorData>(pixel);
|
147
|
+
switch (mode.getType()) {
|
148
|
+
case Rixmap::MODE_TYPE_INDEXED:
|
149
|
+
{
|
150
|
+
const Rixmap::PaletteData* pal = image->getPaletteData();
|
151
|
+
size_t off = 0;
|
152
|
+
if (pal == NULL) {
|
153
|
+
off = 0;
|
154
|
+
} else {
|
155
|
+
off = pal->closest(col->getColor());
|
156
|
+
}
|
157
|
+
image->set(Rixmap::Channel::PALETTE, xpos, ypos, static_cast<uint8_t>(off));
|
158
|
+
}
|
159
|
+
break;
|
160
|
+
|
161
|
+
case Rixmap::MODE_TYPE_GRAYSCALE:
|
162
|
+
image->set(Rixmap::Channel::LUMINANCE, xpos, ypos, col->getLuminance());
|
163
|
+
break;
|
164
|
+
|
165
|
+
case Rixmap::MODE_TYPE_RGB:
|
166
|
+
image->set(Rixmap::Channel::RED, xpos, ypos, col->getRed());
|
167
|
+
image->set(Rixmap::Channel::GREEN, xpos, ypos, col->getGreen());
|
168
|
+
image->set(Rixmap::Channel::BLUE, xpos, ypos, col->getBlue());
|
169
|
+
break;
|
170
|
+
|
171
|
+
default:
|
172
|
+
// DO NOTHING
|
173
|
+
break;
|
174
|
+
}
|
175
|
+
|
176
|
+
if (mode.hasAlpha()) {
|
177
|
+
image->set(Rixmap::Channel::ALPHA, xpos, ypos, col->getAlpha());
|
178
|
+
}
|
179
|
+
} else {
|
180
|
+
// 非対応(`・ω・´)
|
181
|
+
rb_raise(rb_eArgError, "unexpected pixel data type: %s", rb_obj_classname(pixel));
|
182
|
+
}
|
183
|
+
} else {
|
184
|
+
// 範囲外は何もしないお
|
185
|
+
rb_warning("point (%d, %d) is outside of image", xpos, ypos);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
/* }}} */
|
189
|
+
/* Rixmap::Helper::GetBand {{{ */
|
190
|
+
VALUE Rixmap::Helper::GetBand(Rixmap::ImageLineData* line, Rixmap::Channel channel) {
|
191
|
+
if (line->isValid()) {
|
192
|
+
Rixmap::ImageData* parent = line->getImageData();
|
193
|
+
const Rixmap::ModeInfo& mode = parent->getModeInfo();
|
194
|
+
if (mode.has(channel)) {
|
195
|
+
int32_t length = line->getLength();
|
196
|
+
int32_t lineno = line->getLineNumber();
|
197
|
+
uint8_t* band = parent->get(channel, lineno);
|
198
|
+
VALUE bytes = rb_ary_new2(length);
|
199
|
+
for (int32_t i = 0; i < length; i++) {
|
200
|
+
rb_ary_store(bytes, i, INT2FIX(band[i]));
|
201
|
+
}
|
202
|
+
return bytes;
|
203
|
+
} else {
|
204
|
+
return Qnil;
|
205
|
+
}
|
206
|
+
} else {
|
207
|
+
return Qnil;
|
208
|
+
}
|
209
|
+
}
|
210
|
+
/* }}} */
|
211
|
+
/* Rixmap::Helper::UpdateBand {{{ */
|
212
|
+
bool Rixmap::Helper::UpdateBand(Rixmap::ImageLineData* line, Rixmap::Channel channel, VALUE argBand) {
|
213
|
+
if (line->isValid()) {
|
214
|
+
Rixmap::ImageData* parent = line->getImageData();
|
215
|
+
const Rixmap::ModeInfo& mode = parent->getModeInfo();
|
216
|
+
int32_t lineLength = line->getLength();
|
217
|
+
int32_t lineno = line->getLineNumber();
|
218
|
+
if (mode.has(channel)) {
|
219
|
+
// 型ごとにチェックして処理
|
220
|
+
if (RB_TYPE_P(argBand, T_ARRAY)) {
|
221
|
+
// 配列の場合はいったん全要素を調べる
|
222
|
+
long aryLength = RARRAY_LEN(argBand);
|
223
|
+
int32_t length = (aryLength < lineLength) ? aryLength : lineLength;
|
224
|
+
for (int32_t i = 0; i < length; i++) {
|
225
|
+
VALUE item = rb_ary_entry(argBand, i);
|
226
|
+
if (!RB_TYPE_P(item, T_FIXNUM)) {
|
227
|
+
rb_raise(rb_eArgError, "unexpected band data type in line data: %s", rb_obj_classname(item));
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
// OK
|
232
|
+
for (int32_t i = 0; i < length; i++) {
|
233
|
+
VALUE item = rb_ary_entry(argBand, i);
|
234
|
+
int byte = FIX2INT(item);
|
235
|
+
parent->set(channel, i, lineno, static_cast<uint8_t>(byte));
|
236
|
+
}
|
237
|
+
} else {
|
238
|
+
VALUE objBand = rb_String(argBand);
|
239
|
+
long nbyte = RSTRING_LEN(objBand);
|
240
|
+
char* bytes = StringValuePtr(objBand);
|
241
|
+
int32_t length = (nbyte < lineLength) ? nbyte : lineLength;
|
242
|
+
for (int32_t i = 0; i < length; i++) {
|
243
|
+
parent->set(channel, i, lineno, static_cast<uint8_t>(bytes[i]));
|
244
|
+
}
|
245
|
+
}
|
246
|
+
return true;
|
247
|
+
} else {
|
248
|
+
rb_warning("channel %c is not supported of this line", static_cast<char>(channel));
|
249
|
+
return false;
|
250
|
+
}
|
251
|
+
} else {
|
252
|
+
rb_warning("line is not valid");
|
253
|
+
return false;
|
254
|
+
}
|
255
|
+
}
|
256
|
+
/* }}} */
|
257
|
+
/* Rixmap::Helper::GetImageConverter {{{ */
|
258
|
+
Rixmap::Converter* Rixmap::Helper::GetImageConverter(const Rixmap::Mode input, const Rixmap::Mode output) {
|
259
|
+
// コンバータオブジェクト
|
260
|
+
// FIXME これ大丈夫かしら
|
261
|
+
static Rixmap::RGB2GrayScaleConverter rgb2gray;
|
262
|
+
static Rixmap::RGB2IndexConverter rgb2index;
|
263
|
+
static Rixmap::GrayScale2RGBConverter gray2rgb;
|
264
|
+
static Rixmap::GrayScale2IndexConverter gray2index;
|
265
|
+
static Rixmap::Index2RGBConverter index2rgb;
|
266
|
+
static Rixmap::Index2GrayScaleConverter index2gray;
|
267
|
+
|
268
|
+
// チャンネル増減
|
269
|
+
static Rixmap::RGB2RGBConverter rgb2rgb;
|
270
|
+
static Rixmap::GrayScale2RGBConverter gray2gray;
|
271
|
+
static Rixmap::Index2IndexConverter index2index;
|
272
|
+
|
273
|
+
// 判別処理
|
274
|
+
switch (input) {
|
275
|
+
case Rixmap::Mode::INDEXED:
|
276
|
+
switch (output) {
|
277
|
+
case Rixmap::Mode::INDEXED:
|
278
|
+
return &index2index;
|
279
|
+
|
280
|
+
case Rixmap::Mode::RGB:
|
281
|
+
case Rixmap::Mode::RGBA:
|
282
|
+
return &index2rgb;
|
283
|
+
|
284
|
+
case Rixmap::Mode::GRAYSCALE:
|
285
|
+
case Rixmap::Mode::GRAYALPHA:
|
286
|
+
return &index2gray;
|
287
|
+
|
288
|
+
default:
|
289
|
+
// 何もできない
|
290
|
+
// (警告抑制)
|
291
|
+
break;
|
292
|
+
}
|
293
|
+
break;
|
294
|
+
|
295
|
+
case Rixmap::Mode::RGB:
|
296
|
+
case Rixmap::Mode::RGBA:
|
297
|
+
switch (output) {
|
298
|
+
case Rixmap::Mode::RGB:
|
299
|
+
case Rixmap::Mode::RGBA:
|
300
|
+
return &rgb2rgb;
|
301
|
+
|
302
|
+
case Rixmap::Mode::GRAYSCALE:
|
303
|
+
case Rixmap::Mode::GRAYALPHA:
|
304
|
+
return &rgb2gray;
|
305
|
+
|
306
|
+
case Rixmap::Mode::INDEXED:
|
307
|
+
return &rgb2index;
|
308
|
+
|
309
|
+
default:
|
310
|
+
// 何もできない
|
311
|
+
// (警告抑制)
|
312
|
+
break;
|
313
|
+
}
|
314
|
+
break;
|
315
|
+
|
316
|
+
case Rixmap::Mode::GRAYSCALE:
|
317
|
+
case Rixmap::Mode::GRAYALPHA:
|
318
|
+
switch (output) {
|
319
|
+
case Rixmap::Mode::GRAYSCALE:
|
320
|
+
case Rixmap::Mode::GRAYALPHA:
|
321
|
+
return &gray2gray;
|
322
|
+
|
323
|
+
case Rixmap::Mode::RGB:
|
324
|
+
case Rixmap::Mode::RGBA:
|
325
|
+
return &gray2rgb;
|
326
|
+
|
327
|
+
case Rixmap::Mode::INDEXED:
|
328
|
+
return &gray2index;
|
329
|
+
|
330
|
+
default:
|
331
|
+
// 何もできない
|
332
|
+
// (警告抑制)
|
333
|
+
break;
|
334
|
+
}
|
335
|
+
break;
|
336
|
+
|
337
|
+
default:
|
338
|
+
// 何もできない
|
339
|
+
// (警告抑制)
|
340
|
+
break;
|
341
|
+
}
|
342
|
+
|
343
|
+
// 見つからない
|
344
|
+
std::ostringstream err;
|
345
|
+
err << "image converter between "
|
346
|
+
<< Rixmap::ModeInfo::GetModeName(input) << " and "
|
347
|
+
<< Rixmap::ModeInfo::GetModeName(output) << " is not implemented.";
|
348
|
+
throw std::invalid_argument(err.str());
|
349
|
+
}
|
350
|
+
/* }}} */
|
351
|
+
/* Rixmap::Helper::GetBackgroundValue {{{ */
|
352
|
+
VALUE Rixmap::Helper::GetBackgroundValue(const Rixmap::ImageData& image, const Rixmap::BackgroundColor& bg) {
|
353
|
+
const Rixmap::ModeInfo& mode = image.getModeInfo();
|
354
|
+
if (bg.isDisabled()) {
|
355
|
+
// 無効な場合はnil
|
356
|
+
return Qnil;
|
357
|
+
}
|
358
|
+
|
359
|
+
if (mode.isIndexedType()) {
|
360
|
+
// パレット番号
|
361
|
+
return INT2FIX(bg.getPalette());
|
362
|
+
} else if (mode.isGrayScaleType()) {
|
363
|
+
// 輝度値
|
364
|
+
return INT2FIX(bg.getLuminance());
|
365
|
+
} else if (mode.isRGBType()) {
|
366
|
+
// Color Poolから拾う
|
367
|
+
Rixmap::Color color(bg.getRed(), bg.getGreen(), bg.getBlue());
|
368
|
+
return RixmapColorPool::Get(color);
|
369
|
+
} else {
|
370
|
+
return Qnil;
|
371
|
+
}
|
372
|
+
}
|
373
|
+
/* }}} */
|
374
|
+
/* Rixmap::Helper::GetBackgroundAsColor {{{ */
|
375
|
+
VALUE Rixmap::Helper::GetBackgroundAsColor(const Rixmap::ImageData& image, const Rixmap::BackgroundColor& bg) {
|
376
|
+
Rixmap::Color color;
|
377
|
+
const Rixmap::ModeInfo& mode = image.getModeInfo();
|
378
|
+
if (bg.isDisabled()) {
|
379
|
+
// 無効な場合はnil
|
380
|
+
return Qnil;
|
381
|
+
}
|
382
|
+
|
383
|
+
if (mode.isIndexedType()) {
|
384
|
+
color = image.getPaletteData()->get(bg.getPalette());
|
385
|
+
} else if (mode.isGrayScaleType()) {
|
386
|
+
color.setLuminance(bg.getLuminance());
|
387
|
+
} else if (mode.isRGBType()) {
|
388
|
+
color.setRed(bg.getRed());
|
389
|
+
color.setGreen(bg.getGreen());
|
390
|
+
color.setBlue(bg.getBlue());
|
391
|
+
} else {
|
392
|
+
return Qnil;
|
393
|
+
}
|
394
|
+
|
395
|
+
return RixmapColorPool::Get(color);
|
396
|
+
}
|
397
|
+
/* }}} */
|
398
|
+
/* Rixmap::Helper::SetBackgroundValue {{{ */
|
399
|
+
bool Rixmap::Helper::SetBackgroundValue(const Rixmap::ImageData& image, Rixmap::BackgroundColor& bg, VALUE value) {
|
400
|
+
const Rixmap::ModeInfo& mode = image.getModeInfo();
|
401
|
+
if (RTEST(value)) {
|
402
|
+
if (RB_TYPE_P(value, T_TRUE)) {
|
403
|
+
bg.enable();
|
404
|
+
return true;
|
405
|
+
} else if (RB_TYPE_P(value, T_FIXNUM)) {
|
406
|
+
uint8_t v = static_cast<uint8_t>(FIX2INT(value));
|
407
|
+
if (mode.isIndexedType()) {
|
408
|
+
bg.setPalette(v);
|
409
|
+
const Rixmap::PaletteData* palette = image.getPaletteData();
|
410
|
+
if (palette != NULL) {
|
411
|
+
const Rixmap::Color& color = palette->get(v);
|
412
|
+
bg.setRed(color.getRed());
|
413
|
+
bg.setGreen(color.getGreen());
|
414
|
+
bg.setBlue(color.getBlue());
|
415
|
+
}
|
416
|
+
} else if (mode.isGrayScaleType()) {
|
417
|
+
bg.setLuminance(v);
|
418
|
+
bg.setRed(v);
|
419
|
+
bg.setGreen(v);
|
420
|
+
bg.setBlue(v);
|
421
|
+
} else {
|
422
|
+
// RGBの場合はエラーになる
|
423
|
+
rb_raise(rb_eArgError, "'%s' is unexpected value type for %s image.", rb_obj_classname(value), Rixmap::ModeInfo::GetModeName(mode.getMode()).c_str());
|
424
|
+
return false;
|
425
|
+
}
|
426
|
+
bg.enable();
|
427
|
+
return true;
|
428
|
+
} else if (RB_TYPE_P(value, T_ARRAY) || RTEST(rb_obj_is_kind_of(value, cRixmapColor))) {
|
429
|
+
Rixmap::ColorData* color = NULL;
|
430
|
+
|
431
|
+
// 色要素の取得
|
432
|
+
if (RB_TYPE_P(value, T_ARRAY)) {
|
433
|
+
// 配列の場合、それを引数にColorを作る
|
434
|
+
VALUE ary = rb_Array(value);
|
435
|
+
long arySize = RARRAY_LEN(ary);
|
436
|
+
VALUE* aryPtr = RARRAY_PTR(ary);
|
437
|
+
VALUE objColor = rb_funcall2(cRixmapColor, rb_intern("new"), arySize, aryPtr);
|
438
|
+
color = rixmap_unwrap<Rixmap::ColorData>(objColor);
|
439
|
+
} else {
|
440
|
+
color = rixmap_unwrap<Rixmap::ColorData>(value);
|
441
|
+
}
|
442
|
+
|
443
|
+
if (mode.isIndexedType()) {
|
444
|
+
// 最も近い色を探す
|
445
|
+
uint8_t offset = static_cast<uint8_t>(image.getPaletteData()->closest(color->getColor()));
|
446
|
+
bg.setPalette(offset);
|
447
|
+
|
448
|
+
// RGB値も保存
|
449
|
+
bg.setRed(color->getRed());
|
450
|
+
bg.setGreen(color->getGreen());
|
451
|
+
bg.setBlue(color->getBlue());
|
452
|
+
} else if (mode.isGrayScaleType()) {
|
453
|
+
// 輝度値を入れる
|
454
|
+
bg.setLuminance(color->getLuminance());
|
455
|
+
|
456
|
+
// RGB値も保存
|
457
|
+
bg.setRed(color->getRed());
|
458
|
+
bg.setGreen(color->getGreen());
|
459
|
+
bg.setBlue(color->getBlue());
|
460
|
+
} else if (mode.isRGBType()) {
|
461
|
+
// パレットはなし (0)
|
462
|
+
bg.setPalette(0);
|
463
|
+
|
464
|
+
// 輝度値は計算する
|
465
|
+
bg.setLuminance(color->getLuminance());
|
466
|
+
|
467
|
+
// RGBの各要素を使う
|
468
|
+
bg.setRed(color->getRed());
|
469
|
+
bg.setGreen(color->getGreen());
|
470
|
+
bg.setBlue(color->getBlue());
|
471
|
+
} else {
|
472
|
+
rb_raise(rb_eArgError, "'%s' is unexpected value type for %s image.", rb_obj_classname(value), Rixmap::ModeInfo::GetModeName(mode.getMode()).c_str());
|
473
|
+
return false;
|
474
|
+
}
|
475
|
+
bg.enable();
|
476
|
+
return true;
|
477
|
+
}
|
478
|
+
|
479
|
+
// ここに来た場合はエラーにする
|
480
|
+
rb_raise(rb_eArgError, "'%s' is unexpected value type for %s image.", rb_obj_classname(value), Rixmap::ModeInfo::GetModeName(mode.getMode()).c_str());
|
481
|
+
return false;
|
482
|
+
} else {
|
483
|
+
bg.disable();
|
484
|
+
return false;
|
485
|
+
}
|
486
|
+
}
|
487
|
+
/* }}} */
|
488
|
+
/* Rixmap::Helper::GetImageMetadata {{{ */
|
489
|
+
VALUE Rixmap::Helper::GetImageMetadata(const Rixmap::ImageData& image) {
|
490
|
+
VALUE metadata = rb_hash_new();
|
491
|
+
rb_hash_aset(metadata, ID2SYM(rb_intern("palette")), image.getPalette());
|
492
|
+
rb_hash_aset(metadata, ID2SYM(rb_intern("background")), GetBackgroundAsColor(image, image.getBackground()));
|
493
|
+
rb_hash_aset(metadata, ID2SYM(rb_intern("transparent")), GetBackgroundAsColor(image, image.getTransparent()));
|
494
|
+
return metadata;
|
495
|
+
}
|
496
|
+
/* }}} */
|
497
|
+
|
498
|
+
|
499
|
+
//============================================================================//
|
500
|
+
// $Id: rixmaphelper.cxx,v 5590f3c64493 2014/05/31 14:59:34 chikuchikugonzalez $
|
501
|
+
// vim: set sts=4 ts=4 sw=4 expandtab foldmethod=marker:
|