magro 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfa8a730f370ebbdf54c3bbbe2248046ec82e0dc759e14f974637d79d437e254
4
- data.tar.gz: c907656b0d0732f095d103e0c2bfa76eca70859831c19426ebe517c7560d6592
3
+ metadata.gz: c1c544837f96597012ff6cf938a4148b7fcc640237daf460ae26c64f91588767
4
+ data.tar.gz: '08915ee5d2d4ed4b535963684b160e2ab4707d7823b56578f5574099ca33d7ad'
5
5
  SHA512:
6
- metadata.gz: 8943d964496a118ee778532cfc5fe9cdf8ef4a9731b9217453c98f09ec5ef05be77a5d205ef7e6172e9e3d18475b4dcb336d0626ec458a74b957b1504e3f6e36
7
- data.tar.gz: 14ef03b1c882e6d0c2502edce3a93b8bf805588e8ee319652bae5b39cb4d6f682df8387268b646e1e1c1b751db5b944247eec96ad7f7152813af97c3afadf74a
6
+ metadata.gz: 4d5cd134c942319d0ecb83fb39b89cf8a42c3cacc9c4336eaf592b0170a4257e597ce5c62e4fdb35b4641f2446e206c79da4b012c009516547ff7ae464745975
7
+ data.tar.gz: cd6cdb5059adf3ed20ea6b9625d314f0519c338b0f01b8abb1ea73ecb8c5cb183b0288e1cdbdb22482d8fb71945b26f4761911c606bb81ce62008cb3ee984742
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 0.6.0
2
+ - Reorganize native exntesion codes.
3
+ - Remove dependent gem's type declaration file from installation files.
4
+ - Update documentations.
5
+ - Introduce conventional commits.
6
+
1
7
  # 0.5.1
2
8
  - Fix version specifier of runtime dependencies.
3
9
 
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2019-2021 Atsushi Tatsuma
1
+ Copyright (c) 2019-2022 Atsushi Tatsuma
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
data/README.md CHANGED
@@ -61,6 +61,6 @@ Or install it yourself as:
61
61
  Bug reports and pull requests are welcome on GitHub at https://github.com/yoshoku/magro.
62
62
  This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
63
63
 
64
- ## Code of Conduct
64
+ ## License
65
65
 
66
- Everyone interacting in the Magro project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/yoshoku/magro/blob/main/CODE_OF_CONDUCT.md).
66
+ The gem is available as open source under the terms of the [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause).
data/ext/magro/extconf.rb CHANGED
@@ -8,10 +8,7 @@ $LOAD_PATH.each do |lp|
8
8
  end
9
9
  end
10
10
 
11
- unless have_header('numo/narray.h')
12
- puts 'numo/narray.h not found.'
13
- exit(1)
14
- end
11
+ abort 'numo/narray.h not found.' unless have_header('numo/narray.h')
15
12
 
16
13
  if RUBY_PLATFORM =~ /mswin|cygwin|mingw/
17
14
  $LOAD_PATH.each do |lp|
@@ -20,35 +17,14 @@ if RUBY_PLATFORM =~ /mswin|cygwin|mingw/
20
17
  break
21
18
  end
22
19
  end
23
- unless have_library('narray', 'nary_new')
24
- puts 'libnarray.a not found.'
25
- exit(1)
26
- end
27
- end
28
-
29
- unless have_header('setjmp.h')
30
- puts 'setjmp.h not found.'
31
- exit(1)
32
- end
33
-
34
- unless have_header('png.h')
35
- puts 'png.h not found.'
36
- exit(1)
20
+ abort 'libnarray.a not found.' unless have_library('narray', 'nary_new')
37
21
  end
38
22
 
39
- unless have_header('jpeglib.h')
40
- puts 'jpeglib.h not found.'
41
- exit(1)
42
- end
23
+ abort 'setjmp.h not found.' unless have_header('setjmp.h')
24
+ abort 'png.h not found.' unless have_header('png.h')
25
+ abort 'libpng not found.' unless have_library('png')
43
26
 
44
- unless have_library('png')
45
- puts 'libpng not found.'
46
- exit(1)
47
- end
48
-
49
- unless have_library('jpeg')
50
- puts 'libjpeg not found.'
51
- exit(1)
52
- end
27
+ abort 'jpeglib.h not found.' unless have_header('jpeglib.h')
28
+ abort 'libjpeg not found.' unless have_library('jpeg')
53
29
 
54
30
  create_makefile('magro/magro')
data/ext/magro/magro.c CHANGED
@@ -1,9 +1,462 @@
1
+ /**
2
+ * Copyright (c) 2019-2022 Atsushi Tatsuma
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * * Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * * Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * * Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
1
31
  #include "magro.h"
2
32
 
3
33
  VALUE mMagro;
34
+ VALUE mMagroIO;
35
+
36
+ static VALUE magro_io_read_png(VALUE self, VALUE filename_) {
37
+ char* filename = StringValuePtr(filename_);
38
+ FILE* file_ptr = fopen(filename, "rb");
39
+ unsigned char header[8];
40
+ png_structp png_ptr;
41
+ png_infop info_ptr;
42
+ png_bytep* row_ptr_ptr;
43
+ png_bytep row_ptr;
44
+ png_uint_32 width, height;
45
+ int color_type;
46
+ int bit_depth;
47
+ png_uint_32 y;
48
+ int n_dims = 0;
49
+ int n_ch;
50
+ size_t shape[3] = {0};
51
+ VALUE nary;
52
+ uint8_t* nary_ptr;
53
+
54
+ if (file_ptr == NULL) {
55
+ rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
56
+ return Qnil;
57
+ }
58
+
59
+ if (fread(header, 1, 8, file_ptr) < 8) {
60
+ fclose(file_ptr);
61
+ rb_raise(rb_eIOError, "Failed to read header info '%s'", filename);
62
+ return Qnil;
63
+ }
64
+
65
+ if (png_sig_cmp(header, 0, 8)) {
66
+ fclose(file_ptr);
67
+ rb_raise(rb_eIOError, "Failed to read header info '%s'", filename);
68
+ return Qnil;
69
+ }
70
+
71
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
72
+ if (png_ptr == NULL) {
73
+ fclose(file_ptr);
74
+ rb_raise(rb_eNoMemError, "Failed to allocate memory.");
75
+ return Qnil;
76
+ }
77
+ info_ptr = png_create_info_struct(png_ptr);
78
+ if (info_ptr == NULL) {
79
+ png_destroy_read_struct(&png_ptr, NULL, NULL);
80
+ fclose(file_ptr);
81
+ rb_raise(rb_eNoMemError, "Failed to allocate memory.");
82
+ return Qnil;
83
+ }
84
+ if (setjmp(png_jmpbuf(png_ptr))) {
85
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
86
+ fclose(file_ptr);
87
+ rb_raise(rb_eIOError, "Error happened while reading file '%s'", filename);
88
+ return Qnil;
89
+ }
90
+
91
+ png_init_io(png_ptr, file_ptr);
92
+ png_set_sig_bytes(png_ptr, 8);
93
+
94
+ png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_16, NULL);
95
+ row_ptr_ptr = png_get_rows(png_ptr, info_ptr);
96
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
97
+
98
+ if (color_type == PNG_COLOR_TYPE_PALETTE) {
99
+ png_set_palette_to_rgb(png_ptr);
100
+ png_read_update_info(png_ptr, info_ptr);
101
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
102
+ }
103
+
104
+ switch (color_type) {
105
+ case PNG_COLOR_TYPE_GRAY:
106
+ n_ch = 1;
107
+ n_dims = 2;
108
+ shape[0] = height;
109
+ shape[1] = width;
110
+ break;
111
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
112
+ n_ch = 2;
113
+ n_dims = 3;
114
+ shape[0] = height;
115
+ shape[1] = width;
116
+ shape[2] = 2;
117
+ break;
118
+ case PNG_COLOR_TYPE_RGB:
119
+ n_ch = 3;
120
+ n_dims = 3;
121
+ shape[0] = height;
122
+ shape[1] = width;
123
+ shape[2] = 3;
124
+ break;
125
+ case PNG_COLOR_TYPE_RGB_ALPHA:
126
+ n_ch = 4;
127
+ n_dims = 3;
128
+ shape[0] = height;
129
+ shape[1] = width;
130
+ shape[2] = 4;
131
+ break;
132
+ default:
133
+ n_dims = 0;
134
+ break;
135
+ }
136
+
137
+ if (n_dims == 0) {
138
+ fclose(file_ptr);
139
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
140
+ rb_raise(rb_eIOError, "Unsupported color type of input file '%s'", filename);
141
+ return Qnil;
142
+ }
143
+
144
+ nary = rb_narray_new(numo_cUInt8, n_dims, shape);
145
+ nary_ptr = (uint8_t*)na_get_pointer_for_write(nary);
146
+
147
+ for (y = 0; y < height; y++) {
148
+ row_ptr = row_ptr_ptr[y];
149
+ memcpy(nary_ptr + y * width * n_ch, row_ptr, width * n_ch);
150
+ }
151
+
152
+ fclose(file_ptr);
153
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
154
+
155
+ RB_GC_GUARD(filename_);
156
+
157
+ return nary;
158
+ }
159
+
160
+ static VALUE magro_io_save_png(VALUE self, VALUE filename_, VALUE image) {
161
+ char* filename = StringValuePtr(filename_);
162
+ FILE* file_ptr = fopen(filename, "wb");
163
+ png_structp png_ptr;
164
+ png_infop info_ptr;
165
+ png_bytep* row_ptr_ptr;
166
+ png_uint_32 width, height;
167
+ int color_type;
168
+ int bit_depth = 8;
169
+ png_uint_32 y;
170
+ int n_ch;
171
+ int n_dims;
172
+ narray_t* image_nary;
173
+ uint8_t* image_ptr;
174
+
175
+ if (file_ptr == NULL) {
176
+ rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
177
+ return Qfalse;
178
+ }
179
+
180
+ if (CLASS_OF(image) != numo_cUInt8) image = rb_funcall(numo_cUInt8, rb_intern("cast"), 1, image);
181
+ if (!RTEST(nary_check_contiguous(image))) image = nary_dup(image);
182
+
183
+ GetNArray(image, image_nary);
184
+ n_dims = NA_NDIM(image_nary);
185
+ height = (png_uint_32)NA_SHAPE(image_nary)[0];
186
+ width = (png_uint_32)NA_SHAPE(image_nary)[1];
187
+ image_ptr = (uint8_t*)na_get_pointer_for_read(image);
188
+ n_ch = n_dims == 3 ? (int)NA_SHAPE(image_nary)[2] : 1;
189
+
190
+ switch (n_ch) {
191
+ case 4:
192
+ color_type = PNG_COLOR_TYPE_RGBA;
193
+ break;
194
+ case 3:
195
+ color_type = PNG_COLOR_TYPE_RGB;
196
+ break;
197
+ case 2:
198
+ color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
199
+ break;
200
+ default:
201
+ color_type = PNG_COLOR_TYPE_GRAY;
202
+ break;
203
+ }
204
+
205
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
206
+ if (png_ptr == NULL) {
207
+ fclose(file_ptr);
208
+ rb_raise(rb_eNoMemError, "Failed to allocate memory.");
209
+ return Qfalse;
210
+ }
211
+ info_ptr = png_create_info_struct(png_ptr);
212
+ if (info_ptr == NULL) {
213
+ png_destroy_read_struct(&png_ptr, NULL, NULL);
214
+ fclose(file_ptr);
215
+ rb_raise(rb_eNoMemError, "Failed to allocate memory.");
216
+ return Qfalse;
217
+ }
218
+ if (setjmp(png_jmpbuf(png_ptr))) {
219
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
220
+ fclose(file_ptr);
221
+ return Qfalse;
222
+ }
223
+
224
+ png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
225
+ PNG_FILTER_TYPE_DEFAULT);
226
+
227
+ row_ptr_ptr = png_malloc(png_ptr, height * sizeof(png_bytep));
228
+ for (y = 0; y < height; y++) {
229
+ row_ptr_ptr[y] = png_malloc(png_ptr, width * n_ch * sizeof(png_byte));
230
+ memcpy(row_ptr_ptr[y], image_ptr + y * width * n_ch, width * n_ch);
231
+ }
232
+
233
+ png_init_io(png_ptr, file_ptr);
234
+ png_set_rows(png_ptr, info_ptr, row_ptr_ptr);
235
+ png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
236
+
237
+ fclose(file_ptr);
238
+ for (y = 0; y < height; y++) png_free(png_ptr, row_ptr_ptr[y]);
239
+ png_free(png_ptr, row_ptr_ptr);
240
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
241
+
242
+ RB_GC_GUARD(image);
243
+ RB_GC_GUARD(filename_);
244
+
245
+ return Qtrue;
246
+ }
247
+
248
+ struct my_error_mgr {
249
+ struct jpeg_error_mgr pub;
250
+ jmp_buf setjmp_buffer;
251
+ };
252
+
253
+ static void my_error_exit(j_common_ptr cinfo) {
254
+ struct my_error_mgr* my_err = (struct my_error_mgr*)cinfo->err;
255
+ (*cinfo->err->output_message)(cinfo);
256
+ longjmp(my_err->setjmp_buffer, 1);
257
+ }
258
+
259
+ static VALUE magro_io_read_jpg(VALUE self, VALUE filename_) {
260
+ char* filename = StringValuePtr(filename_);
261
+ FILE* file_ptr = fopen(filename, "rb");
262
+ struct jpeg_decompress_struct jpeg;
263
+ struct my_error_mgr err;
264
+ unsigned int width, height;
265
+ int n_colors;
266
+ size_t shape[3] = {0};
267
+ int n_dims;
268
+ unsigned int y;
269
+ VALUE nary;
270
+ uint8_t* nary_ptr;
271
+ JSAMPLE* tmp;
272
+
273
+ if (file_ptr == NULL) {
274
+ rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
275
+ return Qnil;
276
+ }
277
+
278
+ jpeg.err = jpeg_std_error(&err.pub);
279
+ err.pub.error_exit = my_error_exit;
280
+ if (setjmp(err.setjmp_buffer)) {
281
+ rb_raise(rb_eIOError, "Error happened while reading file '%s'", filename);
282
+ return Qnil;
283
+ }
284
+
285
+ jpeg_create_decompress(&jpeg);
286
+ jpeg_stdio_src(&jpeg, file_ptr);
287
+ jpeg_read_header(&jpeg, TRUE);
288
+ jpeg_start_decompress(&jpeg);
289
+
290
+ width = jpeg.output_width;
291
+ height = jpeg.output_height;
292
+ n_colors = jpeg.out_color_components;
293
+
294
+ n_dims = n_colors == 1 ? 2 : 3;
295
+ shape[0] = height;
296
+ shape[1] = width;
297
+ shape[2] = n_colors;
298
+ nary = rb_narray_new(numo_cUInt8, n_dims, shape);
299
+ nary_ptr = (uint8_t*)na_get_pointer_for_write(nary);
300
+
301
+ for (y = 0; y < height; y++) {
302
+ tmp = nary_ptr + y * width * n_colors;
303
+ jpeg_read_scanlines(&jpeg, &tmp, 1);
304
+ }
305
+
306
+ fclose(file_ptr);
307
+ jpeg_finish_decompress(&jpeg);
308
+ jpeg_destroy_decompress(&jpeg);
309
+
310
+ RB_GC_GUARD(filename_);
311
+
312
+ return nary;
313
+ }
314
+
315
+ static VALUE magro_io_save_jpg(int argc, VALUE* argv, VALUE self) {
316
+ VALUE filename_;
317
+ VALUE image;
318
+ VALUE quality_;
319
+ char* filename;
320
+ FILE* file_ptr;
321
+ struct jpeg_compress_struct jpeg;
322
+ struct my_error_mgr err;
323
+ narray_t* image_nary;
324
+ int quality;
325
+ int n_dims, n_ch;
326
+ unsigned int width, height, y;
327
+ uint8_t* image_ptr;
328
+ JSAMPLE* tmp;
329
+
330
+ rb_scan_args(argc, argv, "21", &filename_, &image, &quality_);
331
+
332
+ quality = NIL_P(quality_) ? 95 : NUM2INT(quality_);
333
+
334
+ filename = StringValuePtr(filename_);
335
+
336
+ if (CLASS_OF(image) != numo_cUInt8) image = rb_funcall(numo_cUInt8, rb_intern("cast"), 1, image);
337
+ if (!RTEST(nary_check_contiguous(image))) image = nary_dup(image);
338
+
339
+ jpeg.err = jpeg_std_error(&err.pub);
340
+ err.pub.error_exit = my_error_exit;
341
+ if (setjmp(err.setjmp_buffer)) return Qfalse;
342
+
343
+ jpeg_create_compress(&jpeg);
344
+
345
+ file_ptr = fopen(filename, "wb");
346
+ if (file_ptr == NULL) {
347
+ rb_raise(rb_eIOError, "Failed to open file '%s'", filename);
348
+ jpeg_destroy_compress(&jpeg);
349
+ return Qfalse;
350
+ }
351
+
352
+ GetNArray(image, image_nary);
353
+ n_dims = NA_NDIM(image_nary);
354
+ height = (unsigned int)NA_SHAPE(image_nary)[0];
355
+ width = (unsigned int)NA_SHAPE(image_nary)[1];
356
+ image_ptr = (uint8_t*)na_get_pointer_for_read(image);
357
+ n_ch = n_dims == 3 ? (int)NA_SHAPE(image_nary)[2] : 1;
358
+
359
+ jpeg_stdio_dest(&jpeg, file_ptr);
360
+
361
+ jpeg.image_height = height;
362
+ jpeg.image_width = width;
363
+ jpeg.input_components = n_ch;
364
+
365
+ switch (n_ch) {
366
+ case 3:
367
+ jpeg.in_color_space = JCS_RGB;
368
+ break;
369
+ case 1:
370
+ jpeg.in_color_space = JCS_GRAYSCALE;
371
+ break;
372
+ default:
373
+ jpeg.in_color_space = JCS_UNKNOWN;
374
+ break;
375
+ }
376
+
377
+ jpeg_set_defaults(&jpeg);
378
+
379
+ jpeg_set_quality(&jpeg, quality, TRUE);
380
+
381
+ jpeg_start_compress(&jpeg, TRUE);
382
+
383
+ for (y = 0; y < height; y++) {
384
+ tmp = image_ptr + y * width * n_ch;
385
+ jpeg_write_scanlines(&jpeg, &tmp, 1);
386
+ }
387
+
388
+ jpeg_finish_compress(&jpeg);
389
+ jpeg_destroy_compress(&jpeg);
390
+
391
+ fclose(file_ptr);
392
+
393
+ RB_GC_GUARD(image);
394
+ RB_GC_GUARD(filename_);
395
+
396
+ return Qtrue;
397
+ }
4
398
 
5
399
  void Init_magro() {
400
+ /**
401
+ * Document-module: Magro
402
+ * Magro is an image processing library in Ruby.
403
+ */
6
404
  mMagro = rb_define_module("Magro");
7
-
8
- init_io_module();
405
+ /**
406
+ * Document-module: Magro::IO
407
+ * IO module provides functions for input and output of image file.
408
+ */
409
+ mMagroIO = rb_define_module_under(mMagro, "IO");
410
+ /**
411
+ * @!visibility private
412
+ *
413
+ * Loads PNG image file.
414
+ *
415
+ * @overload read_png(filename) -> Numo::UInt8
416
+ * @param filename [String] File path of PNG image file.
417
+ *
418
+ * @raise [IOError] This error is raised when failed to read image file.
419
+ * @raise [NoMemoryError] If memory allocation of image data fails, this error is raised.
420
+ * @return [Numo::UInt8] (shape: [height, width, n_channels]) Loaded image.
421
+ */
422
+ rb_define_module_function(mMagroIO, "read_png", RUBY_METHOD_FUNC(magro_io_read_png), 1);
423
+ /**
424
+ * @!visibility private
425
+ *
426
+ * Saves PNG image file.
427
+ *
428
+ * @overload save_png(filename, image) -> Boolean
429
+ * @param filename [String] Path to image file to be saved.
430
+ * @param image [Numo::UInt8] (shape: [height, width, n_channels]) Image data to be saved.
431
+ *
432
+ * @raise [IOError] This error is raised when failed to write image file.
433
+ * @raise [NoMemoryError] If memory allocation of image data fails, this error is raised.
434
+ * @return [Boolean] true if file save is successful.
435
+ */
436
+ rb_define_module_function(mMagroIO, "save_png", RUBY_METHOD_FUNC(magro_io_save_png), 2);
437
+ /**
438
+ * @!visibility private
439
+ *
440
+ * Loads JPEG image file.
441
+ *
442
+ * @overload read_jpg(filename) -> Numo::UInt8
443
+ * @param filename [String] File path of JPEG image file.
444
+ *
445
+ * @raise [IOError] This error is raised when failed to read image file.
446
+ * @return [Numo::UInt8] (shape: [height, width, n_channels]) Loaded image.
447
+ */
448
+ rb_define_module_function(mMagroIO, "read_jpg", RUBY_METHOD_FUNC(magro_io_read_jpg), 1);
449
+ /**
450
+ * @!visibility private
451
+ *
452
+ * Saves JPEG image file.
453
+ *
454
+ * @overload save_jpg(filename, image, quality) -> Boolean
455
+ * @param filename [String] Path to image file to be saved.
456
+ * @param image [Numo::UInt8] (shape: [height, width, n_channels]) Image data to be saved.
457
+ * @param quality [Integer/Nil] Quality parameter of jpeg image that takes a value between 0 to 100.
458
+ *
459
+ * @return [Boolean] true if file save is successful.
460
+ */
461
+ rb_define_module_function(mMagroIO, "save_jpg", RUBY_METHOD_FUNC(magro_io_save_jpg), -1);
9
462
  }
data/ext/magro/magro.h CHANGED
@@ -1,8 +1,48 @@
1
+ /**
2
+ * Copyright (c) 2019-2022 Atsushi Tatsuma
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * * Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * * Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * * Neither the name of the copyright holder nor the names of its
16
+ * contributors may be used to endorse or promote products derived from
17
+ * this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
1
31
  #ifndef MAGRO_H
2
32
  #define MAGRO_H 1
3
33
 
34
+ #include <stdio.h>
35
+ #include <stdlib.h>
36
+ #include <string.h>
37
+
38
+ #include <setjmp.h>
39
+
40
+ #include <jpeglib.h>
41
+ #include <png.h>
42
+
4
43
  #include <ruby.h>
5
44
 
6
- #include "imgrw.h"
45
+ #include <numo/narray.h>
46
+ #include <numo/template.h>
7
47
 
8
48
  #endif /* MAGRO_H */
data/lib/magro/io.rb CHANGED
@@ -48,7 +48,7 @@ module Magro
48
48
  # @param image [Numo::UInt8] (shape: [height, width, n_channels]) Image data to be saved.
49
49
  # @param quality [Integer] Quality parameter of jpeg image that takes a value between 0 to 100.
50
50
  # @raise [ArgumentError] If filename is not String or image is not Numo::NArray, this error is raised.
51
- # @raise [IOError] This error is raised when failed to read image file.
51
+ # @raise [IOError] This error is raised when failed to write image file.
52
52
  # @raise [NoMemoryError] If memory allocation of image data fails, this error is raised.
53
53
  # @return [Boolean] true if file save is successful.
54
54
  def imsave(filename, image, quality: nil)
data/lib/magro/version.rb CHANGED
@@ -3,5 +3,5 @@
3
3
  # Magro is an image processing library in Ruby.
4
4
  module Magro
5
5
  # The version of Magro you are using.
6
- VERSION = '0.5.1'
6
+ VERSION = '0.6.0'
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: magro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-28 00:00:00.000000000 Z
11
+ date: 2022-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
@@ -36,24 +36,10 @@ extensions:
36
36
  - ext/magro/extconf.rb
37
37
  extra_rdoc_files: []
38
38
  files:
39
- - ".clang-format"
40
- - ".coveralls.yml"
41
- - ".github/workflows/build.yml"
42
- - ".github/workflows/coverage.yml"
43
- - ".gitignore"
44
- - ".rspec"
45
39
  - CHANGELOG.md
46
- - CODE_OF_CONDUCT.md
47
- - Gemfile
48
40
  - LICENSE.txt
49
41
  - README.md
50
- - Rakefile
51
- - Steepfile
52
- - bin/console
53
- - bin/setup
54
42
  - ext/magro/extconf.rb
