rfreeimage 0.1.0 → 0.1.1

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
  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