rixmap 0.1.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.
@@ -0,0 +1,27 @@
1
+ // -*- coding: utf-8 -*-
2
+ /**
3
+ * Rixmapコア部分用ヘッダ
4
+ */
5
+ #pragma once
6
+ #include "rixmap.hxx"
7
+
8
+ //----------------------------------------------------------------------------//
9
+ // グローバル変数宣言
10
+ //----------------------------------------------------------------------------//
11
+ extern VALUE mRixmap;
12
+ extern VALUE cRixmapBinary;
13
+ extern VALUE cRixmapMode;
14
+ extern VALUE cRixmapColor;
15
+ extern VALUE cRixmapPalette;
16
+ extern VALUE cRixmapImage;
17
+ extern VALUE cRixmapImageLine;
18
+
19
+ //----------------------------------------------------------------------------//
20
+ // コアAPI関数プロトタイプ
21
+ //----------------------------------------------------------------------------//
22
+ extern void RixmapCore_Init();
23
+
24
+
25
+ //============================================================================//
26
+ // $Id: rixmapcore.hxx,v add33526d522 2014/04/19 16:27:29 chikuchikugonzalez $
27
+ // vim: set sts=4 ts=4 sw=4 expandtab foldmethod=marker:
data/src/rixmapio.cxx ADDED
@@ -0,0 +1,652 @@
1
+ // -*- coding: utf-8 -*-
2
+ #include "rixmapio.hxx"
3
+
4
+ //----------------------------------------------------------------------------//
5
+ // C++用グローバルオブジェクト
6
+ //----------------------------------------------------------------------------//
7
+
8
+ //----------------------------------------------------------------------------//
9
+ // グローバルオブジェクト実体
10
+ //----------------------------------------------------------------------------//
11
+ VALUE mRixmapImageIO = Qnil;
12
+ VALUE cRixmapImageIOInfo = Qnil;
13
+ VALUE cRixmapBaseImageIO = Qnil;
14
+ VALUE mRixmapFormat = Qnil;
15
+
16
+ //----------------------------------------------------------------------------//
17
+ // IO系実装
18
+ //----------------------------------------------------------------------------//
19
+ /* Rixmap::ImageIO {{{ */
20
+ /**
21
+ * 画像入出力実装クラスを登録します.
22
+ *
23
+ * @overload register(name, klass, extensions=[])
24
+ * @param [Symbol,String] name 画像入出力実装名. `:BMP` とか.
25
+ * @param [Class] klass 画像入出力の実装クラス.
26
+ * @param [Array<String>] extensions 実装クラスに対応するファイル名拡張子リスト.
27
+ * @return [void]
28
+ *
29
+ * @overload register(name, info)
30
+ * @param [Symbol,String] name 画像入出力実装名
31
+ * @param [Rixmap::ImageIO::ImageIOInfo] info 画像入出力実装情報.
32
+ * @return [void]
33
+ */
34
+ static VALUE ImageIO_Register(int argc, VALUE* argv, VALUE klass) {
35
+ VALUE argName, arg1, arg2;
36
+ rb_scan_args(argc, argv, "21", &argName, &arg1, &arg2);
37
+
38
+ // 名前を大文字化
39
+ VALUE strName = rb_funcall(rb_String(argName), rb_intern("upcase"), 0);
40
+ if (RSTRING_LEN(strName) == 0) {
41
+ rb_raise(rb_eArgError, "empty name is not valid");
42
+ }
43
+ VALUE symName = ID2SYM(rb_intern_str(strName));
44
+
45
+ // 引数で変更
46
+ VALUE info = Qnil;
47
+ if (RB_TYPE_P(arg1, T_CLASS)) {
48
+ // klass
49
+ VALUE objExts = Qnil;
50
+ if (NIL_P(arg2)) {
51
+ objExts = rb_ary_new();
52
+ } else {
53
+ objExts = rb_Array(arg2);
54
+ }
55
+ VALUE params[2] = {
56
+ arg1, objExts
57
+ };
58
+ info = rb_class_new_instance(2, params, cRixmapImageIOInfo);
59
+ } else if (RTEST(rb_obj_is_kind_of(arg1, cRixmapImageIOInfo))) {
60
+ // iio info
61
+ info = rb_obj_clone(arg1);
62
+ } else {
63
+ rb_raise(rb_eArgError, "unknown imageio type: %s", rb_obj_classname(arg1));
64
+ }
65
+
66
+ // レジストリへ入れる
67
+ VALUE registry = rb_iv_get(klass, "@registry");
68
+ OBJ_FREEZE(info);
69
+ rb_hash_aset(registry, symName, info);
70
+
71
+ return info;
72
+ }
73
+
74
+ /**
75
+ * 画像入出力実装のインスタンスを作成します.
76
+ *
77
+ * @overload new(name, *params)
78
+ * @param [Symbol,String] name 画像入出力実装名.
79
+ * @param [Object...] params 実装クラスのコンストラクタに渡される引数.
80
+ * @return [Object] 実装クラスインスタンス.
81
+ */
82
+ static VALUE ImageIO_New(int argc, VALUE* argv, VALUE klass) {
83
+ VALUE argName, argParams;
84
+ rb_scan_args(argc, argv, "1*", &argName, &argParams);
85
+
86
+ // キー名を作成
87
+ VALUE strName = rb_String(argName);
88
+ VALUE symName = ID2SYM(rb_intern_str(rb_funcall(strName, rb_intern("upcase"), 0)));
89
+
90
+ // レジストリから取得
91
+ VALUE registry = rb_iv_get(klass, "@registry");
92
+ VALUE info = rb_hash_lookup(registry, symName);
93
+
94
+ // オブジェクトを作成
95
+ if (NIL_P(info)) {
96
+ rb_raise(rb_eNotImpError, "Image-IO for %s is not implemented.", StringValueCStr(strName));
97
+ }
98
+ VALUE klsIIO = rb_funcall(info, rb_intern("imageio"), 0);
99
+ if (NIL_P(klsIIO)) {
100
+ rb_raise(rb_eNotImpError, "Image-IO for %s is not implemented.", StringValueCStr(strName));
101
+ }
102
+ long nparam = RARRAY_LEN(argParams);
103
+ VALUE* params = RARRAY_PTR(argParams);
104
+ VALUE iio = rb_class_new_instance(nparam, params, klsIIO);
105
+
106
+ return iio;
107
+ }
108
+
109
+ /**
110
+ * 指定した名前に対応する画像入出力実装情報を返します.
111
+ *
112
+ * @param [Symbol,String] name 実装名
113
+ * @return [Rixmap::ImageIO::ImageIOInfo] 実装情報
114
+ */
115
+ static VALUE ImageIO_Get(VALUE klass, VALUE argName) {
116
+ // キー名を作成
117
+ VALUE strName = rb_String(argName);
118
+ VALUE symName = ID2SYM(rb_intern_str(rb_funcall(strName, rb_intern("upcase"), 0)));
119
+
120
+ // レジストリから取得
121
+ VALUE registry = rb_iv_get(klass, "@registry");
122
+ VALUE info = rb_hash_lookup(registry, symName);
123
+
124
+ // 見つからなかった場合はnilになる
125
+ return info;
126
+ }
127
+
128
+ /**
129
+ * 指定したファイル名に最初にマッチした画像入出力実装情報を返します.
130
+ *
131
+ * @param [String] filename ファイル名パターン.
132
+ * @return [Rixmap::ImageIO::ImageIOInfo] 実装情報. 見つからない場合はnil.
133
+ * @see {Rixmap::ImageIO.findall}
134
+ */
135
+ static VALUE ImageIO_Find(VALUE klass, VALUE argFileName) {
136
+ // ファイル名を文字列にしておく
137
+ VALUE strFileName = rb_String(argFileName);
138
+
139
+ // レジストリ
140
+ VALUE registry = rb_iv_get(klass, "@registry");
141
+
142
+ // 登録済みキーリストをすべて取得
143
+ VALUE allKeys = rb_funcall(registry, rb_intern("keys"), 0);
144
+
145
+ // キーでループする
146
+ long nkey = RARRAY_LEN(allKeys);
147
+ for (long i = 0; i < nkey; i++) {
148
+ VALUE tblKey = rb_ary_entry(allKeys, i);
149
+ VALUE tblVal = rb_hash_lookup(registry, tblKey);
150
+
151
+ if (!NIL_P(tblVal) && RTEST(rb_obj_is_kind_of(tblVal, cRixmapImageIOInfo))) {
152
+ VALUE iioInfo = tblVal; // 変数名だけ変えておく
153
+
154
+ // 拡張子をチェック
155
+ if (RTEST(rb_funcall(iioInfo, rb_intern("match?"), 1, strFileName))) {
156
+ // TODO 複数のフォーマットで同じ拡張子に対応している場合
157
+ return iioInfo;
158
+ }
159
+ } else {
160
+ // TODO warningぐらい出しておく?
161
+ }
162
+ }
163
+
164
+ // 見つからなかったらnil
165
+ return Qnil;
166
+ }
167
+
168
+ /**
169
+ * 指定したファイル名にマッチするすべての画像入出力情報を返します.
170
+ *
171
+ * @param [String] filename ファイル名
172
+ * @return [Array<Rixmap::ImageIO::ImageIOInfo>] 実装情報配列. 見つからない場合は空配列になります.
173
+ * @see {Rixmap::ImageIO.find}
174
+ */
175
+ static VALUE ImageIO_FindAll(VALUE klass, VALUE argFileName) {
176
+ // ファイル名を文字列にしておく
177
+ VALUE strFileName = rb_String(argFileName);
178
+
179
+ // レジストリ
180
+ VALUE registry = rb_iv_get(klass, "@registry");
181
+
182
+ // 登録済みキーリストをすべて取得
183
+ VALUE allKeys = rb_funcall(registry, rb_intern("keys"), 0);
184
+
185
+ // キーでループする
186
+ VALUE aryInfo = rb_ary_new();
187
+ long nkey = RARRAY_LEN(allKeys);
188
+ for (long i = 0; i < nkey; i++) {
189
+ VALUE tblKey = rb_ary_entry(allKeys, i);
190
+ VALUE tblVal = rb_hash_lookup(registry, tblKey);
191
+
192
+ if (!NIL_P(tblVal) && RTEST(rb_obj_is_kind_of(tblVal, cRixmapImageIOInfo))) {
193
+ VALUE iioInfo = tblVal; // 変数名だけ変えておく
194
+
195
+ // 拡張子をチェック
196
+ if (RTEST(rb_funcall(iioInfo, rb_intern("match?"), 1, strFileName))) {
197
+ // 配列に追加
198
+ rb_ary_push(aryInfo, iioInfo);
199
+ }
200
+ } else {
201
+ // TODO warningぐらい出しておく?
202
+ }
203
+ }
204
+
205
+ // 見つからなかったら空配列
206
+ return aryInfo;
207
+ }
208
+ /* }}} */
209
+ /* Rixmap::ImageIO::ImageIOInfo {{{ */
210
+ /**
211
+ * 画像入出力情報クラスを初期化します.
212
+ *
213
+ * @overload initialize(klass, extensions = [])
214
+ * @param [Class] klass ImageIO実装クラス
215
+ * @param [Array] extensions 画像の拡張子リスト
216
+ * @return [void]
217
+ */
218
+ static VALUE ImageIOInfo_initialize(int argc, VALUE* argv, VALUE self) {
219
+ VALUE argKlass, argExtensions;
220
+ rb_scan_args(argc, argv, "11", &argKlass, &argExtensions);
221
+
222
+ VALUE objIOClass = argKlass;
223
+ VALUE objExtensions = Qnil;
224
+ if (NIL_P(argExtensions)) {
225
+ objExtensions = rb_ary_new();
226
+ } else {
227
+ objExtensions = rb_Array(argExtensions);
228
+ }
229
+
230
+ rb_iv_set(self, "@imageio", objIOClass);
231
+ rb_iv_set(self, "@extensions", objExtensions);
232
+
233
+ return self;
234
+ }
235
+
236
+ /**
237
+ * 指定したファイル名の拡張子をこの情報クラスの拡張子リストと比較して、
238
+ * マッチしたものが見つかった場合はtrueを返します.
239
+ *
240
+ * @param [String] filename ファイル名
241
+ * @return [Boolean] 拡張子リストとマッチしたものがあるばあいはtrue
242
+ */
243
+ static VALUE ImageIOInfo_isMatchFileName(VALUE self, VALUE argFileName) {
244
+ // 型チェック
245
+ VALUE objExtensions = rb_iv_get(self, "@extensions");
246
+ if (NIL_P(objExtensions)) {
247
+ rb_warning("extensions is null");
248
+ return Qfalse;
249
+ }
250
+ if (!RB_TYPE_P(objExtensions, T_ARRAY)) {
251
+ rb_warning("extensions is not array");
252
+ return Qfalse;
253
+ }
254
+
255
+ // ファイル名
256
+ VALUE objFileName = rb_funcall(rb_String(argFileName), rb_intern("downcase"), 0);
257
+
258
+ // マッチをとる
259
+ long next = RARRAY_LEN(objExtensions);
260
+ for (long i = 0; i < next; i++) {
261
+ VALUE objExt = rb_funcall(rb_String(rb_ary_entry(objExtensions, i)), rb_intern("downcase"), 0);
262
+ if (RTEST(rb_funcall(objFileName, rb_intern("end_with?"), 1, objExt))) {
263
+ return Qtrue;
264
+ }
265
+ }
266
+ return Qfalse;
267
+ }
268
+ /* }}} */
269
+ /* Rixmap::ImageIO::BaseImageIO {{{ */
270
+ /**
271
+ * 画像の先頭バイトからその画像がこのクラスで読み込めるかを判定します.
272
+ *
273
+ * @param [String] magic マジックバイトデータ
274
+ * @return [Boolean] 読み込める形式の場合はtrue
275
+ */
276
+ static VALUE BaseImageIO_IsReadableStatic(VALUE klass, VALUE argMagic) {
277
+ return Qfalse;
278
+ }
279
+
280
+ /**
281
+ * 指定画像がこのクラスで書き込めるかを判定します.
282
+ *
283
+ * @param [Rixmap::Image] image 判定対象画像
284
+ * @return [Boolean] 書き込める形式の場合はtrue
285
+ */
286
+ static VALUE BaseImageIO_IsWritableStatic(VALUE klass, VALUE argImage) {
287
+ return Qfalse;
288
+ }
289
+
290
+ /**
291
+ * 画像入出力実装クラスを初期化します.
292
+ *
293
+ * オプションパラメータが指定されている場合は、キーをインスタンス変数名として値を設定していきます.
294
+ *
295
+ * @overload initialize(options={})
296
+ * @param [Hash] options オプションパラメータ.
297
+ * @return [void]
298
+ */
299
+ static VALUE BaseImageIO_initialize(int argc, VALUE* argv, VALUE self) {
300
+ VALUE argOptions = Qnil;
301
+ rb_scan_args(argc, argv, "01", &argOptions);
302
+
303
+ VALUE objOptions = Qnil;
304
+ if (NIL_P(argOptions)) {
305
+ objOptions = rb_hash_new();
306
+ } else {
307
+ if (RB_TYPE_P(argOptions, T_HASH)) {
308
+ objOptions = argOptions;
309
+ } else {
310
+ #if HAVE_RB_HASH
311
+ objOptions = rb_Hash(argOptions);
312
+ #else
313
+ objOptions = rb_hash_new();
314
+ #endif
315
+ }
316
+ }
317
+
318
+ VALUE keys = rb_funcall(objOptions, rb_intern("keys"), 0);
319
+ VALUE ivPrefix = rb_str_new_cstr("@");
320
+ long nkey = RARRAY_LEN(keys);
321
+ for (long i = 0; i < nkey; i++) {
322
+ VALUE key = rb_ary_entry(keys, i);
323
+ VALUE val = rb_hash_lookup(objOptions, key);
324
+ VALUE strKey = rb_String(key);
325
+ VALUE ivName = rb_str_dup(ivPrefix);
326
+ rb_str_concat(ivName, strKey);
327
+ rb_ivar_set(self, rb_intern_str(ivName), val);
328
+ }
329
+
330
+ return self;
331
+ }
332
+
333
+ /**
334
+ * 画像の先頭バイトからその画像がこのオブジェクトで読み込めるかどうかを判定します.
335
+ *
336
+ * @param [String] magic マジックバイトデータ
337
+ * @return [Boolean] 読み込める場合はtrue
338
+ * @see BaseImageIO.readable?
339
+ */
340
+ static VALUE BaseImageIO_isReadable(VALUE self, VALUE argMagic) {
341
+ VALUE klass = rb_obj_class(self);
342
+ return rb_funcall(klass, rb_intern("readable?"), 1, argMagic);
343
+ }
344
+
345
+ /**
346
+ * 画像がこのオブジェクトで書き込めるかを判定します.
347
+ *
348
+ * @param [Rixmap::Image] image 判定対象画像
349
+ * @return [Boolean] 書き込める形式の場合はtrue
350
+ * @see BaseImageIO.writable?
351
+ */
352
+ static VALUE BaseImageIO_isWritable(VALUE self, VALUE argImage) {
353
+ VALUE klass = rb_obj_class(self);
354
+ return rb_funcall(klass, rb_intern("writable?"), 1, argImage);
355
+ }
356
+
357
+ /**
358
+ * 画像をバイト列へと変換します.
359
+ *
360
+ * 変換処理は各フォーマット毎にサブクラスで実装してください.
361
+ *
362
+ * @overload encode(image, options={})
363
+ * @param [Rixmap::Image] image 変換対象の画像.
364
+ * @param [Hash] options 実行時のオプションパラメータ.
365
+ * @return [String] 画像データを含むバイト列
366
+ * @raise NotImplementedError バイト列への変換処理が実装されていない場合.
367
+ */
368
+ static VALUE BaseImageIO_encode(int argc, VALUE* argv, VALUE self) {
369
+ rb_raise(rb_eNotImpError, "%s#%s is not implemented", rb_obj_classname(self), rb_id2name(rb_frame_this_func()));
370
+ }
371
+
372
+ /**
373
+ * バイト列から画像を復元します.
374
+ *
375
+ * 復元処理は各フォーマット毎にサブクラスで実装してください.
376
+ *
377
+ * @overload decode(data, options={})
378
+ * @param [String] data 画像データが入っているバイト列データ.
379
+ * @param [Hash] options 実行時オプションパラメータ.
380
+ * @return [Rixmap::Image] 復元された画像オブジェクト
381
+ * @raise NotImplementedError バイト列からの復元処理が実装されていない場合.
382
+ */
383
+ static VALUE BaseImageIO_decode(int argc, VALUE* argv, VALUE self) {
384
+ rb_raise(rb_eNotImpError, "%s#%s is not implemented", rb_obj_classname(self), rb_id2name(rb_frame_this_func()));
385
+ }
386
+
387
+ /**
388
+ * 指定したパスへ画像を書き出します.
389
+ *
390
+ * @overload save(path, image, options={})
391
+ * @param [String] path 書き込み先ファイルパス
392
+ * @param [Rixmap::Image] image 書き込む画像オブジェクト.
393
+ * @param [Hash] options 実行時オプションパラメータ.
394
+ * @option options [Integer] :offset ファイルの書き込み開始位置 (バイト数)
395
+ * @return [Integer] 書き込んだバイト数
396
+ * @see #encode
397
+ */
398
+ static VALUE BaseImageIO_save(int argc, VALUE* argv, VALUE self) {
399
+ VALUE argPath, argImage, argOptions;
400
+ rb_scan_args(argc, argv, "21", &argPath, &argImage, &argOptions);
401
+
402
+ // 型チェックとか
403
+ if (!RTEST(rb_obj_is_kind_of(argImage, cRixmapImage))) {
404
+ rb_raise(rb_eArgError, "unexpected type of image: %s", rb_obj_classname(argImage));
405
+ }
406
+ VALUE objPath = rb_String(argPath);
407
+ VALUE objImage = argImage;
408
+ VALUE objOptions = Qnil;
409
+ if (RB_TYPE_P(argOptions, T_HASH)) {
410
+ objOptions = argOptions;
411
+ } else {
412
+ objOptions = rb_hash_new();
413
+ }
414
+
415
+ // 画像のエンコード
416
+ // TODO ここで発生する例外の処理
417
+ VALUE objData = rb_funcall(self, rb_intern("encode"), 2, objImage, objOptions);
418
+
419
+ // ファイルの書き込み位置を確認
420
+ VALUE optFileOffset = rb_hash_lookup(objOptions, ID2SYM(rb_intern("offset")));
421
+ VALUE objFileOffset = Qnil;
422
+ if (NIL_P(optFileOffset)) {
423
+ objFileOffset = INT2FIX(0);
424
+ } else {
425
+ objFileOffset = rb_Integer(optFileOffset);
426
+ }
427
+
428
+ // 書き込み
429
+ VALUE klsIO = rb_path2class("IO");
430
+ VALUE objWroteBytes = rb_funcall(klsIO, rb_intern("binwrite"), 2, objPath, objData, objFileOffset);
431
+
432
+ // 戻す
433
+ return objWroteBytes;
434
+ }
435
+
436
+ /**
437
+ * 指定したストリームへ画像を書き込みます.
438
+ *
439
+ * @overload write(io, image, options={})
440
+ * @param [IO,StringIO] io 出力用に開かれているストリームオブジェクト
441
+ * @param [Rixmap::Image] image 対象画像オブジェクト
442
+ * @param [Hash] options 実行時オプションパラメータ
443
+ * @return [Integer] 書き込んだバイト数
444
+ * @see #encode
445
+ */
446
+ static VALUE BaseImageIO_write(int argc, VALUE* argv, VALUE self) {
447
+ VALUE argIO, argImage, argOptions;
448
+ rb_scan_args(argc, argv, "21", &argIO, &argImage, &argOptions);
449
+
450
+ // 型チェックとか
451
+ if (!RTEST(rb_obj_is_kind_of(argImage, cRixmapImage))) {
452
+ rb_raise(rb_eArgError, "unexpected type of image: %s", rb_obj_classname(argImage));
453
+ }
454
+ VALUE objIO = argIO; // TODO 型チェックする
455
+ VALUE objImage = argImage;
456
+ VALUE objOptions = Qnil;
457
+ if (RB_TYPE_P(argOptions, T_HASH)) {
458
+ objOptions = argOptions;
459
+ } else {
460
+ objOptions = rb_hash_new();
461
+ }
462
+
463
+ // 画像のエンコード
464
+ // TODO ここで発生する例外の処理
465
+ VALUE objData = rb_funcall(self, rb_intern("encode"), 2, objImage, objOptions);
466
+
467
+ // FIXME ここまで #save と同じなのをどうにかしたいよね
468
+
469
+ // 書き込む
470
+ VALUE objWroteBytes = rb_funcall(objIO, rb_intern("write"), 1, objData);
471
+
472
+ // 戻る
473
+ return objWroteBytes;
474
+ }
475
+
476
+ /**
477
+ * 指定したパスから画像を読み込みます.
478
+ *
479
+ * @overload open(path, options={})
480
+ * @param [String] path ファイルパス
481
+ * @param [Hash] options 実行時オプションパラメータ
482
+ * @option options [Integer] :length 読み込むファイルの長さ (バイト数)
483
+ * @option options [Integer] :offset 読み込むファイルの位置
484
+ * @return [Rixmap::Image] 読み込まれた画像
485
+ * @see #decode
486
+ */
487
+ static VALUE BaseImageIO_open(int argc, VALUE* argv, VALUE self) {
488
+ VALUE argPath, argOptions;
489
+ rb_scan_args(argc, argv, "11", &argPath, &argOptions);
490
+
491
+ // 型チェックすべきか
492
+ VALUE objPath = rb_String(argPath);
493
+ VALUE objOptions = Qnil;
494
+ if (RB_TYPE_P(argOptions, T_HASH)) {
495
+ objOptions = argOptions;
496
+ } else {
497
+ objOptions = rb_hash_new();
498
+ }
499
+
500
+ // オプションパラメータ
501
+ VALUE optLength = rb_hash_lookup(objOptions, ID2SYM("length"));
502
+ VALUE optOffset = rb_hash_lookup(objOptions, ID2SYM("offset"));
503
+ VALUE objOffset = Qnil;
504
+ if (NIL_P(optOffset)) {
505
+ objOffset = INT2FIX(0);
506
+ } else {
507
+ objOffset = rb_Integer(optOffset);
508
+ }
509
+
510
+ // バイト列を取得
511
+ VALUE klsIO = rb_path2class("IO");
512
+ VALUE objBytes = rb_funcall(klsIO, rb_intern("binread"), 3, objPath, optLength, objOffset);
513
+
514
+ // 画像を復元
515
+ // TODO ココで発生する例外対処
516
+ VALUE objImage = rb_funcall(self, rb_intern("decode"), 2, objBytes, objOptions);
517
+
518
+ // 戻る
519
+ return objImage;
520
+ }
521
+
522
+ /**
523
+ * 指定されたストリームから画像を読み込みます.
524
+ *
525
+ * @overload read(io, options={})
526
+ * @param [IO,StringIO] io 読み込み用に開かれているストリームオブジェクト
527
+ * @param [Hash] options 実行時オプションパラメータ
528
+ * @option options [Integer] :length 読み込むバイト数
529
+ * @return [Rixmap::Image] 読み込まれた画像
530
+ * @see #decode
531
+ */
532
+ static VALUE BaseImageIO_read(int argc, VALUE* argv, VALUE self) {
533
+ VALUE argIO, argOptions;
534
+ rb_scan_args(argc, argv, "11", &argIO, &argOptions);
535
+
536
+ // 型チェック…?
537
+ VALUE objIO = argIO;
538
+ VALUE objOptions = Qnil;
539
+ if (RB_TYPE_P(argOptions, T_HASH)) {
540
+ objOptions = argOptions;
541
+ } else {
542
+ objOptions = rb_hash_new();
543
+ }
544
+
545
+ // オプションパラメータ
546
+ VALUE optLength = rb_hash_lookup(objOptions, ID2SYM("length"));
547
+
548
+ // 読み込む
549
+ VALUE objBytes = rb_funcall(objIO, rb_intern("read"), 1, optLength);
550
+
551
+ // 復元
552
+ VALUE objImage = rb_funcall(self, rb_intern("decode"), 2, objBytes, objOptions);
553
+
554
+ // 戻る
555
+ return objImage;
556
+ }
557
+ /* }}} */
558
+
559
+ //----------------------------------------------------------------------------//
560
+ // 内部API実装
561
+ //----------------------------------------------------------------------------//
562
+ /**
563
+ * 初期化処理
564
+ */
565
+ void RixmapIO_Init() {
566
+ /**
567
+ * Document-module: Rixmap::ImageIO
568
+ *
569
+ * IO系クラス定義モジュール.
570
+ */
571
+ mRixmapImageIO = rb_define_module_under(mRixmap, "ImageIO");
572
+ rb_define_singleton_method(mRixmapImageIO, "register", RUBY_METHOD_FUNC(ImageIO_Register), -1);
573
+ rb_define_singleton_method(mRixmapImageIO, "new", RUBY_METHOD_FUNC(ImageIO_New), -1);
574
+ rb_define_singleton_method(mRixmapImageIO, "get", RUBY_METHOD_FUNC(ImageIO_Get), 1);
575
+ rb_define_singleton_method(mRixmapImageIO, "find", RUBY_METHOD_FUNC(ImageIO_Find), 1);
576
+ rb_define_singleton_method(mRixmapImageIO, "findall", RUBY_METHOD_FUNC(ImageIO_FindAll), 1);
577
+ rb_iv_set(mRixmapImageIO, "@registry", rb_hash_new());
578
+
579
+ /**
580
+ * Document-class: Rixmap::ImageIO::ImageIOInfo
581
+ *
582
+ * IOクラス実装情報クラス.
583
+ * {Rixmap::ImageIO}モジュールの内部で使用しています.
584
+ */
585
+ cRixmapImageIOInfo = rb_define_class_under(mRixmapImageIO, "ImageIOInfo", rb_cObject);
586
+ rb_define_private_method(cRixmapImageIOInfo, "initialize", RUBY_METHOD_FUNC(ImageIOInfo_initialize), -1);
587
+ rb_define_attr(cRixmapImageIOInfo, "imageio", 1, 1);
588
+ rb_define_attr(cRixmapImageIOInfo, "extensions", 1, 1);
589
+ rb_define_method(cRixmapImageIOInfo, "match?", RUBY_METHOD_FUNC(ImageIOInfo_isMatchFileName), 1);
590
+
591
+ /**
592
+ * Document-class: Rixmap::ImageIO::BaseImageIO
593
+ *
594
+ * 画像入出力処理のベースクラス.
595
+ */
596
+ cRixmapBaseImageIO = rb_define_class_under(mRixmapImageIO, "BaseImageIO", rb_cObject);
597
+ rb_define_singleton_method(cRixmapBaseImageIO, "readable?", RUBY_METHOD_FUNC(BaseImageIO_IsReadableStatic), 1);
598
+ rb_define_singleton_method(cRixmapBaseImageIO, "writable?", RUBY_METHOD_FUNC(BaseImageIO_IsWritableStatic), 1);
599
+ rb_define_private_method(cRixmapBaseImageIO, "initialize", RUBY_METHOD_FUNC(BaseImageIO_initialize), -1);
600
+ rb_define_method(cRixmapBaseImageIO, "readable?", RUBY_METHOD_FUNC(BaseImageIO_isReadable), 1);
601
+ rb_define_method(cRixmapBaseImageIO, "writable?", RUBY_METHOD_FUNC(BaseImageIO_isWritable), 1);
602
+ rb_define_method(cRixmapBaseImageIO, "encode", RUBY_METHOD_FUNC(BaseImageIO_encode), -1);
603
+ rb_define_method(cRixmapBaseImageIO, "decode", RUBY_METHOD_FUNC(BaseImageIO_decode), -1);
604
+ rb_define_method(cRixmapBaseImageIO, "save", RUBY_METHOD_FUNC(BaseImageIO_save), -1);
605
+ rb_define_method(cRixmapBaseImageIO, "write", RUBY_METHOD_FUNC(BaseImageIO_write), -1);
606
+ rb_define_method(cRixmapBaseImageIO, "open", RUBY_METHOD_FUNC(BaseImageIO_open), -1);
607
+ rb_define_method(cRixmapBaseImageIO, "read", RUBY_METHOD_FUNC(BaseImageIO_read), -1);
608
+
609
+ /**
610
+ * Document-module: Rixmap::Format
611
+ *
612
+ * 各種フォーマット実装モジュール.
613
+ */
614
+ mRixmapFormat = rb_define_module_under(mRixmap, "Format");
615
+
616
+ // グローバル変数を保存
617
+ rb_global_variable(&mRixmapImageIO);
618
+ rb_global_variable(&cRixmapImageIOInfo);
619
+ rb_global_variable(&cRixmapBaseImageIO);
620
+ rb_global_variable(&mRixmapFormat);
621
+ }
622
+
623
+ /**
624
+ * 指定したフォーマット名でImageIOへklassを登録します.
625
+ *
626
+ * @param [const char*] name フォーマット名
627
+ * @param [VALUE] klass フォーマット実装クラスオブジェクト
628
+ * @param [int] num 拡張子の実装数
629
+ * @param [const char*...] ... 拡張子リスト
630
+ */
631
+ void RixmapIO_RegisterImageIO(const char* name, volatile VALUE klass, int num, ...) {
632
+ volatile VALUE objName = rb_str_new_cstr(name);
633
+ volatile VALUE aryExts = rb_ary_new();
634
+
635
+ // 拡張子リストを処理.
636
+ // 可変長引数から取得する.
637
+ va_list vargs;
638
+ va_start(vargs, num);
639
+ for (int i = 0; i < num; i++) {
640
+ const char* ext = va_arg(vargs, const char*);
641
+ rb_ary_push(aryExts, rb_str_new_cstr(ext));
642
+ }
643
+ va_end(vargs);
644
+
645
+ // ImageIO.registerを呼び出す
646
+ rb_funcall(mRixmapImageIO, rb_intern("register"), 3, objName, klass, aryExts);
647
+ }
648
+
649
+
650
+ //============================================================================//
651
+ // $Id: rixmapio.cxx,v 66c8edefa6c0 2014/04/20 14:22:54 chikuchikugonzalez $
652
+ // vim: set sts=4 ts=4 sw=4 expandtab foldmethod=marker:
data/src/rixmapio.hxx ADDED
@@ -0,0 +1,25 @@
1
+ // -*- coding: utf-8 -*-
2
+ /**
3
+ * Rixmapの入出力関係ヘッダ
4
+ */
5
+ #pragma once
6
+ #include "rixmapcore.hxx"
7
+
8
+ //----------------------------------------------------------------------------//
9
+ // グローバル変数宣言
10
+ //----------------------------------------------------------------------------//
11
+ extern VALUE mRixmapImageIO;
12
+ extern VALUE cRixmapImageIOInfo;
13
+ extern VALUE cRixmapBaseImageIO;
14
+ extern VALUE mRixmapFormat;
15
+
16
+ //----------------------------------------------------------------------------//
17
+ // コアAPI関数プロトタイプ
18
+ //----------------------------------------------------------------------------//
19
+ extern void RixmapIO_Init();
20
+ extern void RixmapIO_RegisterImageIO(const char* name, volatile VALUE klass, int num, ...);
21
+
22
+
23
+ //============================================================================//
24
+ // $Id: rixmapio.hxx,v bb1f88e64282 2014/04/20 13:54:13 chikuchikugonzalez $
25
+ // vim: set sts=4 ts=4 sw=4 expandtab foldmethod=marker: