rfreeimage 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cba7a3c8f1d3088123e1bacc6249d39dc1e66d3f
4
- data.tar.gz: 972756e89b9b5dd293b213048fac8d1c9aa5a5bf
3
+ metadata.gz: d8d7e7bca8f13f158da2617a15667627c8a0c31a
4
+ data.tar.gz: 638dacb99a69891c7cbd5112e31a4c9b13e28680
5
5
  SHA512:
6
- metadata.gz: ae36dad83c8068efe7919391ad3f637c08f5ce8ee67201a215d0d5c9accf1bfd7404925c932982126bddde44af2234bf36d9e1bfc95a31421960ea2112ee25c6
7
- data.tar.gz: f439d72b5a1a953276de0648cfa2d8b6e047670a3dc81522071039703cb2d7e6b4eba17a933cce5b23efdb4ba22d4c582fb4548261457881d6b1a7f48f6ca2f6
6
+ metadata.gz: af82826b1c9556159e616dca72a0e639dd7897b8aa9e00934cd2ffb62e24710b9f2956afae22ecb862f63548bb2b48754e760dda623b07e7fe4b4079cb0884e5
7
+ data.tar.gz: cdab92f66f9dcb575d3d429e63e3eaef0b8c5770ae703ddab435a244a4972d19bd496662de6a7483beaaf9efcff0948baaaf695018df1c5dfd5c41f611cc5d70
@@ -6,6 +6,16 @@ static VALUE rb_mFI;
6
6
  static VALUE Class_Image;
7
7
  static VALUE Class_RFIError;
8
8
 
9
+ __attribute__((constructor))
10
+ static void __rfi_module_init() {
11
+ FreeImage_Initialise(FALSE);
12
+ }
13
+
14
+ __attribute__((destructor))
15
+ static void __rfi_module_uninit() {
16
+ FreeImage_DeInitialise();
17
+ }
18
+
9
19
  static VALUE rb_rfi_version(VALUE self)
10
20
  {
11
21
  return rb_ary_new3(3, INT2NUM(FREEIMAGE_MAJOR_VERSION),
@@ -20,14 +30,6 @@ static VALUE rb_rfi_string_version(VALUE self)
20
30
  return result;
21
31
  }
22
32
 
23
- static VALUE
24
- file_arg_rescue(VALUE arg)
25
- {
26
- rb_raise(rb_eTypeError, "argument must be path name or open file (%s given)",
27
- rb_class2name(CLASS_OF(arg)));
28
- return(VALUE)0;
29
- }
30
-
31
33
  struct native_image {
32
34
  int w;
33
35
  int h;
@@ -60,6 +62,7 @@ static inline char *rfi_value_to_str(VALUE v)
60
62
  {
61
63
  char *filename;
62
64
  long f_len;
65
+ Check_Type(v, T_STRING);
63
66
  f_len = RSTRING_LEN(v);
64
67
  filename = malloc(f_len + 1);
65
68
  memcpy(filename, RSTRING_PTR(v), f_len);
@@ -67,14 +70,28 @@ static inline char *rfi_value_to_str(VALUE v)
67
70
  return filename;
68
71
  }
69
72
 
73
+ static FIBITMAP *
74
+ convert_bpp(FIBITMAP *orig, unsigned int bpp) {
75
+ FIBITMAP *h = NULL;
76
+ switch(bpp) {
77
+ case 8:
78
+ h = FreeImage_ConvertToGreyscale(orig);
79
+ break;
80
+ case 32:
81
+ h = FreeImage_ConvertTo32Bits(orig);
82
+ break;
83
+ }
84
+ return h;
85
+ }
86
+
70
87
  static void
71
88
  rd_image(VALUE clazz, VALUE file, struct native_image *img, unsigned int bpp, BOOL ping)
72
89
  {
73
90
  char *filename;
91
+ int flags = 0;
74
92
  FIBITMAP *h = NULL, *orig = NULL;
75
93
  FREE_IMAGE_FORMAT in_fif;
76
94
 
77
- file = rb_rescue(rb_String, file, file_arg_rescue, file);
78
95
  filename = rfi_value_to_str(file);
79
96
 
80
97
  in_fif = FreeImage_GetFileType(filename, 0);
@@ -83,33 +100,62 @@ rd_image(VALUE clazz, VALUE file, struct native_image *img, unsigned int bpp, BO
83
100
  rb_raise(rb_eIOError, "Invalid image file");
84
101
  }
85
102
 
86
- orig = FreeImage_Load(in_fif, filename, ping ? FIF_LOAD_NOPIXELS : 0 );
103
+ if (ping) flags |= FIF_LOAD_NOPIXELS;
104
+ if (in_fif == FIF_JPEG) flags |= JPEG_EXIFROTATE;
105
+ orig = FreeImage_Load(in_fif, filename, flags);
87
106
  free(filename);
88
107
  if (!orig)
89
108
  rb_raise(rb_eIOError, "Fail to load image file");
90
- if (FreeImage_GetBPP(orig) == bpp || bpp <= 0 || ping) {
109
+ if (ping) {
91
110
  h = orig;
92
111
  } else {
93
- switch(bpp) {
94
- case 8:
95
- h = FreeImage_ConvertTo8Bits(orig);
96
- break;
97
- case 24:
98
- h = FreeImage_ConvertTo24Bits(orig);
99
- break;
100
- case 32:
101
- h = FreeImage_ConvertTo32Bits(orig);
102
- break;
103
- default:
104
- rb_raise(rb_eArgError, "Invalid bpp");
105
- }
112
+ if (bpp <= 0) bpp = 32;
113
+ h = convert_bpp(orig, bpp);
114
+ FreeImage_Unload(orig);
115
+ if (!h) rb_raise(rb_eArgError, "Invalid bpp");
116
+ }
117
+ img->handle = h;
118
+ img->w = FreeImage_GetWidth(h);
119
+ img->h = FreeImage_GetHeight(h);
120
+ img->bpp = FreeImage_GetBPP(h);
121
+ img->stride = FreeImage_GetPitch(h);
122
+ img->fif = in_fif;
123
+ }
124
+
125
+ static void
126
+ rd_image_blob(VALUE clazz, VALUE blob, struct native_image *img, unsigned int bpp, BOOL ping)
127
+ {
128
+ FIBITMAP *h = NULL, *orig = NULL;
129
+ FIMEMORY *fmh;
130
+ FREE_IMAGE_FORMAT in_fif;
131
+
132
+ Check_Type(blob, T_STRING);
133
+ fmh = FreeImage_OpenMemory((BYTE*)RSTRING_PTR(blob), RSTRING_LEN(blob));
134
+
135
+ in_fif = FreeImage_GetFileTypeFromMemory(fmh, 0);
136
+ if (in_fif == FIF_UNKNOWN) {
137
+ FreeImage_CloseMemory(fmh);
138
+ rb_raise(rb_eIOError, "Invalid image blob");
139
+ }
140
+
141
+ orig = FreeImage_LoadFromMemory(in_fif, fmh, ping ? FIF_LOAD_NOPIXELS : 0 );
142
+ FreeImage_CloseMemory(fmh);
143
+ if (!orig)
144
+ rb_raise(rb_eIOError, "Fail to load image from memory");
145
+
146
+ if (ping) {
147
+ h = orig;
148
+ } else {
149
+ if (bpp <= 0) bpp = 32;
150
+ h = convert_bpp(orig, bpp);
106
151
  FreeImage_Unload(orig);
152
+ if (!h) rb_raise(rb_eArgError, "Invalid bpp");
107
153
  }
108
154
  img->handle = h;
109
155
  img->w = FreeImage_GetWidth(h);
110
156
  img->h = FreeImage_GetHeight(h);
111
157
  img->bpp = FreeImage_GetBPP(h);
112
- img->stride = FreeImage_GetLine(h);
158
+ img->stride = FreeImage_GetPitch(h);
113
159
  img->fif = in_fif;
114
160
  }
115
161
 
@@ -119,7 +165,6 @@ VALUE Image_initialize(int argc, VALUE *argv, VALUE self)
119
165
  /* unwrap */
120
166
  Data_Get_Struct(self, struct native_image, img);
121
167
 
122
- memset(img, 0, sizeof(struct native_image));
123
168
  switch (argc)
124
169
  {
125
170
  case 1:
@@ -149,7 +194,7 @@ VALUE Image_save(VALUE self, VALUE file)
149
194
  Data_Get_Struct(self, struct native_image, img);
150
195
  RFI_CHECK_IMG(img);
151
196
 
152
- file = rb_rescue(rb_String, file, file_arg_rescue, file);
197
+ Check_Type(file, T_STRING);
153
198
  filename = rfi_value_to_str(file);
154
199
 
155
200
  out_fif = FreeImage_GetFIFFromFilename(filename);
@@ -158,7 +203,14 @@ VALUE Image_save(VALUE self, VALUE file)
158
203
  rb_raise(Class_RFIError, "Invalid format");
159
204
  }
160
205
 
161
- result = FreeImage_Save(out_fif, img->handle, filename, 0);
206
+ if (out_fif == FIF_JPEG && img->bpp != 8 && img->bpp != 24) {
207
+ FIBITMAP *to_save = FreeImage_ConvertTo24Bits(img->handle);
208
+ result = FreeImage_Save(out_fif, to_save, filename, JPEG_BASELINE);
209
+ FreeImage_Unload(to_save);
210
+ } else {
211
+ result = FreeImage_Save(out_fif, img->handle, filename, 0);
212
+ }
213
+
162
214
  free(filename);
163
215
 
164
216
  if(!result)
@@ -219,11 +271,25 @@ VALUE Image_read_bytes(VALUE self)
219
271
  {
220
272
  struct native_image* img;
221
273
  const char *p;
274
+ char *ptr;
275
+ unsigned stride_dst;
276
+ int i;
277
+ VALUE v;
222
278
 
223
279
  Data_Get_Struct(self, struct native_image, img);
224
280
  RFI_CHECK_IMG(img);
225
281
  p = (const char*)FreeImage_GetBits(img->handle);
226
- return rb_str_new(p, img->stride * img->h);
282
+ stride_dst = img->w * (img->bpp / 8);
283
+ v = rb_str_new(NULL, stride_dst * img->h);
284
+
285
+ /* up-side-down */
286
+ ptr = RSTRING_PTR(v) + img->h * stride_dst;
287
+ for(i = 0; i < img->h; i++) {
288
+ ptr -= stride_dst;
289
+ memcpy(ptr, p, stride_dst);
290
+ p += img->stride;
291
+ }
292
+ return v;
227
293
  }
228
294
 
229
295
  VALUE Image_buffer_addr(VALUE self)
@@ -251,7 +317,7 @@ static inline VALUE rfi_get_image(FIBITMAP *nh)
251
317
  new_img = malloc(sizeof(struct native_image));
252
318
  memset(new_img, 0, sizeof(struct native_image));
253
319
  new_img->handle = nh;
254
- new_img->stride = FreeImage_GetLine(nh);
320
+ new_img->stride = FreeImage_GetPitch(nh);
255
321
  new_img->bpp = FreeImage_GetBPP(nh);
256
322
  new_img->w = FreeImage_GetWidth(nh);
257
323
  new_img->h = FreeImage_GetHeight(nh);
@@ -266,20 +332,12 @@ VALUE Image_to_bpp(VALUE self, VALUE _bpp)
266
332
  int bpp = NUM2INT(_bpp);
267
333
  Data_Get_Struct(self, struct native_image, img);
268
334
  RFI_CHECK_IMG(img);
335
+ if (bpp == img->bpp)
336
+ return self;
337
+
338
+ nh = convert_bpp(img->handle, bpp);
339
+ if (!nh) rb_raise(rb_eArgError, "Invalid bpp");
269
340
 
270
- switch(bpp) {
271
- case 8:
272
- nh = FreeImage_ConvertTo8Bits(img->handle);
273
- break;
274
- case 24:
275
- nh = FreeImage_ConvertTo24Bits(img->handle);
276
- break;
277
- case 32:
278
- nh = FreeImage_ConvertTo32Bits(img->handle);
279
- break;
280
- default:
281
- rb_raise(rb_eArgError, "Invalid bpp");
282
- }
283
341
  return rfi_get_image(nh);
284
342
  }
285
343
 
@@ -342,18 +400,115 @@ VALUE Image_crop(VALUE self, VALUE _left, VALUE _top, VALUE _right, VALUE _botto
342
400
  return rfi_get_image(nh);
343
401
  }
344
402
 
403
+ #define ALLOC_NEW_IMAGE(__v, img) \
404
+ VALUE __v = Image_alloc(Class_Image); \
405
+ struct native_image* img; \
406
+ Data_Get_Struct(__v, struct native_image, img) \
407
+
345
408
  VALUE Image_ping(VALUE self, VALUE file)
346
409
  {
347
- struct native_image* img = malloc(sizeof(struct native_image));
410
+ ALLOC_NEW_IMAGE(v, img);
411
+
348
412
  rd_image(self, file, img, 0, 1);
413
+ if (img->handle)
414
+ FreeImage_Unload(img->handle);
415
+ img->handle = NULL;
416
+
417
+ return v;
418
+ }
419
+
420
+ VALUE Image_from_blob(int argc, VALUE *argv, VALUE self)
421
+ {
422
+ ALLOC_NEW_IMAGE(v, img);
349
423
 
424
+ switch (argc)
425
+ {
426
+ case 1:
427
+ rd_image_blob(self, argv[0], img, 0, 0);
428
+ break;
429
+ case 2:
430
+ rd_image_blob(self, argv[0], img, NUM2INT(argv[1]), 0);
431
+ break;
432
+ default:
433
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
434
+ break;
435
+ }
436
+
437
+ return v;
438
+ }
439
+
440
+ VALUE Image_ping_blob(VALUE self, VALUE blob)
441
+ {
442
+ ALLOC_NEW_IMAGE(v, img);
443
+
444
+ rd_image_blob(self, blob, img, 0, 1);
350
445
  if (img->handle)
351
446
  FreeImage_Unload(img->handle);
352
447
  img->handle = NULL;
353
448
 
354
- return Data_Wrap_Struct(Class_Image, NULL, Image_free, img);
449
+ return v;
450
+ }
451
+
452
+ /* draw */
453
+ VALUE Image_draw_point(VALUE self, VALUE _x, VALUE _y, VALUE color, VALUE _size)
454
+ {
455
+ struct native_image* img;
456
+ int x = NUM2INT(_x);
457
+ int y = NUM2INT(_y);
458
+ int size = NUM2INT(_size);
459
+ int hs = size / 2, i, j;
460
+ unsigned int bgra = NUM2UINT(color);
461
+ if (size < 0)
462
+ rb_raise(rb_eArgError, "Invalid point size: %d", size);
463
+ Data_Get_Struct(self, struct native_image, img);
464
+ RFI_CHECK_IMG(img);
465
+
466
+ for(i = -hs; i <= hs; i++) {
467
+ for(j = -hs; j <= hs; j++) {
468
+ if (i*i + j*j <= hs*hs)
469
+ FreeImage_SetPixelColor(img->handle, x + i, img->h - (y + j) - 1, (RGBQUAD*)&bgra);
470
+ }
471
+ }
472
+
473
+ return self;
355
474
  }
356
475
 
476
+ VALUE Image_draw_rectangle(VALUE self, VALUE _x1, VALUE _y1,
477
+ VALUE _x2, VALUE _y2,
478
+ VALUE color, VALUE _width)
479
+ {
480
+ struct native_image* img;
481
+ int x1 = NUM2INT(_x1);
482
+ int y1 = NUM2INT(_y1);
483
+ int x2 = NUM2INT(_x2);
484
+ int y2 = NUM2INT(_y2);
485
+ int size = NUM2INT(_width);
486
+ int hs = size / 2, i, j;
487
+ unsigned int bgra = NUM2UINT(color);
488
+ if (size < 0)
489
+ rb_raise(rb_eArgError, "Invalid line width: %d", size);
490
+ Data_Get_Struct(self, struct native_image, img);
491
+ RFI_CHECK_IMG(img);
492
+
493
+ for(i = -hs; i <= hs; i++) {
494
+ for(j = x1; j <= x2; j++) {
495
+ FreeImage_SetPixelColor(img->handle, j, img->h - (y1 + i) - 1, (RGBQUAD*)&bgra);
496
+ FreeImage_SetPixelColor(img->handle, j, img->h - (y2 + i) - 1, (RGBQUAD*)&bgra);
497
+ }
498
+ }
499
+
500
+ for(i = -hs; i <= hs; i++) {
501
+ for(j = y1; j <= y2; j++) {
502
+ FreeImage_SetPixelColor(img->handle, x1 + i, img->h - j - 1, (RGBQUAD*)&bgra);
503
+ FreeImage_SetPixelColor(img->handle, x2 + i, img->h - j - 1, (RGBQUAD*)&bgra);
504
+ }
505
+ }
506
+
507
+ return self;
508
+ }
509
+
510
+
511
+
357
512
  void Init_rfreeimage(void)
358
513
  {
359
514
  rb_mFI = rb_define_module("RFreeImage");
@@ -382,8 +537,11 @@ void Init_rfreeimage(void)
382
537
  rb_define_method(Class_Image, "resize", Image_resize, 2);
383
538
  rb_define_method(Class_Image, "crop", Image_crop, 4);
384
539
 
385
- rb_define_singleton_method(Class_Image, "ping", Image_ping, 1);
540
+ /* draw */
541
+ rb_define_method(Class_Image, "draw_point", Image_draw_point, 4);
542
+ rb_define_method(Class_Image, "draw_rectangle", Image_draw_rectangle, 4 + 2);
386
543
 
544
+ rb_define_singleton_method(Class_Image, "ping", Image_ping, 1);
545
+ rb_define_singleton_method(Class_Image, "from_blob", Image_from_blob, -1);
546
+ rb_define_singleton_method(Class_Image, "ping_blob", Image_ping_blob, 1);
387
547
  }
388
-
389
-
@@ -4,6 +4,16 @@ module RFreeImage
4
4
  BGR = 24
5
5
  BGRA = 32
6
6
  end
7
+ module Color
8
+ BLUE = 0xff0000ff
9
+ GREEN = 0xff00ff00
10
+ RED = 0xffff0000
11
+ YELLOW = 0xffffff00
12
+ CYAN = 0xff00ffff
13
+ WHITE = 0xffffffff
14
+ BLACK = 0xff000000
15
+ GRAY = 0xffa9a9a9
16
+ end
7
17
  class Image
8
18
  def bytes
9
19
  @bytes ||= read_bytes
@@ -15,12 +25,25 @@ module RFreeImage
15
25
  end
16
26
 
17
27
  def gray?
18
- bpp == GRAY
28
+ bpp == ImageBPP::GRAY
19
29
  end
20
30
 
21
31
  def to_gray
22
32
  return self if gray?
23
33
  to_bpp 8
24
34
  end
35
+
36
+ def bgra?
37
+ bpp == ImageBPP::BGRA
38
+ end
39
+
40
+ def to_bgra
41
+ return self if bgra?
42
+ to_bpp 32
43
+ end
44
+
45
+
46
+ alias_method :write, :save
47
+ alias_method :columns, :cols
25
48
  end
26
49
  end
@@ -1,3 +1,3 @@
1
1
  module RFreeImage
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rfreeimage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuheng Chen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-01 00:00:00.000000000 Z
11
+ date: 2015-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler