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.
@@ -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 dstImageObject = RixmapImage_NewInstance(ipo->getPreferredMode(), newWidth, newHeight, srcImage->getMetadata());
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 753dbf70cab3 2014/05/16 16:13:38 chikuchikugonzalez $
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: