rixmap 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: