rixmap 0.1.1 → 0.2.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.
data/src/rixmapcore.cxx CHANGED
@@ -3,6 +3,7 @@
3
3
  * Rixmapコア実装.
4
4
  */
5
5
  #include "rixmapcore.hxx"
6
+ #include "rixmap/helper.hxx"
6
7
 
7
8
  //----------------------------------------------------------------------------//
8
9
  // オブジェクトプール実装
@@ -110,212 +111,6 @@ VALUE cRixmapPalette = Qnil;
110
111
  VALUE cRixmapImage = Qnil;
111
112
  VALUE cRixmapImageLine = Qnil;
112
113
 
113
- //----------------------------------------------------------------------------//
114
- // ヘルパー関数
115
- //----------------------------------------------------------------------------//
116
- namespace RixmapHelper {/*{{{*/
117
- /**
118
- * 指定色数のパレットを作成します.
119
- */
120
- static VALUE CreatePalette(size_t size = 256) {
121
- VALUE args[1] = {
122
- ULONG2NUM(size)
123
- };
124
- return rb_class_new_instance(1, args, cRixmapPalette);
125
- }
126
-
127
- /**
128
- * スキャンラインオブジェクトを作成します.
129
- */
130
- static VALUE CreateImageLine(VALUE image, int32_t lineno) {
131
- VALUE args[2] = {
132
- image,
133
- LONG2NUM(lineno)
134
- };
135
- return rb_class_new_instance(2, args, cRixmapImageLine);
136
- }
137
-
138
- /**
139
- * ピクセルを取得します.
140
- */
141
- static VALUE GetPixel(Rixmap::ImageData* image, int32_t xpos, int32_t ypos) {
142
- // TODO imageがNULLの時対策
143
-
144
- // 範囲チェック
145
- if (image->isOutside(xpos, ypos)) {
146
- // 範囲外はnil
147
- return Qnil;
148
- }
149
-
150
- const Rixmap::ChannelArray& channels = image->getModeInfo().getChannels();
151
- size_t nchannel = channels.size();
152
-
153
- if (nchannel == 0) {
154
- // ない場合はnil
155
- return Qnil;
156
- } else if (nchannel == 1) {
157
- // 一つの場合は整数値で返す
158
- Rixmap::Channel channel = channels.at(0);
159
- uint8_t value = image->get(channel, xpos, ypos);
160
- return INT2FIX(value);
161
- } else {
162
- // それ以外は配列で返す
163
- VALUE pixel = rb_ary_new2(nchannel);
164
- for (size_t i = 0; i < nchannel; i++) {
165
- Rixmap::Channel channel = channels.at(i);
166
- uint8_t value = image->get(channel, xpos, ypos);
167
- rb_ary_store(pixel, i, INT2FIX(value));
168
- }
169
- return pixel;
170
- }
171
- }
172
-
173
- /**
174
- * ピクセルを更新します.
175
- */
176
- static void UpdatePixel(Rixmap::ImageData* image, int32_t xpos, int32_t ypos, VALUE pixel) {
177
- // TODO imageがNULLの時対策
178
- const Rixmap::ModeInfo& mode = image->getModeInfo();
179
-
180
- // 範囲チェック
181
- if (image->isInside(xpos, ypos)) {
182
- if (RB_TYPE_P(pixel, T_ARRAY)) {
183
- // 配列
184
- const Rixmap::ChannelArray& channels = mode.getChannels();
185
- for (size_t i = 0; i < channels.size(); i++) {
186
- Rixmap::Channel channel = channels.at(i);
187
- VALUE objItem = rb_ary_entry(pixel, i);
188
- if (!NIL_P(objItem)) {
189
- int value = ROUND2BYTE(NUM2INT(rb_Integer(objItem)));
190
- image->set(channel, xpos, ypos, static_cast<uint8_t>(value));
191
- }
192
- }
193
- } else if (RB_TYPE_P(pixel, T_FIXNUM) || RB_TYPE_P(pixel, T_FLOAT)) {
194
- //} else if (RB_TYPE_P(pixel, T_FIXNUM) /* || RB_TYPE_P(pixel, T_BIGNUM) */) {
195
- // 数値
196
- int value = ROUND2BYTE(NUM2INT(rb_Integer(pixel)));
197
- const Rixmap::ChannelArray& channels = mode.getChannels();
198
- for (auto it = channels.begin(); it != channels.end(); it++) {
199
- image->set(*it, xpos, ypos, static_cast<uint8_t>(value));
200
- }
201
- } else if (RTEST(rb_obj_is_kind_of(pixel, cRixmapColor))) {
202
- // カラーオブジェクト
203
- Rixmap::ColorData* col = rixmap_unwrap<Rixmap::ColorData>(pixel);
204
- switch (mode.getType()) {
205
- case Rixmap::MODE_TYPE_INDEXED:
206
- {
207
- const Rixmap::PaletteData* pal = image->getPaletteData();
208
- size_t off = 0;
209
- if (pal == NULL) {
210
- off = 0;
211
- } else {
212
- off = pal->closest(col->getColor());
213
- }
214
- image->set(Rixmap::Channel::PALETTE, xpos, ypos, static_cast<uint8_t>(off));
215
- }
216
- break;
217
-
218
- case Rixmap::MODE_TYPE_GRAYSCALE:
219
- image->set(Rixmap::Channel::LUMINANCE, xpos, ypos, col->getLuminance());
220
- break;
221
-
222
- case Rixmap::MODE_TYPE_RGB:
223
- image->set(Rixmap::Channel::RED, xpos, ypos, col->getRed());
224
- image->set(Rixmap::Channel::GREEN, xpos, ypos, col->getGreen());
225
- image->set(Rixmap::Channel::BLUE, xpos, ypos, col->getBlue());
226
- break;
227
-
228
- default:
229
- // DO NOTHING
230
- break;
231
- }
232
-
233
- if (mode.hasAlpha()) {
234
- image->set(Rixmap::Channel::ALPHA, xpos, ypos, col->getAlpha());
235
- }
236
- } else {
237
- // 非対応(`・ω・´)
238
- rb_raise(rb_eArgError, "unexpected pixel data type: %s", rb_obj_classname(pixel));
239
- }
240
- } else {
241
- // 範囲外は何もしないお
242
- rb_warning("point (%d, %d) is outside of image", xpos, ypos);
243
- }
244
- }
245
-
246
- /**
247
- * スキャンラインから指定したチャンネルのバンドデータを取得します.
248
- */
249
- static VALUE GetBand(Rixmap::ImageLineData* line, Rixmap::Channel channel) {
250
- if (line->isValid()) {
251
- Rixmap::ImageData* parent = line->getImageData();
252
- const Rixmap::ModeInfo& mode = parent->getModeInfo();
253
- if (mode.has(channel)) {
254
- int32_t length = line->getLength();
255
- int32_t lineno = line->getLineNumber();
256
- uint8_t* band = parent->get(channel, lineno);
257
- VALUE bytes = rb_ary_new2(length);
258
- for (int32_t i = 0; i < length; i++) {
259
- rb_ary_store(bytes, i, INT2FIX(band[i]));
260
- }
261
- return bytes;
262
- } else {
263
- return Qnil;
264
- }
265
- } else {
266
- return Qnil;
267
- }
268
- }
269
-
270
- /**
271
- * スキャンライン内の指定チャンネルデータを更新します.
272
- */
273
- static bool UpdateBand(Rixmap::ImageLineData* line, Rixmap::Channel channel, VALUE argBand) {
274
- if (line->isValid()) {
275
- Rixmap::ImageData* parent = line->getImageData();
276
- const Rixmap::ModeInfo& mode = parent->getModeInfo();
277
- int32_t lineLength = line->getLength();
278
- int32_t lineno = line->getLineNumber();
279
- if (mode.has(channel)) {
280
- // 型ごとにチェックして処理
281
- if (RB_TYPE_P(argBand, T_ARRAY)) {
282
- // 配列の場合はいったん全要素を調べる
283
- long aryLength = RARRAY_LEN(argBand);
284
- int32_t length = (aryLength < lineLength) ? aryLength : lineLength;
285
- for (int32_t i = 0; i < length; i++) {
286
- VALUE item = rb_ary_entry(argBand, i);
287
- if (!RB_TYPE_P(item, T_FIXNUM)) {
288
- rb_raise(rb_eArgError, "unexpected band data type in line data: %s", rb_obj_classname(item));
289
- }
290
- }
291
-
292
- // OK
293
- for (int32_t i = 0; i < length; i++) {
294
- VALUE item = rb_ary_entry(argBand, i);
295
- int byte = FIX2INT(item);
296
- parent->set(channel, i, lineno, static_cast<uint8_t>(byte));
297
- }
298
- } else {
299
- VALUE objBand = rb_String(argBand);
300
- long nbyte = RSTRING_LEN(objBand);
301
- char* bytes = StringValuePtr(objBand);
302
- int32_t length = (nbyte < lineLength) ? nbyte : lineLength;
303
- for (int32_t i = 0; i < length; i++) {
304
- parent->set(channel, i, lineno, static_cast<uint8_t>(bytes[i]));
305
- }
306
- }
307
- return true;
308
- } else {
309
- rb_warning("channel %c is not supported of this line", static_cast<char>(channel));
310
- return false;
311
- }
312
- } else {
313
- rb_warning("line is not valid");
314
- return false;
315
- }
316
- }
317
- }/*}}}*/
318
-
319
114
  //----------------------------------------------------------------------------//
320
115
  // ライブラリ実装
321
116
  //----------------------------------------------------------------------------//
@@ -1178,7 +973,7 @@ static VALUE Binary_each(VALUE self) {
1178
973
  * @return [Rixmap::Binary] self
1179
974
  * @see Array#reverse!
1180
975
  */
1181
- static VALUE Binary_reverse(VALUE self) {
976
+ static VALUE Binary_reverseSelf(VALUE self) {
1182
977
  Rixmap::BinaryData* _this = rixmap_unwrap<Rixmap::BinaryData>(self);
1183
978
  std::reverse(_this->begin(), _this->end());
1184
979
  return self;
@@ -1190,13 +985,49 @@ static VALUE Binary_reverse(VALUE self) {
1190
985
  * @return [Rixmap::Binary] 逆順に並べられたバイナリ配列
1191
986
  * @see Array#reverse
1192
987
  */
1193
- static VALUE Binary_copyReverse(VALUE self) {
988
+ static VALUE Binary_reverse(VALUE self) {
1194
989
  Rixmap::BinaryData* _this = rixmap_unwrap<Rixmap::BinaryData>(self);
1195
990
  VALUE objResult = rb_class_new_instance(0, NULL, cRixmapBinary);
1196
991
  Rixmap::BinaryData* result = rixmap_unwrap<Rixmap::BinaryData>(objResult);
1197
992
  result->insert(result->begin(), _this->rbegin(), _this->rend());
1198
993
  return objResult;
1199
994
  }
995
+
996
+ /**
997
+ * バイナリ要素の各バイトについてブロックを呼び出し、その戻り値で要素を置き換えます.
998
+ *
999
+ * @overload map!()
1000
+ * @yield [byte] バイトごとにブロックを呼び出します.
1001
+ * @yieldparam byte [Integer] バイトデータ
1002
+ * @return [Rixmap::Binary] selfを返します.
1003
+ */
1004
+ static VALUE Binary_mapSelf(VALUE self) {
1005
+ if (!rb_block_given_p()) {
1006
+ rb_raise(rb_eRuntimeError, "block parameter are required.");
1007
+ }
1008
+
1009
+ Rixmap::BinaryData* _this = rixmap_unwrap<Rixmap::BinaryData>(self);
1010
+ size_t size = _this->size();
1011
+ for (size_t i = 0; i < size; i++) {
1012
+ VALUE byte = INT2FIX(_this->at(i));
1013
+ VALUE resp = rb_yield_values(1, byte);
1014
+ rb_funcall(self, rb_intern("[]="), 2, ULONG2NUM(i), resp);
1015
+ }
1016
+ return self;
1017
+ }
1018
+
1019
+ /**
1020
+ * バイナリ要素の各バイトについてブロックを呼び出し、その戻り値で構成される新しいバイナリ配列を返します.
1021
+ *
1022
+ * @overload map()
1023
+ * @yield [byte] バイトごとにブロックを呼び出します.
1024
+ * @yieldparam byte [Integer] バイトデータ
1025
+ * @return [Rixmap::Binary] ブロックを呼び出し結果からなる新しいバイナリ配列を返します.
1026
+ */
1027
+ static VALUE Binary_map(VALUE self) {
1028
+ VALUE binary = rb_obj_clone(self);
1029
+ return rb_funcall_passing_block(binary, rb_intern("map!"), 0, NULL);
1030
+ }
1200
1031
  /* }}} */
1201
1032
  /* Rixmap::Mode {{{ */
1202
1033
  static void Mode_Free(Rixmap::ModeData* data) {
@@ -1632,7 +1463,13 @@ static VALUE Palette_initializeCopy(VALUE self, VALUE argObject) {
1632
1463
  Rixmap::PaletteData* _this = rixmap_unwrap<Rixmap::PaletteData>(self);
1633
1464
  Rixmap::PaletteData* _that = rixmap_unwrap<Rixmap::PaletteData>(argObject);
1634
1465
 
1466
+ // デフォルトカラーを複製
1635
1467
  _this->setDefaultColor(_that->getDefaultColor());
1468
+
1469
+ // 拡張する
1470
+ _this->resize(_that->getSize());
1471
+
1472
+ // カラーをコピー
1636
1473
  _this->setColors(_that->getColors());
1637
1474
 
1638
1475
  return self;
@@ -1684,28 +1521,6 @@ static VALUE Palette_offsetGet(VALUE self, VALUE argOffset) {
1684
1521
  * @see Color.new
1685
1522
  */
1686
1523
  static VALUE Palette_offsetSet(VALUE self, VALUE argOffset, VALUE argColor) {
1687
- Rixmap::Color color(0, 0, 0, 255);
1688
-
1689
- // カラーオブジェクトを解析
1690
- if (RB_TYPE_P(argColor, T_STRING)) {
1691
- // Color.newを使ってオブジェクトを構築
1692
- VALUE objColor = rb_funcall(cRixmapColor, rb_intern("new"), 1, argColor);
1693
- Rixmap::ColorData* data = rixmap_unwrap<Rixmap::ColorData>(objColor);
1694
- color = data->getColor();
1695
- } else if (RTEST(rb_obj_is_kind_of(argColor, cRixmapColor))) {
1696
- // Rixmap::Colorそのもの
1697
- Rixmap::ColorData* data = rixmap_unwrap<Rixmap::ColorData>(argColor);
1698
- color = data->getColor();
1699
- } else {
1700
- // 配列から
1701
- VALUE aryColor = rb_Array(argColor);
1702
- long arylen = RARRAY_LEN(aryColor);
1703
- VALUE* aryptr = RARRAY_PTR(aryColor);
1704
- VALUE objColor = rb_funcall2(cRixmapColor, rb_intern("new"), arylen, aryptr);
1705
- Rixmap::ColorData* data = rixmap_unwrap<Rixmap::ColorData>(objColor);
1706
- color = data->getColor();
1707
- }
1708
-
1709
1524
  // 内部データポインタ
1710
1525
  Rixmap::PaletteData* _this = rixmap_unwrap<Rixmap::PaletteData>(self);
1711
1526
 
@@ -1717,11 +1532,9 @@ static VALUE Palette_offsetSet(VALUE self, VALUE argOffset, VALUE argColor) {
1717
1532
  pos += length;
1718
1533
  }
1719
1534
 
1720
- // 範囲チェック
1721
- if (0 <= pos && pos < length) {
1722
- _this->set(pos, color);
1723
- } else {
1724
- rb_warning("offset %ld is out of range", offset);
1535
+ // 更新
1536
+ if (!Rixmap::Helper::UpdatePalette(_this, pos, argColor)) {
1537
+ rb_raise(rb_eIndexError, "offset %ld is out of range", offset);
1725
1538
  }
1726
1539
  return argColor;
1727
1540
  }
@@ -1873,6 +1686,42 @@ static VALUE Palette_each(VALUE self) {
1873
1686
  }
1874
1687
  }
1875
1688
 
1689
+ /**
1690
+ * 各要素についてブロックを呼び出し、その戻り値でパレットデータを破壊的に変更します.
1691
+ *
1692
+ * @overload map!()
1693
+ * @yield [color] 色を引数にブロックを呼び出します.
1694
+ * @yieldparam color [Rixmap::Color] カラーオブジェクト
1695
+ * @return [Rixmap::Palette] selfを返します.
1696
+ */
1697
+ static VALUE Palette_mapSelf(VALUE self) {
1698
+ if (!rb_block_given_p()) {
1699
+ rb_raise(rb_eRuntimeError, "block parameter are required.");
1700
+ }
1701
+ Rixmap::PaletteData* _this = rixmap_unwrap<Rixmap::PaletteData>(self);
1702
+ size_t size = _this->getSize();
1703
+ for (size_t i = 0; i < size; i++) {
1704
+ VALUE color = RixmapColorPool::Get(_this->at(i));
1705
+ VALUE resp = rb_yield_values(1, color);
1706
+ Rixmap::Helper::UpdatePalette(_this, i, resp);
1707
+ //rb_funcall(self, rb_intern("[]="), 2, ULONG2NUM(i), resp);
1708
+ }
1709
+ return self;
1710
+ }
1711
+
1712
+ /**
1713
+ * パレット内の各要素についてブロックを呼び出し、その戻り値からなる新しいパレットを返します.
1714
+ *
1715
+ * @overload map()
1716
+ * @yield [color] 色を引数にブロックを呼び出します.
1717
+ * @yieldparam color [Rixmap::Color] カラーオブジェクト
1718
+ * @return [Rixmap::Palette] ブロックを呼び出した結果からなるパレット
1719
+ */
1720
+ static VALUE Palette_map(VALUE self) {
1721
+ VALUE pal = rb_obj_clone(self);
1722
+ return rb_funcall_passing_block(pal, rb_intern("map!"), 0, NULL);
1723
+ }
1724
+
1876
1725
  /**
1877
1726
  * オブジェクトとしての文字列表現を返します.
1878
1727
  *
@@ -2039,7 +1888,7 @@ static VALUE Image_initialize(int argc, VALUE* argv, VALUE self) {
2039
1888
  // パレットの処置
2040
1889
  if (_this->getModeInfo().isIndexedType() && NIL_P(optPalette)) {
2041
1890
  // インデックスカラー形式でかつ、パレットが指定されてない場合は作る
2042
- optPalette = RixmapHelper::CreatePalette(256);
1891
+ optPalette = RixmapPalette_NewInstance(256);
2043
1892
  }
2044
1893
 
2045
1894
  // パレットの設定
@@ -2049,6 +1898,22 @@ static VALUE Image_initialize(int argc, VALUE* argv, VALUE self) {
2049
1898
  return self;
2050
1899
  }
2051
1900
 
1901
+ /**
1902
+ * 複製されたオブジェクトを初期化します.
1903
+ *
1904
+ * @param [Object] obj 複製元
1905
+ * @return [void]
1906
+ */
1907
+ static VALUE Image_initializeCopy(VALUE self, VALUE argObject) {
1908
+ Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
1909
+ Rixmap::ImageData* _that = rixmap_unwrap<Rixmap::ImageData>(argObject);
1910
+
1911
+ // 複製
1912
+ *_this = *_that;
1913
+
1914
+ return self;
1915
+ }
1916
+
2052
1917
  /**
2053
1918
  * 画像形式を取得します.
2054
1919
  *
@@ -2246,7 +2111,7 @@ static VALUE Image_offsetGet(int argc, VALUE* argv, VALUE self) {
2246
2111
  // [line] 形式
2247
2112
  // TODO [nil, nil] とかどうするよ
2248
2113
  long lineno = NUM2LONG(rb_Integer(arg0));
2249
- return RixmapHelper::CreateImageLine(self, lineno);
2114
+ return RixmapImageLine_NewInstance(self, lineno);
2250
2115
  } else {
2251
2116
  // [x, y] 形式ですよねー
2252
2117
  // TODO [nil, 0] とかどうするよ
@@ -2254,7 +2119,7 @@ static VALUE Image_offsetGet(int argc, VALUE* argv, VALUE self) {
2254
2119
  long ypos = NUM2LONG(rb_Integer(arg1));
2255
2120
  Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
2256
2121
 
2257
- return RixmapHelper::GetPixel(_this, xpos, ypos);
2122
+ return Rixmap::Helper::GetPixel(_this, xpos, ypos);
2258
2123
  }
2259
2124
  }
2260
2125
 
@@ -2389,7 +2254,7 @@ static VALUE Image_offsetSet(int argc, VALUE* argv, VALUE self) {
2389
2254
  // 要素を更新
2390
2255
  for (int32_t i = 0; i < length; i++) {
2391
2256
  VALUE item = rb_ary_entry(argData, i);
2392
- RixmapHelper::UpdatePixel(_this, i, lineno, item);
2257
+ Rixmap::Helper::UpdatePixel(_this, i, lineno, item);
2393
2258
  }
2394
2259
  } else if (RB_TYPE_P(argData, T_STRING)) {
2395
2260
  // TODO rb_String使って強制的に文字列化する
@@ -2427,7 +2292,7 @@ static VALUE Image_offsetSet(int argc, VALUE* argv, VALUE self) {
2427
2292
  int32_t xpos = NUM2LONG(rb_Integer(argX));
2428
2293
  int32_t ypos = NUM2LONG(rb_Integer(argY));
2429
2294
 
2430
- RixmapHelper::UpdatePixel(_this, xpos, ypos, argData);
2295
+ Rixmap::Helper::UpdatePixel(_this, xpos, ypos, argData);
2431
2296
  }
2432
2297
 
2433
2298
  // 戻る
@@ -2477,7 +2342,7 @@ static VALUE Image_eachLine(VALUE self) {
2477
2342
  if (rb_block_given_p()) { // ブロック有
2478
2343
  Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
2479
2344
  for (int32_t h = 0; h < _this->getHeight(); h++) {
2480
- VALUE line = RixmapHelper::CreateImageLine(self, h);
2345
+ VALUE line = RixmapImageLine_NewInstance(self, h);
2481
2346
  rb_yield_values(1, line);
2482
2347
  }
2483
2348
  return self;
@@ -2508,7 +2373,7 @@ static VALUE Image_eachPixel(VALUE self) {
2508
2373
  Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
2509
2374
  for (int32_t h = 0; h < _this->getHeight(); h++) {
2510
2375
  for (int32_t w = 0; w < _this->getWidth(); w++) {
2511
- VALUE pixel = RixmapHelper::GetPixel(_this, w, h);
2376
+ VALUE pixel = Rixmap::Helper::GetPixel(_this, w, h);
2512
2377
  rb_yield_values(1, pixel);
2513
2378
  }
2514
2379
  }
@@ -2532,7 +2397,7 @@ static VALUE Image_getLines(VALUE self) {
2532
2397
  VALUE aryLines = rb_ary_new2(_this->getHeight());
2533
2398
 
2534
2399
  for (int32_t h = 0; h < _this->getHeight(); h++) {
2535
- VALUE line = RixmapHelper::CreateImageLine(self, h);
2400
+ VALUE line = RixmapImageLine_NewInstance(self, h);
2536
2401
  rb_ary_store(aryLines, h, line);
2537
2402
  }
2538
2403
 
@@ -2556,7 +2421,7 @@ static VALUE Image_getPixels(VALUE self) {
2556
2421
  for (int32_t h = 0; h < _this->getHeight(); h++) {
2557
2422
  VALUE aryLine = rb_ary_new2(_this->getWidth());
2558
2423
  for (int32_t w = 0; w < _this->getWidth(); w++) {
2559
- VALUE pixel = RixmapHelper::GetPixel(_this, w, h);
2424
+ VALUE pixel = Rixmap::Helper::GetPixel(_this, w, h);
2560
2425
  rb_ary_store(aryLine, w, pixel);
2561
2426
  }
2562
2427
  rb_ary_store(aryPixels, h, aryLine);
@@ -2583,6 +2448,387 @@ static VALUE Image_inspect(VALUE self) {
2583
2448
  _this->getHeight(),
2584
2449
  StringValueCStr(paletteText));
2585
2450
  }
2451
+
2452
+ /**
2453
+ * 画像形式を変換します.
2454
+ *
2455
+ * @param [Rixmap::Mode] mode 変換先の画像形式.
2456
+ * @return [Rixmap::Image] 変換された画像オブジェクト.
2457
+ */
2458
+ static VALUE Image_convert(VALUE self, VALUE argMode) {
2459
+ VALUE destImage = Qnil;
2460
+ {
2461
+ VALUE params[3] = {
2462
+ argMode,
2463
+ rb_funcall(self, rb_intern("width"), 0),
2464
+ rb_funcall(self, rb_intern("height"), 0)
2465
+ };
2466
+ destImage = rb_class_new_instance(3, params, cRixmapImage);
2467
+ }
2468
+
2469
+ // ポインタ
2470
+ Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
2471
+ Rixmap::ImageData* _dest = rixmap_unwrap<Rixmap::ImageData>(destImage);
2472
+
2473
+ // コンバータ
2474
+ try {
2475
+ Rixmap::Converter* converter = Rixmap::Helper::GetImageConverter(_this->getMode(), _dest->getMode());
2476
+ converter->convert(*_this, *_dest);
2477
+ } catch (const std::exception& e) {
2478
+ rb_raise(rb_eRuntimeError, e.what());
2479
+ }
2480
+
2481
+ return destImage;
2482
+ }
2483
+
2484
+ /**
2485
+ * 複数の色コンポーネントを含む画像を、各コンポーネント毎のグレースケール形式画像に分解します.
2486
+ *
2487
+ * 変換ルールとしてはインデックスカラー形式のみ、そのまま返されます.
2488
+ * それ以外は`R`, `G`, `B`, `L`, `A`の各色のみを含むグレースケール形式になります.
2489
+ *
2490
+ * @return [Array<Rixmap::Image>] 色コンポーネント単位のグレースケール形式画像配列
2491
+ */
2492
+ static VALUE Image_split(VALUE self) {
2493
+ Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
2494
+ const Rixmap::ModeInfo& _mode = _this->getModeInfo();
2495
+
2496
+ VALUE planes = rb_ary_new();
2497
+ if (_mode.isIndexedType()) {
2498
+ rb_ary_push(planes, self);
2499
+ } else {
2500
+ int32_t _width = _this->getWidth();
2501
+ int32_t _height = _this->getHeight();
2502
+ const Rixmap::ChannelArray& _channels = _mode.getChannels();
2503
+ for (auto it = _channels.begin(); it != _channels.end(); it++) {
2504
+ Rixmap::Channel channel = *it;
2505
+
2506
+ // グレースケール画像を作成
2507
+ VALUE plane = RixmapImage_NewInstance(Rixmap::Mode::GRAYSCALE, _width, _height);
2508
+ Rixmap::ImageData* data = rixmap_unwrap<Rixmap::ImageData>(plane);
2509
+
2510
+ for (int32_t h = 0; h < _height; h++) {
2511
+ for (int32_t w = 0; w < _width; w++) {
2512
+ data->set(Rixmap::Channel::LUMINANCE, w, h, _this->get(channel, w, h));
2513
+ }
2514
+ }
2515
+
2516
+ rb_ary_push(planes, plane);
2517
+ }
2518
+ }
2519
+
2520
+ return planes;
2521
+ }
2522
+
2523
+ /**
2524
+ * 画像を指定色で破壊的に塗りつぶします.
2525
+ *
2526
+ * @overload fill!(color)
2527
+ * 画像全体を`color`で塗りつぶします.
2528
+ *
2529
+ * やることをは `#fill!(color, 0, 0, width - 1, height - 1)` と同じです.
2530
+ *
2531
+ * @param [Array<Integer>,Integer,Rixmap::Color] color
2532
+ * 設定する色.
2533
+ * 配列または{Rixmap::Color}で指定します.
2534
+ * また、グレースケール形式とインデックスカラー形式の場合は整数値も使えます.
2535
+ * その場合は輝度値またはパレットインデックスです.
2536
+ *
2537
+ * @return [Rixmap::Image] selfを返します
2538
+ *
2539
+ * @overload fill!(color, left, top, right, bottom)
2540
+ * (left, top) を左上とし、(right, bottom) を右下とした領域を`color`で塗りつぶします.
2541
+ *
2542
+ * @param [Array<Integer>,Integer,Rixmap::Color] color 塗りつぶし色
2543
+ * @param [Integer] left 塗りつぶす領域の左側位置
2544
+ * @param [Integer] top 塗りつぶす領域の上側位置
2545
+ * @param [Integer] right 塗りつぶす領域の右側位置
2546
+ * @param [Integer] bottom 塗りつぶす領域の下側位置
2547
+ * @return [Rixmap::Image] selfを返します
2548
+ */
2549
+ static VALUE Image_fillSelf(int argc, VALUE* argv, VALUE self) {
2550
+ VALUE argColor = Qnil;
2551
+
2552
+ // 領域
2553
+ int32_t left = 0, top = 0, right = 0, bottom = 0;
2554
+
2555
+ // 自分
2556
+ Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
2557
+
2558
+ switch (argc) {
2559
+ case 1: // fill!(color)
2560
+ argColor = argv[0];
2561
+ left = 0;
2562
+ top = 0;
2563
+ right = _this->getWidth() - 1;
2564
+ bottom = _this->getHeight() - 1;
2565
+ break;
2566
+
2567
+ case 5: // fille!(color, left, top, right, bottom)
2568
+ argColor = argv[0];
2569
+ left = NUM2LONG(rb_Integer(argv[1]));
2570
+ top = NUM2LONG(rb_Integer(argv[2]));
2571
+ right = NUM2LONG(rb_Integer(argv[3]));
2572
+ bottom = NUM2LONG(rb_Integer(argv[4]));
2573
+
2574
+ // 補正
2575
+ if (left < 0) {
2576
+ left = 0;
2577
+ }
2578
+ if (top < 0) {
2579
+ top = 0;
2580
+ }
2581
+ if (right >= _this->getWidth()) {
2582
+ right = _this->getWidth() - 1;
2583
+ }
2584
+ if (bottom >= _this->getHeight()) {
2585
+ bottom = _this->getHeight() - 1;
2586
+ }
2587
+ break;
2588
+
2589
+ default:
2590
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 5)", argc);
2591
+ break;
2592
+ }
2593
+
2594
+ // 更新
2595
+ for (int32_t h = top; h <= bottom; h++) {
2596
+ for (int32_t w = left; w <= right; w++) {
2597
+ Rixmap::Helper::UpdatePixel(_this, w, h, argColor);
2598
+ }
2599
+ }
2600
+
2601
+ return self;
2602
+ }
2603
+
2604
+ /**
2605
+ * 指定色で塗りつぶした画像を返します.
2606
+ *
2607
+ * @see #fill!
2608
+ */
2609
+ static VALUE Image_fill(int argc, VALUE* argv, VALUE self) {
2610
+ VALUE image = rb_obj_clone(self);
2611
+ rb_funcall2(image, rb_intern("fill!"), argc, argv);
2612
+ return image;
2613
+ }
2614
+
2615
+ /**
2616
+ * この画像を指定領域の部分画像に切り詰めます.
2617
+ * オブジェクト自体を破壊的に変更します.
2618
+ *
2619
+ * @param [Integer] left 切り出す領域の左端位置
2620
+ * @param [Integer] top 切り出す領域の上端位置
2621
+ * @param [Integer] right 切り出す領域の右端位置
2622
+ * @param [Integer] bottom 切り出す領域の下端位置
2623
+ * @return [Rixmap::Image] 切り詰められたself自身.
2624
+ * 画像サイズは (right - left + 1, bottom - top + 1) になります.
2625
+ */
2626
+ static VALUE Image_cropSelf(VALUE self, VALUE argLeft, VALUE argTop, VALUE argRight, VALUE argBottom) {
2627
+ // 自分
2628
+ Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
2629
+
2630
+ // 複製を取得
2631
+ VALUE croppedImage = rb_funcall(self, rb_intern("crop"), 4, argLeft, argTop, argRight, argBottom);
2632
+
2633
+ // 自分へ移動
2634
+ Rixmap::ImageData* cropped = rixmap_unwrap<Rixmap::ImageData>(croppedImage);
2635
+ *_this = *cropped;
2636
+
2637
+ // 自分を戻す
2638
+ return self;
2639
+ }
2640
+
2641
+ /**
2642
+ * 指定領域の部分画像を取得します.
2643
+ *
2644
+ * @param [Integer] left 切り出す領域の左端位置
2645
+ * @param [Integer] top 切り出す領域の上端位置
2646
+ * @param [Integer] right 切り出す領域の右端位置
2647
+ * @param [Integer] bottom 切り出す領域の下端位置
2648
+ * @return [Rixmap::Image] 指定領域内のピクセルから構成される部分画像.
2649
+ * 画像サイズは (right - left + 1, bottom - top + 1) になります.
2650
+ */
2651
+ static VALUE Image_crop(VALUE self, VALUE argLeft, VALUE argTop, VALUE argRight, VALUE argBottom) {
2652
+ // 自分
2653
+ Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
2654
+
2655
+ // 領域決定
2656
+ int32_t left = NUM2LONG(rb_Integer(argLeft));
2657
+ int32_t top = NUM2LONG(rb_Integer(argTop));
2658
+ int32_t right = NUM2LONG(rb_Integer(argRight));
2659
+ int32_t bottom = NUM2LONG(rb_Integer(argBottom));
2660
+
2661
+ // チェック
2662
+ if (left >= right) {
2663
+ rb_raise(rb_eArgError, "left edge is over right edge: %d < %d is not valid.", left, right);
2664
+ }
2665
+ if (top >= bottom) {
2666
+ rb_raise(rb_eArgError, "top edge is over bottom edge: %d < %d is not valid.", top, bottom);
2667
+ }
2668
+
2669
+ // 幅
2670
+ int32_t newWidth = (right - left) + 1;
2671
+ int32_t newHeight = (bottom - top) + 1;
2672
+
2673
+ // 適用先
2674
+ VALUE cropOptions = _this->getMetadata();
2675
+ VALUE croppedImage = RixmapImage_NewInstance(_this->getMode(), newWidth, newHeight, cropOptions);
2676
+ Rixmap::ImageData* cropped = rixmap_unwrap<Rixmap::ImageData>(croppedImage);
2677
+
2678
+ // ピクセルを切り出し
2679
+ int32_t selfWidth = _this->getWidth();
2680
+ int32_t selfHeight = _this->getHeight();
2681
+ const Rixmap::ChannelArray& channels = _this->getModeInfo().getChannels();
2682
+ for (auto it = channels.begin(); it != channels.end(); it++) {
2683
+ Rixmap::Channel channel = *it;
2684
+ for (int32_t h = top; h <= bottom; h++) {
2685
+ if (h < 0 || selfHeight <= h) {
2686
+ continue;
2687
+ }
2688
+ for (int32_t w = left; w <= right; w++) {
2689
+ if (w < 0 || selfWidth <= w) {
2690
+ continue;
2691
+ }
2692
+
2693
+ cropped->set(channel, (w - left), (h - top), _this->get(channel, w, h));
2694
+ }
2695
+ }
2696
+ }
2697
+
2698
+ // 複製を戻す
2699
+ return croppedImage;
2700
+ }
2701
+
2702
+ /**
2703
+ * 別の画像をこの画像に破壊的に合成します.
2704
+ *
2705
+ * @param [Rixmap::Image] image 合成する画像
2706
+ * @param [Integer] x 合成位置 (X軸方向)
2707
+ * @param [Integer] y 合成位置 (Y軸方向)
2708
+ * @return [Rixmap::Image] selfを返します.
2709
+ */
2710
+ static VALUE Image_pasteSelf(VALUE self, VALUE argImage, VALUE argX, VALUE argY) {
2711
+ Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
2712
+ Rixmap::ImageData* image = rixmap_unwrap<Rixmap::ImageData>(argImage);
2713
+ int32_t xoffset = NUM2LONG(rb_Integer(argX));
2714
+ int32_t yoffset = NUM2LONG(rb_Integer(argY));
2715
+
2716
+ for (int32_t h = 0; h < image->getHeight(); h++) {
2717
+ for (int32_t w = 0; w < image->getWidth(); w++) {
2718
+ int32_t xpos = xoffset + w;
2719
+ int32_t ypos = yoffset + h;
2720
+ if (_this->isInside(xpos, ypos)) {
2721
+ Rixmap::Color pixel = image->fetch(w, h);
2722
+ Rixmap::Helper::UpdatePixel(_this, xpos, ypos, RixmapColorPool::Get(pixel));
2723
+ }
2724
+ }
2725
+ }
2726
+
2727
+ return self;
2728
+ }
2729
+
2730
+ /**
2731
+ * この画像と指定された画像を合成した新しい画像を返します.
2732
+ *
2733
+ * @param [Rixmap::Image] image 合成する画像
2734
+ * @param [Integer] x 合成位置 (X軸方向)
2735
+ * @param [Integer] y 合成位置 (Y軸方向)
2736
+ * @return [Rixmap::Image] 合成された新しい画像
2737
+ * @see #paste!
2738
+ */
2739
+ static VALUE Image_paste(VALUE self, VALUE argImage, VALUE argX, VALUE argY) {
2740
+ VALUE base = rb_obj_clone(self);
2741
+ return rb_funcall(base, rb_intern("paste!"), 3, argImage, argX, argY);
2742
+ }
2743
+
2744
+ /**
2745
+ * @overload deform(deformer, *args)
2746
+ * 指定された{Rixmap::Deformer::BaseDeformer}インスタンスを使って変形処理を実行します.
2747
+ * @param [Rixmap::Deformer::BaseDeformer] deformer 変形処理実装インスタンス
2748
+ * @param [Array] *args {Rixmap::Deformer::BaseDeformer#deform} に渡す追加引数
2749
+ * @return [Rixmap::Image] 変形後画像
2750
+ *
2751
+ * @see Rixmap::Deformer::BaseDeformer#deform
2752
+ */
2753
+ static VALUE Image_deform(int argc, VALUE* argv, VALUE self) {
2754
+ VALUE argDeformer, argParams;
2755
+ rb_scan_args(argc, argv, "1*", &argDeformer, &argParams);
2756
+
2757
+ // パラメータを構築
2758
+ VALUE params = rb_ary_new();
2759
+ rb_ary_push(params, self);
2760
+ rb_ary_concat(params, argParams);
2761
+
2762
+ // 変形実行
2763
+ VALUE deformed = rb_funcall2(argDeformer, rb_intern("deform"), RARRAY_LEN(params), RARRAY_PTR(params));
2764
+
2765
+ // 変形画像を返却
2766
+ return deformed;
2767
+ }
2768
+
2769
+ /**
2770
+ * @overload deform!(deformer, *args)
2771
+ * 指定された{Rixmap::Deformer::BaseDeformer}インスタンスを使って破壊的に変形処理を実行します.
2772
+ * @param [Rixmap::Deformer::BaseDeformer] deformer 変形処理実装インスタンス
2773
+ * @param [Array] *args {Rixmap::Deformer::BaseDeformer#deform} に渡す追加引数
2774
+ * @return [Rixmap::Image] selfを返します.
2775
+ *
2776
+ * @see Rixmap::Deformer::BaseDeformer#deform
2777
+ */
2778
+ static VALUE Image_deformSelf(int argc, VALUE* argv, VALUE self) {
2779
+ VALUE argDeformer, argParams;
2780
+ rb_scan_args(argc, argv, "1*", &argDeformer, &argParams);
2781
+
2782
+ // パラメータを構築
2783
+ VALUE params = rb_ary_new();
2784
+ rb_ary_push(params, self);
2785
+ rb_ary_concat(params, argParams);
2786
+
2787
+ // 変形実行
2788
+ VALUE deformedImage = rb_funcall2(argDeformer, rb_intern("deform"), RARRAY_LEN(params), RARRAY_PTR(params));
2789
+
2790
+ // 自分に上書き
2791
+ Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
2792
+ Rixmap::ImageData* deformed = rixmap_unwrap<Rixmap::ImageData>(deformedImage);
2793
+ *_this = *deformed;
2794
+
2795
+ return self;
2796
+ }
2797
+
2798
+ /**
2799
+ * 指定方向に破壊的に反転処理を行います.
2800
+ *
2801
+ * @param [Integer] direction 反転方向. {Rixmap::HORIZONTAL}, {Rixmap::VERTICAL}, {Rixmap::DIAGONAL}のいずれか.
2802
+ * @return [Rixmap::Image] selfを返します.
2803
+ */
2804
+ static VALUE Image_flipSelf(VALUE self, VALUE argDirection) {
2805
+ Rixmap::ImageData* _this = rixmap_unwrap<Rixmap::ImageData>(self);
2806
+
2807
+ // 反転方向
2808
+ Rixmap::FlipDirection direction = static_cast<Rixmap::FlipDirection>(NUM2INT(rb_Integer(argDirection)));
2809
+
2810
+ // 反転処理
2811
+ _this->flip(direction);
2812
+
2813
+ return self;
2814
+ }
2815
+
2816
+ /**
2817
+ * 指定方向に反転を行った画像を返します.
2818
+ *
2819
+ * @param [Integer] direction 反転方向. {Rixmap::HORIZONTAL}, {Rixmap::VERTICAL}, {Rixmap::DIAGONAL}のいずれか.
2820
+ * @return [Rixmap::Image] 反転後の画像
2821
+ */
2822
+ static VALUE Image_flip(VALUE self, VALUE argDirection) {
2823
+ // 複製を作成
2824
+ VALUE image = rb_obj_clone(self);
2825
+
2826
+ // 複製を反転
2827
+ rb_funcall(image, rb_intern("flip!"), 1, argDirection);
2828
+
2829
+ // 複製を戻す
2830
+ return image;
2831
+ }
2586
2832
  /* }}} */
2587
2833
  /* Rixmap::Image::Line {{{ */
2588
2834
  static void ImageLine_Mark(Rixmap::ImageLineData* data) {
@@ -2662,7 +2908,7 @@ static VALUE ImageLine_isValid(VALUE self) {
2662
2908
  */
2663
2909
  static VALUE ImageLine_getRedBand(VALUE self) {
2664
2910
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2665
- return RixmapHelper::GetBand(_this, Rixmap::Channel::RED);
2911
+ return Rixmap::Helper::GetBand(_this, Rixmap::Channel::RED);
2666
2912
  }
2667
2913
 
2668
2914
  /**
@@ -2673,7 +2919,7 @@ static VALUE ImageLine_getRedBand(VALUE self) {
2673
2919
  */
2674
2920
  static VALUE ImageLine_setRedBand(VALUE self, VALUE argBand) {
2675
2921
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2676
- RixmapHelper::UpdateBand(_this, Rixmap::Channel::RED, argBand);
2922
+ Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::RED, argBand);
2677
2923
  return argBand;
2678
2924
  }
2679
2925
 
@@ -2685,7 +2931,7 @@ static VALUE ImageLine_setRedBand(VALUE self, VALUE argBand) {
2685
2931
  */
2686
2932
  static VALUE ImageLine_getGreenBand(VALUE self) {
2687
2933
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2688
- return RixmapHelper::GetBand(_this, Rixmap::Channel::GREEN);
2934
+ return Rixmap::Helper::GetBand(_this, Rixmap::Channel::GREEN);
2689
2935
  }
2690
2936
 
2691
2937
  /**
@@ -2696,7 +2942,7 @@ static VALUE ImageLine_getGreenBand(VALUE self) {
2696
2942
  */
2697
2943
  static VALUE ImageLine_setGreenBand(VALUE self, VALUE argBand) {
2698
2944
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2699
- RixmapHelper::UpdateBand(_this, Rixmap::Channel::GREEN, argBand);
2945
+ Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::GREEN, argBand);
2700
2946
  return argBand;
2701
2947
  }
2702
2948
 
@@ -2708,7 +2954,7 @@ static VALUE ImageLine_setGreenBand(VALUE self, VALUE argBand) {
2708
2954
  */
2709
2955
  static VALUE ImageLine_getBlueBand(VALUE self) {
2710
2956
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2711
- return RixmapHelper::GetBand(_this, Rixmap::Channel::BLUE);
2957
+ return Rixmap::Helper::GetBand(_this, Rixmap::Channel::BLUE);
2712
2958
  }
2713
2959
 
2714
2960
  /**
@@ -2719,7 +2965,7 @@ static VALUE ImageLine_getBlueBand(VALUE self) {
2719
2965
  */
2720
2966
  static VALUE ImageLine_setBlueBand(VALUE self, VALUE argBand) {
2721
2967
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2722
- RixmapHelper::UpdateBand(_this, Rixmap::Channel::BLUE, argBand);
2968
+ Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::BLUE, argBand);
2723
2969
  return argBand;
2724
2970
  }
2725
2971
 
@@ -2731,7 +2977,7 @@ static VALUE ImageLine_setBlueBand(VALUE self, VALUE argBand) {
2731
2977
  */
2732
2978
  static VALUE ImageLine_getAlphaBand(VALUE self) {
2733
2979
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2734
- return RixmapHelper::GetBand(_this, Rixmap::Channel::ALPHA);
2980
+ return Rixmap::Helper::GetBand(_this, Rixmap::Channel::ALPHA);
2735
2981
  }
2736
2982
 
2737
2983
  /**
@@ -2742,7 +2988,7 @@ static VALUE ImageLine_getAlphaBand(VALUE self) {
2742
2988
  */
2743
2989
  static VALUE ImageLine_setAlphaBand(VALUE self, VALUE argBand) {
2744
2990
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2745
- RixmapHelper::UpdateBand(_this, Rixmap::Channel::ALPHA, argBand);
2991
+ Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::ALPHA, argBand);
2746
2992
  return argBand;
2747
2993
  }
2748
2994
 
@@ -2754,7 +3000,7 @@ static VALUE ImageLine_setAlphaBand(VALUE self, VALUE argBand) {
2754
3000
  */
2755
3001
  static VALUE ImageLine_getLuminanceBand(VALUE self) {
2756
3002
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2757
- return RixmapHelper::GetBand(_this, Rixmap::Channel::LUMINANCE);
3003
+ return Rixmap::Helper::GetBand(_this, Rixmap::Channel::LUMINANCE);
2758
3004
  }
2759
3005
 
2760
3006
  /**
@@ -2765,7 +3011,7 @@ static VALUE ImageLine_getLuminanceBand(VALUE self) {
2765
3011
  */
2766
3012
  static VALUE ImageLine_setLuminanceBand(VALUE self, VALUE argBand) {
2767
3013
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2768
- RixmapHelper::UpdateBand(_this, Rixmap::Channel::LUMINANCE, argBand);
3014
+ Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::LUMINANCE, argBand);
2769
3015
  return argBand;
2770
3016
  }
2771
3017
 
@@ -2777,7 +3023,7 @@ static VALUE ImageLine_setLuminanceBand(VALUE self, VALUE argBand) {
2777
3023
  */
2778
3024
  static VALUE ImageLine_getPaletteBand(VALUE self) {
2779
3025
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2780
- return RixmapHelper::GetBand(_this, Rixmap::Channel::PALETTE);
3026
+ return Rixmap::Helper::GetBand(_this, Rixmap::Channel::PALETTE);
2781
3027
  }
2782
3028
 
2783
3029
  /**
@@ -2788,7 +3034,7 @@ static VALUE ImageLine_getPaletteBand(VALUE self) {
2788
3034
  */
2789
3035
  static VALUE ImageLine_setPaletteBand(VALUE self, VALUE argBand) {
2790
3036
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2791
- RixmapHelper::UpdateBand(_this, Rixmap::Channel::PALETTE, argBand);
3037
+ Rixmap::Helper::UpdateBand(_this, Rixmap::Channel::PALETTE, argBand);
2792
3038
  return argBand;
2793
3039
  }
2794
3040
 
@@ -2805,7 +3051,7 @@ static VALUE ImageLine_offsetGet(VALUE self, VALUE argOffset) {
2805
3051
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2806
3052
  long offset = NUM2LONG(rb_Integer(argOffset));
2807
3053
 
2808
- return RixmapHelper::GetPixel(_this->getImageData(), offset, _this->getLineNumber());
3054
+ return Rixmap::Helper::GetPixel(_this->getImageData(), offset, _this->getLineNumber());
2809
3055
  }
2810
3056
 
2811
3057
  /**
@@ -2822,7 +3068,7 @@ static VALUE ImageLine_offsetSet(VALUE self, VALUE argOffset, VALUE argColor) {
2822
3068
  Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
2823
3069
  long offset = NUM2LONG(rb_Integer(argOffset));
2824
3070
 
2825
- RixmapHelper::UpdatePixel(_this->getImageData(), offset, _this->getLineNumber(), argColor);
3071
+ Rixmap::Helper::UpdatePixel(_this->getImageData(), offset, _this->getLineNumber(), argColor);
2826
3072
 
2827
3073
  return argColor;
2828
3074
  }
@@ -2846,7 +3092,7 @@ static VALUE ImageLine_toArray(VALUE self) {
2846
3092
  int32_t lineno = _this->getLineNumber();
2847
3093
  VALUE pixels = rb_ary_new2(length);
2848
3094
  for (int32_t i = 0; i < length; i++) {
2849
- VALUE pixel = RixmapHelper::GetPixel(_parent, i, lineno);
3095
+ VALUE pixel = Rixmap::Helper::GetPixel(_parent, i, lineno);
2850
3096
  rb_ary_store(pixels, i, pixel);
2851
3097
  }
2852
3098
  return pixels;
@@ -2965,7 +3211,7 @@ static VALUE ImageLine_each(VALUE self) {
2965
3211
  int32_t length = _this->getLength();
2966
3212
  int32_t lineno = _this->getLineNumber();
2967
3213
  for (int32_t i = 0; i < length; i++) {
2968
- VALUE pixel = RixmapHelper::GetPixel(_parent, i, lineno);
3214
+ VALUE pixel = Rixmap::Helper::GetPixel(_parent, i, lineno);
2969
3215
  rb_yield_values(1, pixel);
2970
3216
  }
2971
3217
  }
@@ -2978,6 +3224,34 @@ static VALUE ImageLine_each(VALUE self) {
2978
3224
  }
2979
3225
  }
2980
3226
 
3227
+ /**
3228
+ * スキャンライン内の各ピクセルについてブロックを呼び出し、その戻り値でピクセルを更新します.
3229
+ *
3230
+ * @overload map!()
3231
+ * @yield [pixel] ピクセルごとにブロックを呼び出します.
3232
+ * @yieldparam pixel [Integer,Array] ピクセルデータ
3233
+ * @return [Rixmap::Image::Line] selfを返します.
3234
+ */
3235
+ static VALUE ImageLine_mapSelf(VALUE self) {
3236
+ if (!rb_block_given_p()) {
3237
+ rb_raise(rb_eRuntimeError, "block parameter are required.");
3238
+ }
3239
+
3240
+ Rixmap::ImageLineData* _this = rixmap_unwrap<Rixmap::ImageLineData>(self);
3241
+ if (_this->isValid()) {
3242
+ Rixmap::ImageData* _parent = _this->getImageData();
3243
+ int32_t length = _this->getLength();
3244
+ int32_t lineno = _this->getLineNumber();
3245
+ for (int32_t i = 0; i < length; i++) {
3246
+ VALUE pixel = Rixmap::Helper::GetPixel(_parent, i, lineno);
3247
+ VALUE resp = rb_yield_values(1, pixel);
3248
+ Rixmap::Helper::UpdatePixel(_parent, i, lineno, resp);
3249
+ }
3250
+ }
3251
+
3252
+ return self;
3253
+ }
3254
+
2981
3255
  /**
2982
3256
  * オブジェクトとしての文字列表現を返します.
2983
3257
  *
@@ -3036,8 +3310,10 @@ void RixmapCore_Init() {
3036
3310
  rb_define_method(cRixmapBinary, "shift", RUBY_METHOD_FUNC(Binary_shift), -1);
3037
3311
  rb_define_method(cRixmapBinary, "unshift", RUBY_METHOD_FUNC(Binary_unshift), -1);
3038
3312
  rb_define_method(cRixmapBinary, "each", RUBY_METHOD_FUNC(Binary_each), 0);
3039
- rb_define_method(cRixmapBinary, "reverse", RUBY_METHOD_FUNC(Binary_copyReverse), 0);
3040
- rb_define_method(cRixmapBinary, "reverse!", RUBY_METHOD_FUNC(Binary_reverse), 0);
3313
+ rb_define_method(cRixmapBinary, "reverse", RUBY_METHOD_FUNC(Binary_reverse), 0);
3314
+ rb_define_method(cRixmapBinary, "reverse!", RUBY_METHOD_FUNC(Binary_reverseSelf), 0);
3315
+ rb_define_method(cRixmapBinary, "map", RUBY_METHOD_FUNC(Binary_map), 0);
3316
+ rb_define_method(cRixmapBinary, "map!", RUBY_METHOD_FUNC(Binary_mapSelf), 0);
3041
3317
  rb_define_method(cRixmapBinary, "to_ary", RUBY_METHOD_FUNC(Binary_toArray), 0);
3042
3318
  rb_define_method(cRixmapBinary, "to_str", RUBY_METHOD_FUNC(Binary_toString), 0);
3043
3319
  rb_define_method(cRixmapBinary, "to_s", RUBY_METHOD_FUNC(Binary_toTextString), 0);
@@ -3121,14 +3397,16 @@ void RixmapCore_Init() {
3121
3397
  rb_define_alloc_func(cRixmapPalette, Palette_Alloc);
3122
3398
  rb_define_private_method(cRixmapPalette, "initialize", RUBY_METHOD_FUNC(Palette_initialize), -1);
3123
3399
  rb_define_private_method(cRixmapPalette, "initialize_copy", RUBY_METHOD_FUNC(Palette_initializeCopy), 1);
3124
- rb_define_method(cRixmapPalette, "size", RUBY_METHOD_FUNC(Palette_getSize), 0);
3125
- rb_define_method(cRixmapPalette, "[]", RUBY_METHOD_FUNC(Palette_offsetGet), 1);
3126
- rb_define_method(cRixmapPalette, "[]=", RUBY_METHOD_FUNC(Palette_offsetSet), 2);
3127
- rb_define_method(cRixmapPalette, "==", RUBY_METHOD_FUNC(Palette_operatorEquals), 1);
3128
- rb_define_method(cRixmapPalette, "to_s", RUBY_METHOD_FUNC(Palette_toString), -1); // バイト列への変換
3129
- rb_define_method(cRixmapPalette, "to_a", RUBY_METHOD_FUNC(Palette_toArray), 0); // カラー配列への変換 (self.each.to_aでもいいかも)
3130
- rb_define_method(cRixmapPalette, "each", RUBY_METHOD_FUNC(Palette_each), 0);
3131
- rb_define_method(cRixmapPalette, "inspect", RUBY_METHOD_FUNC(Palette_inspect), 0);
3400
+ rb_define_method(cRixmapPalette, "size", RUBY_METHOD_FUNC(Palette_getSize), 0);
3401
+ rb_define_method(cRixmapPalette, "[]", RUBY_METHOD_FUNC(Palette_offsetGet), 1);
3402
+ rb_define_method(cRixmapPalette, "[]=", RUBY_METHOD_FUNC(Palette_offsetSet), 2);
3403
+ rb_define_method(cRixmapPalette, "==", RUBY_METHOD_FUNC(Palette_operatorEquals), 1);
3404
+ rb_define_method(cRixmapPalette, "to_s", RUBY_METHOD_FUNC(Palette_toString), -1); // バイト列への変換
3405
+ rb_define_method(cRixmapPalette, "to_a", RUBY_METHOD_FUNC(Palette_toArray), 0); // カラー配列への変換 (self.each.to_aでもいいかも)
3406
+ rb_define_method(cRixmapPalette, "each", RUBY_METHOD_FUNC(Palette_each), 0);
3407
+ rb_define_method(cRixmapPalette, "map", RUBY_METHOD_FUNC(Palette_map), 0);
3408
+ rb_define_method(cRixmapPalette, "map!", RUBY_METHOD_FUNC(Palette_mapSelf), 0);
3409
+ rb_define_method(cRixmapPalette, "inspect", RUBY_METHOD_FUNC(Palette_inspect), 0);
3132
3410
  rb_include_module(cRixmapPalette, rb_mEnumerable);
3133
3411
 
3134
3412
  /**
@@ -3154,7 +3432,8 @@ void RixmapCore_Init() {
3154
3432
  */
3155
3433
  cRixmapImage = rb_define_class_under(mRixmap, "Image", rb_cObject);
3156
3434
  rb_define_alloc_func(cRixmapImage, Image_Alloc);
3157
- rb_define_private_method(cRixmapImage, "initialize", RUBY_METHOD_FUNC(Image_initialize), -1);
3435
+ rb_define_private_method(cRixmapImage, "initialize", RUBY_METHOD_FUNC(Image_initialize), -1);
3436
+ rb_define_private_method(cRixmapImage, "initialize_copy", RUBY_METHOD_FUNC(Image_initializeCopy), 1);
3158
3437
  rb_define_method(cRixmapImage, "mode", RUBY_METHOD_FUNC(Image_getMode), 0);
3159
3438
  rb_define_method(cRixmapImage, "width", RUBY_METHOD_FUNC(Image_getWidth), 0);
3160
3439
  rb_define_method(cRixmapImage, "height", RUBY_METHOD_FUNC(Image_getHeight), 0);
@@ -3173,9 +3452,33 @@ void RixmapCore_Init() {
3173
3452
  rb_define_method(cRixmapImage, "each_pixel", RUBY_METHOD_FUNC(Image_eachPixel), 0);
3174
3453
  rb_define_method(cRixmapImage, "lines", RUBY_METHOD_FUNC(Image_getLines), 0);
3175
3454
  rb_define_method(cRixmapImage, "pixels", RUBY_METHOD_FUNC(Image_getPixels), 0);
3455
+ rb_define_method(cRixmapImage, "convert", RUBY_METHOD_FUNC(Image_convert), 1);
3176
3456
  rb_define_method(cRixmapImage, "inspect", RUBY_METHOD_FUNC(Image_inspect), 0);
3177
3457
  rb_alias(cRixmapImage, rb_intern("dim"), rb_intern("dimension"));
3178
3458
 
3459
+ //// 画像操作系
3460
+ rb_define_method(cRixmapImage, "split", RUBY_METHOD_FUNC(Image_split), 0);
3461
+ rb_define_method(cRixmapImage, "fill", RUBY_METHOD_FUNC(Image_fill), -1);
3462
+ rb_define_method(cRixmapImage, "fill!", RUBY_METHOD_FUNC(Image_fillSelf), -1);
3463
+ rb_define_method(cRixmapImage, "crop", RUBY_METHOD_FUNC(Image_crop), 4);
3464
+ rb_define_method(cRixmapImage, "crop!", RUBY_METHOD_FUNC(Image_cropSelf), 4);
3465
+ rb_define_method(cRixmapImage, "paste", RUBY_METHOD_FUNC(Image_paste), 3);
3466
+ rb_define_method(cRixmapImage, "paste!", RUBY_METHOD_FUNC(Image_pasteSelf), 3);
3467
+ rb_define_method(cRixmapImage, "deform", RUBY_METHOD_FUNC(Image_deform), -1);
3468
+ rb_define_method(cRixmapImage, "deform!", RUBY_METHOD_FUNC(Image_deformSelf), -1);
3469
+ rb_define_method(cRixmapImage, "flip", RUBY_METHOD_FUNC(Image_flip), 1);
3470
+ rb_define_method(cRixmapImage, "flip!", RUBY_METHOD_FUNC(Image_flipSelf), 1);
3471
+
3472
+ // 反転方向定数値
3473
+ /** 水平方向への反転 */
3474
+ rb_define_const(mRixmap, "HORIZONTAL", INT2FIX(static_cast<int>(Rixmap::FlipDirection::HORIZONTAL)));
3475
+
3476
+ /** 垂直方向への反転 */
3477
+ rb_define_const(mRixmap, "VERTICAL", INT2FIX(static_cast<int>(Rixmap::FlipDirection::VERTICAL)));
3478
+
3479
+ /** 横と縦に同時に反転 */
3480
+ rb_define_const(mRixmap, "DIAGONAL", INT2FIX(static_cast<int>(Rixmap::FlipDirection::DIAGONAL)));
3481
+
3179
3482
  /**
3180
3483
  * Document-class: Rixmap::Image::Line
3181
3484
  *
@@ -3206,6 +3509,7 @@ void RixmapCore_Init() {
3206
3509
  rb_define_method(cRixmapImageLine, "to_a", RUBY_METHOD_FUNC(ImageLine_toArray), 0);
3207
3510
  rb_define_method(cRixmapImageLine, "to_s", RUBY_METHOD_FUNC(ImageLine_toString), -1);
3208
3511
  rb_define_method(cRixmapImageLine, "each", RUBY_METHOD_FUNC(ImageLine_each), 0);
3512
+ rb_define_method(cRixmapImageLine, "map!", RUBY_METHOD_FUNC(ImageLine_mapSelf), 0);
3209
3513
  rb_define_method(cRixmapImageLine, "inspect", RUBY_METHOD_FUNC(ImageLine_inspect), 0);
3210
3514
  rb_alias(cRixmapImageLine, rb_intern("to_ary"), rb_intern("to_a"));
3211
3515
  rb_include_module(cRixmapImageLine, rb_mEnumerable);
@@ -3220,7 +3524,99 @@ void RixmapCore_Init() {
3220
3524
  rb_global_variable(&cRixmapImageLine);
3221
3525
  }
3222
3526
 
3527
+ /**
3528
+ * 指定した情報から新しいRixmap::Imageインスタンスを作成します.
3529
+ */
3530
+ VALUE RixmapImage_NewInstance(Rixmap::Mode mode, int32_t width, int32_t height, VALUE options) {
3531
+ VALUE args[4] = {
3532
+ RixmapModePool::Get(mode),
3533
+ LONG2NUM(width),
3534
+ LONG2NUM(height),
3535
+ options
3536
+ };
3537
+
3538
+ return rb_class_new_instance(4, args, cRixmapImage);
3539
+ }
3540
+
3541
+ /**
3542
+ * 指定された色数のパレットを作成します.
3543
+ */
3544
+ VALUE RixmapPalette_NewInstance(size_t size) {
3545
+ VALUE args[1] = {
3546
+ ULONG2NUM(size)
3547
+ };
3548
+ return rb_class_new_instance(1, args, cRixmapPalette);
3549
+ }
3550
+
3551
+ /**
3552
+ * 赤要素のみの256諧調パレットを作成します.
3553
+ */
3554
+ VALUE RixmapPalette_NewRedScaleInstance() {
3555
+ VALUE instance = RixmapPalette_NewInstance(256);
3556
+ Rixmap::PaletteData* data = rixmap_unwrap<Rixmap::PaletteData>(instance);
3557
+ size_t size = data->getSize();
3558
+ for (size_t i = 0; i < size; i++) {
3559
+ Rixmap::Color color(static_cast<uint8_t>(i), 0, 0);
3560
+ data->set(i, color);
3561
+ }
3562
+ return instance;
3563
+ }
3564
+
3565
+ /**
3566
+ * 緑要素のみの256諧調パレットを作成します.
3567
+ */
3568
+ VALUE RixmapPalette_NewGreenScaleInstance() {
3569
+ VALUE instance = RixmapPalette_NewInstance(256);
3570
+ Rixmap::PaletteData* data = rixmap_unwrap<Rixmap::PaletteData>(instance);
3571
+ size_t size = data->getSize();
3572
+ for (size_t i = 0; i < size; i++) {
3573
+ Rixmap::Color color(0, static_cast<uint8_t>(i), 0);
3574
+ data->set(i, color);
3575
+ }
3576
+ return instance;
3577
+ }
3578
+
3579
+ /**
3580
+ * 青要素のみの256諧調パレットを作成します.
3581
+ */
3582
+ VALUE RixmapPalette_NewBlueScaleInstance() {
3583
+ VALUE instance = RixmapPalette_NewInstance(256);
3584
+ Rixmap::PaletteData* data = rixmap_unwrap<Rixmap::PaletteData>(instance);
3585
+ size_t size = data->getSize();
3586
+ for (size_t i = 0; i < size; i++) {
3587
+ Rixmap::Color color(0, 0, static_cast<uint8_t>(i));
3588
+ data->set(i, color);
3589
+ }
3590
+ return instance;
3591
+ }
3592
+
3593
+ /**
3594
+ * グレースケール256諧調パレットを作成します.
3595
+ */
3596
+ VALUE RixmapPalette_NewGrayScaleInstance() {
3597
+ VALUE instance = RixmapPalette_NewInstance(256);
3598
+ Rixmap::PaletteData* data = rixmap_unwrap<Rixmap::PaletteData>(instance);
3599
+ size_t size = data->getSize();
3600
+ for (size_t i = 0; i < size; i++) {
3601
+ uint8_t value = static_cast<uint8_t>(i);
3602
+ Rixmap::Color color(value, value, value);
3603
+ data->set(i, color);
3604
+ }
3605
+ return instance;
3606
+ }
3607
+
3608
+ /**
3609
+ * スキャンラインオブジェクトを作成します.
3610
+ */
3611
+ VALUE RixmapImageLine_NewInstance(VALUE image, int32_t lineno) {
3612
+ VALUE args[2] = {
3613
+ image,
3614
+ LONG2NUM(lineno)
3615
+ };
3616
+ return rb_class_new_instance(2, args, cRixmapImageLine);
3617
+ }
3618
+
3223
3619
 
3224
3620
  //============================================================================//
3225
- // $Id: rixmapcore.cxx,v f933bbbed93e 2014/04/21 14:36:01 chikuchikugonzalez $
3621
+ // $Id: rixmapcore.cxx,v 753dbf70cab3 2014/05/16 16:13:38 chikuchikugonzalez $
3226
3622
  // vim: set sts=4 ts=4 sw=4 expandtab foldmethod=marker: