magro 0.4.2 → 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,421 +0,0 @@
1
- #include "imgrw.h"
2
-
3
- RUBY_EXTERN VALUE mMagro;
4
-
5
- /**
6
- * @!visibility private
7
- */
8
- static
9
- VALUE magro_io_read_png(VALUE self, VALUE filename_)
10
- {
11
- char* filename = StringValuePtr(filename_);
12
- FILE* file_ptr = fopen(filename, "rb");
13
- unsigned char header[8];
14
- png_structp png_ptr;
15
- png_infop info_ptr;
16
- png_bytep* row_ptr_ptr;
17
- png_bytep row_ptr;
18
- png_uint_32 width, height;
19
- int color_type;
20
- int bit_depth;
21
- png_uint_32 y;
22
- int n_dims = 0;
23
- int n_ch;
24
- size_t shape[3] = { 0 };
25
- VALUE nary;
26
- uint8_t* nary_ptr;
27
-
28
- if (file_ptr == NULL) {
29
- rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
30
- return Qnil;
31
- }
32
-
33
- if (fread(header, 1, 8, file_ptr) < 8) {
34
- fclose(file_ptr);
35
- rb_raise(rb_eIOError, "Failed to read header info '%s'", filename);
36
- return Qnil;
37
- }
38
-
39
- if (png_sig_cmp(header, 0, 8)) {
40
- fclose(file_ptr);
41
- rb_raise(rb_eIOError, "Failed to read header info '%s'", filename);
42
- return Qnil;
43
- }
44
-
45
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
46
- if (png_ptr == NULL) {
47
- fclose(file_ptr);
48
- rb_raise(rb_eNoMemError, "Failed to allocate memory.");
49
- return Qnil;
50
- }
51
- info_ptr = png_create_info_struct(png_ptr);
52
- if (info_ptr == NULL) {
53
- png_destroy_read_struct(&png_ptr, NULL, NULL);
54
- fclose(file_ptr);
55
- rb_raise(rb_eNoMemError, "Failed to allocate memory.");
56
- return Qnil;
57
- }
58
- if (setjmp(png_jmpbuf(png_ptr))) {
59
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
60
- fclose(file_ptr);
61
- rb_raise(rb_eIOError, "Error happened while reading file '%s'", filename);
62
- return Qnil;
63
- }
64
-
65
- png_init_io(png_ptr, file_ptr);
66
- png_set_sig_bytes(png_ptr, 8);
67
-
68
- png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_16, NULL);
69
- row_ptr_ptr = png_get_rows(png_ptr, info_ptr);
70
- png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
71
-
72
- if (color_type == PNG_COLOR_TYPE_PALETTE) {
73
- png_set_palette_to_rgb(png_ptr);
74
- png_read_update_info(png_ptr, info_ptr);
75
- png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
76
- }
77
-
78
- switch (color_type) {
79
- case PNG_COLOR_TYPE_GRAY:
80
- n_ch = 1;
81
- n_dims = 2;
82
- shape[0] = height;
83
- shape[1] = width;
84
- break;
85
- case PNG_COLOR_TYPE_GRAY_ALPHA:
86
- n_ch = 2;
87
- n_dims = 3;
88
- shape[0] = height;
89
- shape[1] = width;
90
- shape[2] = 2;
91
- break;
92
- case PNG_COLOR_TYPE_RGB:
93
- n_ch = 3;
94
- n_dims = 3;
95
- shape[0] = height;
96
- shape[1] = width;
97
- shape[2] = 3;
98
- break;
99
- case PNG_COLOR_TYPE_RGB_ALPHA:
100
- n_ch = 4;
101
- n_dims = 3;
102
- shape[0] = height;
103
- shape[1] = width;
104
- shape[2] = 4;
105
- break;
106
- default:
107
- n_dims = 0;
108
- break;
109
- }
110
-
111
- if (n_dims == 0) {
112
- fclose(file_ptr);
113
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
114
- rb_raise(rb_eIOError, "Unsupported color type of input file '%s'", filename);
115
- return Qnil;
116
- }
117
-
118
- nary = rb_narray_new(numo_cUInt8, n_dims, shape);
119
- nary_ptr = (uint8_t*)na_get_pointer_for_write(nary);
120
-
121
- for (y = 0; y < height; y++) {
122
- row_ptr = row_ptr_ptr[y];
123
- memcpy(nary_ptr + y * width * n_ch, row_ptr, width * n_ch);
124
- }
125
-
126
- fclose(file_ptr);
127
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
128
-
129
- RB_GC_GUARD(filename_);
130
-
131
- return nary;
132
- }
133
-
134
- /**
135
- * @!visibility private
136
- */
137
- static
138
- VALUE magro_io_save_png(VALUE self, VALUE filename_, VALUE image)
139
- {
140
- char* filename = StringValuePtr(filename_);
141
- FILE* file_ptr = fopen(filename, "wb");
142
- png_structp png_ptr;
143
- png_infop info_ptr;
144
- png_bytep* row_ptr_ptr;
145
- png_uint_32 width, height;
146
- int color_type;
147
- int bit_depth = 8;
148
- png_uint_32 y;
149
- int n_ch;
150
- int n_dims;
151
- narray_t* image_nary;
152
- uint8_t* image_ptr;
153
-
154
- if (file_ptr == NULL) {
155
- rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
156
- return Qfalse;
157
- }
158
-
159
- if (CLASS_OF(image) != numo_cUInt8) {
160
- image = rb_funcall(numo_cUInt8, rb_intern("cast"), 1, image);
161
- }
162
- if (!RTEST(nary_check_contiguous(image))) {
163
- image = nary_dup(image);
164
- }
165
-
166
- GetNArray(image, image_nary);
167
- n_dims = NA_NDIM(image_nary);
168
- height = (png_uint_32)NA_SHAPE(image_nary)[0];
169
- width = (png_uint_32)NA_SHAPE(image_nary)[1];
170
- image_ptr = (uint8_t*)na_get_pointer_for_read(image);
171
-
172
- n_ch = 1;
173
- if (n_dims == 3) {
174
- n_ch = (int)NA_SHAPE(image_nary)[2];
175
- }
176
-
177
- switch (n_ch) {
178
- case 4:
179
- color_type = PNG_COLOR_TYPE_RGBA;
180
- break;
181
- case 3:
182
- color_type = PNG_COLOR_TYPE_RGB;
183
- break;
184
- case 2:
185
- color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
186
- break;
187
- default:
188
- color_type = PNG_COLOR_TYPE_GRAY;
189
- break;
190
- }
191
-
192
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
193
- if (png_ptr == NULL) {
194
- fclose(file_ptr);
195
- rb_raise(rb_eNoMemError, "Failed to allocate memory.");
196
- return Qfalse;
197
- }
198
- info_ptr = png_create_info_struct(png_ptr);
199
- if (info_ptr == NULL) {
200
- png_destroy_read_struct(&png_ptr, NULL, NULL);
201
- fclose(file_ptr);
202
- rb_raise(rb_eNoMemError, "Failed to allocate memory.");
203
- return Qfalse;
204
- }
205
- if (setjmp(png_jmpbuf(png_ptr))) {
206
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
207
- fclose(file_ptr);
208
- return Qfalse;
209
- }
210
-
211
- png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type,
212
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
213
-
214
- row_ptr_ptr = png_malloc(png_ptr, height * sizeof(png_bytep));
215
- for (y = 0; y < height; y++) {
216
- row_ptr_ptr[y] = png_malloc(png_ptr, width * n_ch * sizeof(png_byte));
217
- memcpy(row_ptr_ptr[y], image_ptr + y * width * n_ch, width * n_ch);
218
- }
219
-
220
- png_init_io(png_ptr, file_ptr);
221
- png_set_rows(png_ptr, info_ptr, row_ptr_ptr);
222
- png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
223
-
224
- fclose(file_ptr);
225
- for (y = 0; y < height; y++) {
226
- png_free(png_ptr, row_ptr_ptr[y]);
227
- }
228
- png_free(png_ptr, row_ptr_ptr);
229
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
230
-
231
- RB_GC_GUARD(image);
232
- RB_GC_GUARD(filename_);
233
-
234
- return Qtrue;
235
- }
236
-
237
- struct my_error_mgr {
238
- struct jpeg_error_mgr pub;
239
- jmp_buf setjmp_buffer;
240
- };
241
-
242
- static void
243
- my_error_exit(j_common_ptr cinfo)
244
- {
245
- struct my_error_mgr* my_err = (struct my_error_mgr*)cinfo->err;
246
- (*cinfo->err->output_message)(cinfo);
247
- longjmp(my_err->setjmp_buffer, 1);
248
- }
249
-
250
- /**
251
- * @!visibility private
252
- */
253
- static
254
- VALUE magro_io_read_jpg(VALUE self, VALUE filename_)
255
- {
256
- char* filename = StringValuePtr(filename_);
257
- FILE* file_ptr = fopen(filename, "rb");
258
- struct jpeg_decompress_struct jpeg;
259
- struct my_error_mgr err;
260
- unsigned int width, height;
261
- int n_colors;
262
- size_t shape[3] = { 0 };
263
- int n_dims;
264
- unsigned int y;
265
- VALUE nary;
266
- uint8_t* nary_ptr;
267
- JSAMPLE* tmp;
268
-
269
- if (file_ptr == NULL) {
270
- rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
271
- return Qnil;
272
- }
273
-
274
- jpeg.err = jpeg_std_error(&err.pub);
275
- err.pub.error_exit = my_error_exit;
276
- if (setjmp(err.setjmp_buffer)) {
277
- rb_raise(rb_eIOError, "Error happened while reading file '%s'", filename);
278
- return Qnil;
279
- }
280
-
281
- jpeg_create_decompress(&jpeg);
282
- jpeg_stdio_src(&jpeg, file_ptr);
283
- jpeg_read_header(&jpeg, TRUE);
284
- jpeg_start_decompress(&jpeg);
285
-
286
- width = jpeg.output_width;
287
- height = jpeg.output_height;
288
- n_colors = jpeg.out_color_components;
289
-
290
- n_dims = n_colors == 1 ? 2 : 3;
291
- shape[0] = height;
292
- shape[1] = width;
293
- shape[2] = n_colors;
294
- nary = rb_narray_new(numo_cUInt8, n_dims, shape);
295
- nary_ptr = (uint8_t*)na_get_pointer_for_write(nary);
296
-
297
- for (y = 0; y < height; y++) {
298
- tmp = nary_ptr + y * width * n_colors;
299
- jpeg_read_scanlines(&jpeg, &tmp, 1);
300
- }
301
-
302
- fclose(file_ptr);
303
- jpeg_finish_decompress(&jpeg);
304
- jpeg_destroy_decompress(&jpeg);
305
-
306
- RB_GC_GUARD(filename_);
307
-
308
- return nary;
309
- }
310
-
311
- /**
312
- * @!visibility private
313
- */
314
- static
315
- VALUE magro_io_save_jpg(int argc, VALUE* argv, VALUE self)
316
- {
317
- VALUE filename_;
318
- VALUE image;
319
- VALUE quality_;
320
- char* filename;
321
- FILE* file_ptr;
322
- struct jpeg_compress_struct jpeg;
323
- struct my_error_mgr err;
324
- narray_t* image_nary;
325
- int quality;
326
- int n_dims, n_ch;
327
- unsigned int width, height, y;
328
- uint8_t* image_ptr;
329
- JSAMPLE* tmp;
330
-
331
- rb_scan_args(argc, argv, "21", &filename_, &image, &quality_);
332
-
333
- if (NIL_P(quality_)) {
334
- quality = 95;
335
- } else {
336
- quality = NUM2INT(quality_);
337
- }
338
-
339
- filename = StringValuePtr(filename_);
340
-
341
- if (CLASS_OF(image) != numo_cUInt8) {
342
- image = rb_funcall(numo_cUInt8, rb_intern("cast"), 1, image);
343
- }
344
- if (!RTEST(nary_check_contiguous(image))) {
345
- image = nary_dup(image);
346
- }
347
-
348
- jpeg.err = jpeg_std_error(&err.pub);
349
- err.pub.error_exit = my_error_exit;
350
- if (setjmp(err.setjmp_buffer)) {
351
- return Qfalse;
352
- }
353
-
354
- jpeg_create_compress(&jpeg);
355
-
356
- file_ptr = fopen(filename, "wb");
357
- if (file_ptr == NULL) {
358
- rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
359
- jpeg_destroy_compress(&jpeg);
360
- return Qfalse;
361
- }
362
-
363
- GetNArray(image, image_nary);
364
- n_dims = NA_NDIM(image_nary);
365
- height = (unsigned int)NA_SHAPE(image_nary)[0];
366
- width = (unsigned int)NA_SHAPE(image_nary)[1];
367
- image_ptr = (uint8_t*)na_get_pointer_for_read(image);
368
-
369
- n_ch = 1;
370
- if (n_dims == 3) {
371
- n_ch = (int)NA_SHAPE(image_nary)[2];
372
- }
373
-
374
- jpeg_stdio_dest(&jpeg, file_ptr);
375
-
376
- jpeg.image_height = height;
377
- jpeg.image_width = width;
378
- jpeg.input_components = n_ch;
379
-
380
- switch (n_ch) {
381
- case 3:
382
- jpeg.in_color_space = JCS_RGB;
383
- break;
384
- case 1:
385
- jpeg.in_color_space = JCS_GRAYSCALE;
386
- break;
387
- default:
388
- jpeg.in_color_space = JCS_UNKNOWN;
389
- break;
390
- }
391
-
392
- jpeg_set_defaults(&jpeg);
393
-
394
- jpeg_set_quality(&jpeg, quality, TRUE);
395
-
396
- jpeg_start_compress(&jpeg, TRUE);
397
-
398
- for (y = 0; y < height; y++) {
399
- tmp = image_ptr + y * width * n_ch;
400
- jpeg_write_scanlines(&jpeg, &tmp, 1);
401
- }
402
-
403
- jpeg_finish_compress(&jpeg);
404
- jpeg_destroy_compress(&jpeg);
405
-
406
- fclose(file_ptr);
407
-
408
- RB_GC_GUARD(image);
409
- RB_GC_GUARD(filename_);
410
-
411
- return Qtrue;
412
- }
413
-
414
- void init_io_module()
415
- {
416
- VALUE mIO = rb_define_module_under(mMagro, "IO");
417
- rb_define_module_function(mIO, "read_png", magro_io_read_png, 1);
418
- rb_define_module_function(mIO, "save_png", magro_io_save_png, 2);
419
- rb_define_module_function(mIO, "read_jpg", magro_io_read_jpg, 1);
420
- rb_define_module_function(mIO, "save_jpg", magro_io_save_jpg, -1);
421
- }
data/ext/magro/imgrw.h DELETED
@@ -1,18 +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
- #include <png.h>
10
- #include <jpeglib.h>
11
-
12
- #include <ruby.h>
13
- #include <numo/narray.h>
14
- #include <numo/template.h>
15
-
16
- void init_io_module();
17
-
18
- #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