55
- - ext/magro/imgrw.c
56
- - ext/magro/imgrw.h
57
43
  - ext/magro/magro.c
58
44
  - ext/magro/magro.h
59
45
  - lib/magro.rb
@@ -61,12 +47,10 @@ files:
61
47
  - lib/magro/io.rb
62
48
  - lib/magro/transform.rb
63
49
  - lib/magro/version.rb
64
- - magro.gemspec
65
50
  - sig/magro.rbs
66
51
  - sig/magro/filter.rbs
67
52
  - sig/magro/io.rbs
68
53
  - sig/magro/transform.rbs
69
- - sig/patch.rbs
70
54
  homepage: https://github.com/yoshoku/magro
71
55
  licenses:
72
56
  - BSD-3-Clause
@@ -75,7 +59,7 @@ metadata:
75
59
  source_code_uri: https://github.com/yoshoku/magro
76
60
  changelog_uri: https://github.com/yoshoku/magro/blob/main/CHANGELOG.md
77
61
  documentation_uri: https://yoshoku.github.io/magro/doc/
78
- post_install_message:
62
+ post_install_message:
79
63
  rdoc_options: []
80
64
  require_paths:
81
65
  - lib
@@ -90,8 +74,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
74
  - !ruby/object:Gem::Version
91
75
  version: '0'
92
76
  requirements: []
93
- rubygems_version: 3.2.21
94
- signing_key:
77
+ rubygems_version: 3.3.3
78
+ signing_key:
95
79
  specification_version: 4
96
80
  summary: Magro is a minimal image processing library for Ruby.
97
81
  test_files: []