magro 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/magro/imgrw.c DELETED
@@ -1,410 +0,0 @@
1
- #include "imgrw.h"
2
-
3
- RUBY_EXTERN VALUE mMagro;
4
-
5
- /**
6
- * @!visibility private
7
- */
8
- static VALUE magro_io_read_png(VALUE self, VALUE filename_) {
9
- char* filename = StringValuePtr(filename_);
10
- FILE* file_ptr = fopen(filename, "rb");
11
- unsigned char header[8];
12
- png_structp png_ptr;
13
- png_infop info_ptr;
14
- png_bytep* row_ptr_ptr;
15
- png_bytep row_ptr;
16
- png_uint_32 width, height;
17
- int color_type;
18
- int bit_depth;
19
- png_uint_32 y;
20
- int n_dims = 0;
21
- int n_ch;
22
- size_t shape[3] = {0};
23
- VALUE nary;
24
- uint8_t* nary_ptr;
25
-
26
- if (file_ptr == NULL) {
27
- rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
28
- return Qnil;
29
- }
30
-
31
- if (fread(header, 1, 8, file_ptr) < 8) {
32
- fclose(file_ptr);
33
- rb_raise(rb_eIOError, "Failed to read header info '%s'", filename);
34
- return Qnil;
35
- }
36
-
37
- if (png_sig_cmp(header, 0, 8)) {
38
- fclose(file_ptr);
39
- rb_raise(rb_eIOError, "Failed to read header info '%s'", filename);
40
- return Qnil;
41
- }
42
-
43
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
44
- if (png_ptr == NULL) {
45
- fclose(file_ptr);
46
- rb_raise(rb_eNoMemError, "Failed to allocate memory.");
47
- return Qnil;
48
- }
49
- info_ptr = png_create_info_struct(png_ptr);
50
- if (info_ptr == NULL) {
51
- png_destroy_read_struct(&png_ptr, NULL, NULL);
52
- fclose(file_ptr);
53
- rb_raise(rb_eNoMemError, "Failed to allocate memory.");
54
- return Qnil;
55
- }
56
- if (setjmp(png_jmpbuf(png_ptr))) {
57
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
58
- fclose(file_ptr);
59
- rb_raise(rb_eIOError, "Error happened while reading file '%s'", filename);
60
- return Qnil;
61
- }
62
-
63
- png_init_io(png_ptr, file_ptr);
64
- png_set_sig_bytes(png_ptr, 8);
65
-
66
- png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_16, NULL);
67
- row_ptr_ptr = png_get_rows(png_ptr, info_ptr);
68
- png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
69
-
70
- if (color_type == PNG_COLOR_TYPE_PALETTE) {
71
- png_set_palette_to_rgb(png_ptr);
72
- png_read_update_info(png_ptr, info_ptr);
73
- png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
74
- }
75
-
76
- switch (color_type) {
77
- case PNG_COLOR_TYPE_GRAY:
78
- n_ch = 1;
79
- n_dims = 2;
80
- shape[0] = height;
81
- shape[1] = width;
82
- break;
83
- case PNG_COLOR_TYPE_GRAY_ALPHA:
84
- n_ch = 2;
85
- n_dims = 3;
86
- shape[0] = height;
87
- shape[1] = width;
88
- shape[2] = 2;
89
- break;
90
- case PNG_COLOR_TYPE_RGB:
91
- n_ch = 3;
92
- n_dims = 3;
93
- shape[0] = height;
94
- shape[1] = width;
95
- shape[2] = 3;
96
- break;
97
- case PNG_COLOR_TYPE_RGB_ALPHA:
98
- n_ch = 4;
99
- n_dims = 3;
100
- shape[0] = height;
101
- shape[1] = width;
102
- shape[2] = 4;
103
- break;
104
- default:
105
- n_dims = 0;
106
- break;
107
- }
108
-
109
- if (n_dims == 0) {
110
- fclose(file_ptr);
111
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
112
- rb_raise(rb_eIOError, "Unsupported color type of input file '%s'", filename);
113
- return Qnil;
114
- }
115
-
116
- nary = rb_narray_new(numo_cUInt8, n_dims, shape);
117
- nary_ptr = (uint8_t*)na_get_pointer_for_write(nary);
118
-
119
- for (y = 0; y < height; y++) {
120
- row_ptr = row_ptr_ptr[y];
121
- memcpy(nary_ptr + y * width * n_ch, row_ptr, width * n_ch);
122
- }
123
-
124
- fclose(file_ptr);
125
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
126
-
127
- RB_GC_GUARD(filename_);
128
-
129
- return nary;
130
- }
131
-
132
- /**
133
- * @!visibility private
134
- */
135
- static VALUE magro_io_save_png(VALUE self, VALUE filename_, VALUE image) {
136
- char* filename = StringValuePtr(filename_);
137
- FILE* file_ptr = fopen(filename, "wb");
138
- png_structp png_ptr;
139
- png_infop info_ptr;
140
- png_bytep* row_ptr_ptr;
141
- png_uint_32 width, height;
142
- int color_type;
143
- int bit_depth = 8;
144
- png_uint_32 y;
145
- int n_ch;
146
- int n_dims;
147
- narray_t* image_nary;
148
- uint8_t* image_ptr;
149
-
150
- if (file_ptr == NULL) {
151
- rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
152
- return Qfalse;
153
- }
154
-
155
- if (CLASS_OF(image) != numo_cUInt8) {
156
- image = rb_funcall(numo_cUInt8, rb_intern("cast"), 1, image);
157
- }
158
- if (!RTEST(nary_check_contiguous(image))) {
159
- image = nary_dup(image);
160
- }
161
-
162
- GetNArray(image, image_nary);
163
- n_dims = NA_NDIM(image_nary);
164
- height = (png_uint_32)NA_SHAPE(image_nary)[0];
165
- width = (png_uint_32)NA_SHAPE(image_nary)[1];
166
- image_ptr = (uint8_t*)na_get_pointer_for_read(image);
167
-
168
- n_ch = 1;
169
- if (n_dims == 3) {
170
- n_ch = (int)NA_SHAPE(image_nary)[2];
171
- }
172
-
173
- switch (n_ch) {
174
- case 4:
175
- color_type = PNG_COLOR_TYPE_RGBA;
176
- break;
177
- case 3:
178
- color_type = PNG_COLOR_TYPE_RGB;
179
- break;
180
- case 2:
181
- color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
182
- break;
183
- default:
184
- color_type = PNG_COLOR_TYPE_GRAY;
185
- break;
186
- }
187
-
188
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
189
- if (png_ptr == NULL) {
190
- fclose(file_ptr);
191
- rb_raise(rb_eNoMemError, "Failed to allocate memory.");
192
- return Qfalse;
193
- }
194
- info_ptr = png_create_info_struct(png_ptr);
195
- if (info_ptr == NULL) {
196
- png_destroy_read_struct(&png_ptr, NULL, NULL);
197
- fclose(file_ptr);
198
- rb_raise(rb_eNoMemError, "Failed to allocate memory.");
199
- return Qfalse;
200
- }
201
- if (setjmp(png_jmpbuf(png_ptr))) {
202
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
203
- fclose(file_ptr);
204
- return Qfalse;
205
- }
206
-
207
- png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
208
- PNG_FILTER_TYPE_DEFAULT);
209
-
210
- row_ptr_ptr = png_malloc(png_ptr, height * sizeof(png_bytep));
211
- for (y = 0; y < height; y++) {
212
- row_ptr_ptr[y] = png_malloc(png_ptr, width * n_ch * sizeof(png_byte));
213
- memcpy(row_ptr_ptr[y], image_ptr + y * width * n_ch, width * n_ch);
214
- }
215
-
216
- png_init_io(png_ptr, file_ptr);
217
- png_set_rows(png_ptr, info_ptr, row_ptr_ptr);
218
- png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
219
-
220
- fclose(file_ptr);
221
- for (y = 0; y < height; y++) {
222
- png_free(png_ptr, row_ptr_ptr[y]);
223
- }
224
- png_free(png_ptr, row_ptr_ptr);
225
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
226
-
227
- RB_GC_GUARD(image);
228
- RB_GC_GUARD(filename_);
229
-
230
- return Qtrue;
231
- }
232
-
233
- struct my_error_mgr {
234
- struct jpeg_error_mgr pub;
235
- jmp_buf setjmp_buffer;
236
- };
237
-
238
- static void my_error_exit(j_common_ptr cinfo) {
239
- struct my_error_mgr* my_err = (struct my_error_mgr*)cinfo->err;
240
- (*cinfo->err->output_message)(cinfo);
241
- longjmp(my_err->setjmp_buffer, 1);
242
- }
243
-
244
- /**
245
- * @!visibility private
246
- */
247
- static VALUE magro_io_read_jpg(VALUE self, VALUE filename_) {
248
- char* filename = StringValuePtr(filename_);
249
- FILE* file_ptr = fopen(filename, "rb");
250
- struct jpeg_decompress_struct jpeg;
251
- struct my_error_mgr err;
252
- unsigned int width, height;
253
- int n_colors;
254
- size_t shape[3] = {0};
255
- int n_dims;
256
- unsigned int y;
257
- VALUE nary;
258
- uint8_t* nary_ptr;
259
- JSAMPLE* tmp;
260
-
261
- if (file_ptr == NULL) {
262
- rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
263
- return Qnil;
264
- }
265
-
266
- jpeg.err = jpeg_std_error(&err.pub);
267
- err.pub.error_exit = my_error_exit;
268
- if (setjmp(err.setjmp_buffer)) {
269
- rb_raise(rb_eIOError, "Error happened while reading file '%s'", filename);
270
- return Qnil;
271
- }
272
-
273
- jpeg_create_decompress(&jpeg);
274
- jpeg_stdio_src(&jpeg, file_ptr);
275
- jpeg_read_header(&jpeg, TRUE);
276
- jpeg_start_decompress(&jpeg);
277
-
278
- width = jpeg.output_width;
279
- height = jpeg.output_height;
280
- n_colors = jpeg.out_color_components;
281
-
282
- n_dims = n_colors == 1 ? 2 : 3;
283
- shape[0] = height;
284
- shape[1] = width;
285
- shape[2] = n_colors;
286
- nary = rb_narray_new(numo_cUInt8, n_dims, shape);
287
- nary_ptr = (uint8_t*)na_get_pointer_for_write(nary);
288
-
289
- for (y = 0; y < height; y++) {
290
- tmp = nary_ptr + y * width * n_colors;
291
- jpeg_read_scanlines(&jpeg, &tmp, 1);
292
- }
293
-
294
- fclose(file_ptr);
295
- jpeg_finish_decompress(&jpeg);
296
- jpeg_destroy_decompress(&jpeg);
297
-
298
- RB_GC_GUARD(filename_);
299
-
300
- return nary;
301
- }
302
-
303
- /**
304
- * @!visibility private
305
- */
306
- static VALUE magro_io_save_jpg(int argc, VALUE* argv, VALUE self) {
307
- VALUE filename_;
308
- VALUE image;
309
- VALUE quality_;
310
- char* filename;
311
- FILE* file_ptr;
312
- struct jpeg_compress_struct jpeg;
313
- struct my_error_mgr err;
314
- narray_t* image_nary;
315
- int quality;
316
- int n_dims, n_ch;
317
- unsigned int width, height, y;
318
- uint8_t* image_ptr;
319
- JSAMPLE* tmp;
320
-
321
- rb_scan_args(argc, argv, "21", &filename_, &image, &quality_);
322
-
323
- if (NIL_P(quality_)) {
324
- quality = 95;
325
- } else {
326
- quality = NUM2INT(quality_);
327
- }
328
-
329
- filename = StringValuePtr(filename_);
330
-
331
- if (CLASS_OF(image) != numo_cUInt8) {
332
- image = rb_funcall(numo_cUInt8, rb_intern("cast"), 1, image);
333
- }
334
- if (!RTEST(nary_check_contiguous(image))) {
335
- image = nary_dup(image);
336
- }
337
-
338
- jpeg.err = jpeg_std_error(&err.pub);
339
- err.pub.error_exit = my_error_exit;
340
- if (setjmp(err.setjmp_buffer)) {
341
- return Qfalse;
342
- }
343
-
344
- jpeg_create_compress(&jpeg);
345
-
346
- file_ptr = fopen(filename, "wb");
347
- if (file_ptr == NULL) {
348
- rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
349
- jpeg_destroy_compress(&jpeg);
350
- return Qfalse;
351
- }
352
-
353
- GetNArray(image, image_nary);
354
- n_dims = NA_NDIM(image_nary);
355
- height = (unsigned int)NA_SHAPE(image_nary)[0];
356
- width = (unsigned int)NA_SHAPE(image_nary)[1];
357
- image_ptr = (uint8_t*)na_get_pointer_for_read(image);
358
-
359
- n_ch = 1;
360
- if (n_dims == 3) {
361
- n_ch = (int)NA_SHAPE(image_nary)[2];
362
- }
363
-
364
- jpeg_stdio_dest(&jpeg, file_ptr);
365
-
366
- jpeg.image_height = height;
367
- jpeg.image_width = width;
368
- jpeg.input_components = n_ch;
369
-
370
- switch (n_ch) {
371
- case 3:
372
- jpeg.in_color_space = JCS_RGB;
373
- break;
374
- case 1:
375
- jpeg.in_color_space = JCS_GRAYSCALE;
376
- break;
377
- default:
378
- jpeg.in_color_space = JCS_UNKNOWN;
379
- break;
380
- }
381
-
382
- jpeg_set_defaults(&jpeg);
383
-
384
- jpeg_set_quality(&jpeg, quality, TRUE);
385
-
386
- jpeg_start_compress(&jpeg, TRUE);
387
-
388
- for (y = 0; y < height; y++) {
389
- tmp = image_ptr + y * width * n_ch;
390
- jpeg_write_scanlines(&jpeg, &tmp, 1);
391
- }
392
-
393
- jpeg_finish_compress(&jpeg);
394
- jpeg_destroy_compress(&jpeg);
395
-
396
- fclose(file_ptr);
397
-
398
- RB_GC_GUARD(image);
399
- RB_GC_GUARD(filename_);
400
-
401
- return Qtrue;
402
- }
403
-
404
- void init_io_module() {
405
- VALUE mIO = rb_define_module_under(mMagro, "IO");
406
- rb_define_module_function(mIO, "read_png", magro_io_read_png, 1);
407
- rb_define_module_function(mIO, "save_png", magro_io_save_png, 2);
408
- rb_define_module_function(mIO, "read_jpg", magro_io_read_jpg, 1);
409
- rb_define_module_function(mIO, "save_jpg", magro_io_save_jpg, -1);
410
- }
data/ext/magro/imgrw.h DELETED
@@ -1,20 +0,0 @@
1
- #ifndef MAGRO_IO_H
2
- #define MAGRO_IO_H 1
3
-
4
- #include <stdio.h>
5
- #include <stdlib.h>
6
- #include <string.h>
7
-
8
- #include <setjmp.h>
9
-
10
- #include <jpeglib.h>
11
- #include <png.h>
12
-
13
- #include <ruby.h>
14
-
15
- #include <numo/narray.h>
16
- #include <numo/template.h>
17
-
18
- void init_io_module();
19
-
20
- #endif /* MAGRO_IO_H */
data/magro.gemspec DELETED
@@ -1,39 +0,0 @@
1
- lib = File.expand_path('lib', __dir__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'magro/version'
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = 'magro'
7
- spec.version = Magro::VERSION
8
- spec.authors = ['yoshoku']
9
- spec.email = ['yoshoku@outlook.com']
10
-
11
- spec.summary = 'Magro is a minimal image processing library for Ruby.'
12
- spec.description = <<~MSG
13
- Magro is a minimal image processing library for Ruby.
14
- Magro uses Numo::NArray arrays as image objects and provides basic image processing functions.
15
- Current supporting features are reading and writing JPEG and PNG images,
16
- image resizing with bilinear interpolation method, and image filtering.
17
- MSG
18
-
19
- spec.homepage = 'https://github.com/yoshoku/magro'
20
- spec.license = 'BSD-3-Clause'
21
-
22
- spec.metadata['homepage_uri'] = spec.homepage
23
- spec.metadata['source_code_uri'] = 'https://github.com/yoshoku/magro'
24
- spec.metadata['changelog_uri'] = 'https://github.com/yoshoku/magro/blob/main/CHANGELOG.md'
25
- spec.metadata['documentation_uri'] = 'https://yoshoku.github.io/magro/doc/'
26
-
27
- # Specify which files should be added to the gem when it is released.
28
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
29
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
30
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
31
- end
32
-
33
- spec.bindir = 'exe'
34
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
- spec.require_paths = ['lib']
36
- spec.extensions = ['ext/magro/extconf.rb']
37
-
38
- spec.add_runtime_dependency 'numo-narray', '>= 0.9.1'
39
- end
data/sig/patch.rbs DELETED
@@ -1,90 +0,0 @@
1
- module Numo
2
- class NArray
3
- def self.cast: (untyped a) -> untyped
4
- def self.zeros: (*Integer) -> untyped
5
- def self.[]: (*untyped) -> untyped
6
- def []: () -> untyped
7
- def []=: () -> untyped
8
- def +: (untyped) -> untyped
9
- def empty?: () -> bool
10
- def flatten: () -> untyped
11
- def initialize: (*untyped) -> untyped
12
- def ndim: () -> Integer
13
- def shape: () -> [Integer, Integer]
14
- def swapaxes: (Integer, Integer) -> untyped
15
- def transpose: (*untyped) -> untyped
16
- end
17
-
18
- class Int8 < NArray
19
- def *: (untyped) -> untyped
20
- def +: (untyped) -> untyped
21
- def []: (*untyped) -> untyped
22
- def []=: (*untyped) -> untyped
23
- end
24
-
25
- class Int16 < NArray
26
- def *: (untyped) -> untyped
27
- def +: (untyped) -> untyped
28
- def []: (*untyped) -> untyped
29
- def []=: (*untyped) -> untyped
30
- end
31
-
32
- class Int32 < NArray
33
- def *: (untyped) -> untyped
34
- def +: (untyped) -> untyped
35
- def []: (*untyped) -> untyped
36
- def []=: (*untyped) -> untyped
37
- def seq: (*untyped) -> untyped
38
- end
39
-
40
- class Int64 < NArray
41
- def *: (untyped) -> untyped
42
- def +: (untyped) -> untyped
43
- def []: (*untyped) -> untyped
44
- def []=: (*untyped) -> untyped
45
- end
46
-
47
- class UInt8 < NArray
48
- def *: (untyped) -> untyped
49
- def +: (untyped) -> untyped
50
- def []: (*untyped) -> untyped
51
- def []=: (*untyped) -> untyped
52
- end
53
-
54
- class UInt16 < NArray
55
- def *: (untyped) -> untyped
56
- def +: (untyped) -> untyped
57
- def []: (*untyped) -> untyped
58
- def []=: (*untyped) -> untyped
59
- end
60
-
61
- class UInt32 < NArray
62
- def *: (untyped) -> untyped
63
- def +: (untyped) -> untyped
64
- def []: (*untyped) -> untyped
65
- def []=: (*untyped) -> untyped
66
- end
67
-
68
- class UInt64 < NArray
69
- def *: (untyped) -> untyped
70
- def +: (untyped) -> untyped
71
- def []: (*untyped) -> untyped
72
- def []=: (*untyped) -> untyped
73
- end
74
-
75
- class SFloat < NArray
76
- def sum: (*untyped) -> untyped
77
- def *: (untyped) -> untyped
78
- def +: (untyped) -> untyped
79
- def []: (*untyped) -> untyped
80
- def []=: (*untyped) -> untyped
81
- end
82
-
83
- class DFloat < NArray
84
- def sum: (*untyped) -> untyped
85
- def *: (untyped) -> untyped
86
- def +: (untyped) -> untyped
87
- def []: (*untyped) -> untyped
88
- def []=: (*untyped) -> untyped
89
- end
90
- end