devil 0.1.6 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,50 @@
1
+ 2009-10-21
2
+ version 0.1.8
3
+ * made LANCZOS3 scaling filter the default for highquality thumbnails
4
+ * changed clear color to DevIL default (mother of pearl and full alpha)
5
+ * added blit function to HLA (high level API)
6
+ * added mirror, edge_detect, emboss, enlarge_canvas, etc to HLA
7
+ * added ILU_CENTER, ILU_LOWER_LEFT, ILU_PLACEMENT etc to LLA
8
+ * include ILU and IL modules in Devil::Image now
9
+ * made Devil::Image#show return self
10
+ * made Devil::Image#show use a dup of the image (so a 'snapshot' is taken of image)
11
+ * added Devil.set_options method to HLA
12
+ * refactored HLA to use an 'action' method, saved code duplication of set_binding/error_check etc.
13
+
14
+ 2009-10-17 John Mair (Banisterfiend)
15
+ * ruby_il.c added:
16
+ * constants: IMAGE_DEPTH, ORIGIN_SET, CONV_PAL, CUR_IMAGE, ORIGIN_LOWER_LEFT, ORIGIN_LOWER_RIGHT
17
+ * methods: Disable, OriginFunc, ClearColour, ClearImage.
18
+ * Modified FromBlob method to restore old binding after use.
19
+ * ruby_ilu.c added:
20
+ * methods: EnlargeCanvas, EdgeDetectP, EdgeDetectS, Emboss, Mirror, SwapColours.
21
+ * Modified Crop to now take z-axis parameters. (stick to original API as closely as possible)
22
+
23
+ 2009-10-15 John Mair (Banisterfiend)
24
+ * hopefully fixed compile errors on SnowLeopard!
25
+ * added error checking to Devil::load_image()
26
+ * added monkeypatch to Gosu::Image::new() to transparently load multiple formats
27
+ * updated some rdoc
28
+
29
+ 2009-10-13 John Mair (Banisterfiend)
30
+ * version 0.1.6
31
+ * added Gosu and TexPlay interoperability
32
+ * ...bunch of other miscellaneous functionality
33
+ * released gem
34
+
35
+ 2009-10-10 John Mair (Banisterfiend)
36
+ * constants added to ruby_il.c:
37
+ * IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_FORMAT, FILE_OVERWRITE
38
+ * functions added to ruby_il.c:
39
+ * ilEnable, ilGetInteger, ilConvertImage, ToBlob, ilCloneCurImage
40
+ * conditional compilation added to ruby_il.c for LBM constant
41
+ * functions added to ruby_ilu.c:
42
+ * ilFlipImage, ilRotate, ilCrop
43
+ * added Gosu and TexPlay interoperability
44
+ * ...bunch of other miscellaneous functionality
45
+
46
+ 2009-10-06 John Mair (Banisterfiend)
47
+ * ruby 1.9 compatibility
48
+
49
+ 2006-09-28 Jaroslaw Tworek <dev.jrx@gmail.com>
50
+ * Initial release
data/README CHANGED
@@ -1,27 +1,46 @@
1
- Devil version 0.1.6
2
- ===================
1
+ Ruby Devil version 0.1.8
2
+ ========================
3
3
 
4
4
  * Original author: Jaroslaw Tworek <dev.jrx@gmail.com>
5
- * Current maintainer: John Mair (banisterfiend) http://banisterfiend.wordpress.com
5
+ * Current maintainer: John Mair (banisterfiend) [http://banisterfiend.wordpress.com]
6
6
 
7
7
  Ruby bindings for the Developer's Image Library
8
- You need DevIL installed to build this extension
8
+ You need DevIL installed to use this extension
9
+
10
+ The Ruby Devil Project page is here: [http://github.com/banister/devil]
11
+
9
12
 
10
13
  Installation Instructions:
11
14
  ==========================
12
15
 
13
16
  For debian:
17
+
14
18
  * install the libdevil and libdevil-dev packages
15
19
 
20
+ For Gentoo:
21
+
22
+ * emerge "media-libs/devil"
23
+
16
24
  For windows:
17
- * download devil.dll and ilu.dll from here http://openil.sourceforge.net
18
- * and copy devil.dll and ilu.dll to c:\windows\system\
25
+
26
+ * download devil.dll and ilu.dll from [http://github.com/banister/devil/downloads]
27
+ * and copy these files to c:\windows\system\
28
+
29
+ For macosx:
30
+
31
+ * sudo port install libdevil
19
32
 
20
33
  For other systems:
34
+
21
35
  * install libdevil and lib-devil-dev using your package manager
22
- * OR download and install the libraries from http://openil.sourceforge.net
36
+ * OR download and install the libraries from [http://openil.sourceforge.net]
37
+
38
+ After you've installed the DevIL libraries you install the gem by going:
39
+
40
+ * gem install devil
23
41
 
24
42
  If you wish to use the Gosu and TexPlay extensions, it is necessary to also have:
43
+
25
44
  * the Gosu gem (gem install gosu)
26
45
  * the TexPlay gem (gem install texplay)
27
46
  * ruby-opengl (gem install ruby-opengl)
data/Rakefile CHANGED
@@ -1,10 +1,14 @@
1
1
  require 'rake/clean'
2
- require 'rake/extensiontask'
2
+
3
+ if RUBY_PLATFORM !~ /win32/
4
+ require 'rake/extensiontask'
5
+ end
6
+
3
7
  require 'rake/gempackagetask'
4
8
  require 'rake/testtask'
5
9
  require 'rake/rdoctask'
6
10
 
7
- DEVIL_VERSION = "0.1.6"
11
+ DEVIL_VERSION = "0.1.8"
8
12
 
9
13
  dlext = Config::CONFIG['DLEXT']
10
14
 
@@ -22,23 +26,23 @@ spec = Gem::Specification.new do |s|
22
26
  s.require_path = 'lib'
23
27
  s.homepage = "http://banisterfiend.wordpress.com"
24
28
 
25
- if RUBY_PLATFORM =~ /win/
29
+ if RUBY_PLATFORM =~ /win32/
26
30
  s.platform = Gem::Platform::CURRENT
27
31
  else
28
32
  s.platform = Gem::Platform::RUBY
29
33
  end
30
34
 
31
- if RUBY_PLATFORM !~ /win/
35
+ if RUBY_PLATFORM !~ /win32/
32
36
  s.extensions = FileList["ext/**/extconf.rb"]
33
37
  end
34
38
 
35
39
  s.has_rdoc = true
36
40
  s.extra_rdoc_files = ["README"]
37
41
  s.rdoc_options << '--main' << 'README'
38
- s.files = ["Rakefile", "README", "LICENSE", "lib/devil.rb", "lib/devil/gosu.rb"] +
42
+ s.files = ["Rakefile", "README", "CHANGELOG", "LICENSE", "lib/devil.rb", "lib/devil/gosu.rb"] +
39
43
  FileList["ext/**/extconf.rb", "ext/**/*.h", "ext/**/*.c", "test/test*.rb", "test/*.png", "test/*.jpg"].to_a
40
44
 
41
- if RUBY_PLATFORM =~ /win/
45
+ if RUBY_PLATFORM =~ /win32/
42
46
  s.files += ["lib/1.8/devil.so", "lib/1.9/devil.so"]
43
47
  end
44
48
 
@@ -51,10 +55,12 @@ end
51
55
 
52
56
  task :compile => :clean
53
57
 
54
- Rake::ExtensionTask.new('devil', spec) do |ext|
55
- ext.config_script = 'extconf.rb'
56
- ext.cross_compile = true
57
- ext.cross_platform = 'i386-mswin32'
58
+ if RUBY_PLATFORM !~ /win32/
59
+ Rake::ExtensionTask.new('devil', spec) do |ext|
60
+ ext.config_script = 'extconf.rb'
61
+ ext.cross_compile = true
62
+ ext.cross_platform = 'i386-mswin32'
63
+ end
58
64
  end
59
65
 
60
66
  Rake::TestTask.new do |t|
data/ext/devil/extconf.rb CHANGED
@@ -3,10 +3,14 @@ require 'mkmf'
3
3
  if RUBY_PLATFORM =~ /mingw/
4
4
  $CFLAGS += ' -I/home/john/.rake-compiler/ruby/ruby-1.8.6-p287/include/'
5
5
  $LDFLAGS += ' -L/home/john/.rake-compiler/ruby/ruby-1.8.6-p287/lib/'
6
+ elsif RUBY_PLATFORM =~ /darwin/
7
+
8
+ # this only works if you install devil via macports
9
+ $CFLAGS += ' -I/opt/local/include/'
10
+ $LDFLAGS += ' -L/opt/local/lib/'
6
11
  end
7
12
 
8
- puts "platform is #{RUBY_PLATFORM}"
9
- if RUBY_PLATFORM =~ /win/ || RUBY_PLATFORM =~ /mingw/
13
+ if RUBY_PLATFORM =~ /(win32|mingw)/
10
14
  exit unless have_library("DevIL");
11
15
  else
12
16
  exit unless have_library("IL");
data/ext/devil/ruby_il.c CHANGED
@@ -151,7 +151,7 @@ static VALUE il_GetData(VALUE obj) {
151
151
  /* void* data = ImageData2Arr(rb_data); */
152
152
 
153
153
  /* ILuint uint = ilCopyPixels(XOff, YOff, ZOff, Width, Height, Depth, Format, Type, data); */
154
- /* return INT2FIX(uint); */
154
+ /* return INT2FIX(uint); */
155
155
  /* } */
156
156
 
157
157
  static VALUE il_SetData(VALUE obj, VALUE rb_Data) {
@@ -242,6 +242,13 @@ static VALUE il_Enable(VALUE obj, VALUE rb_mode) {
242
242
  return flag ? Qtrue : Qfalse;
243
243
  }
244
244
 
245
+ static VALUE il_Disable(VALUE obj, VALUE rb_mode) {
246
+ ILenum mode = NUM2INT(rb_mode);
247
+
248
+ ILboolean flag = ilDisable(mode);
249
+ return flag ? Qtrue : Qfalse;
250
+ }
251
+
245
252
  static VALUE il_GetInteger(VALUE obj, VALUE rb_mode) {
246
253
  ILenum mode = NUM2INT(rb_mode);
247
254
 
@@ -258,13 +265,22 @@ static VALUE il_ConvertImage(VALUE obj, VALUE rb_destformat, VALUE rb_desttype)
258
265
  return flag ? Qtrue : Qfalse;
259
266
  }
260
267
 
268
+ /* TODO: MAKE SURE NO MEMORY LEAKS! */
261
269
  /* this function is not actualy in the DevIL API, but im adding it here for convenience */
262
270
  static VALUE bf_ToBlob(VALUE obj)
263
271
  {
264
- ILuint width, height;
272
+ ILuint width, height, saved_image, copy_image;
265
273
  char * img_ptr;
266
274
  VALUE blob;
275
+
276
+ saved_image = ilGetInteger(IL_CUR_IMAGE);
277
+
278
+ /* make a copy of the current image */
279
+ copy_image = ilCloneCurImage();
280
+
281
+ ilBindImage(copy_image);
267
282
 
283
+ /* ensure the image is int RGBA UNSIGNED_BYTE format for blob */
268
284
  ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
269
285
 
270
286
  width = ilGetInteger(IL_IMAGE_WIDTH);
@@ -274,6 +290,11 @@ static VALUE bf_ToBlob(VALUE obj)
274
290
 
275
291
  blob = rb_str_new(img_ptr, 4 * width * height);
276
292
 
293
+ /* restore saved binding */
294
+ ilBindImage(saved_image);
295
+
296
+ ilDeleteImages(1, &copy_image);
297
+
277
298
  return blob;
278
299
  }
279
300
 
@@ -282,17 +303,22 @@ static VALUE bf_FromBlob(VALUE obj, VALUE blob, VALUE rb_width, VALUE rb_height)
282
303
  ILubyte * data;
283
304
  ILuint width, height;
284
305
  ILuint image;
306
+ ILuint saved_image;
285
307
 
286
308
  width = NUM2INT(rb_width);
287
309
  height = NUM2INT(rb_height);
288
310
 
289
311
  data = (ILubyte *) RSTRING_PTR(blob);
290
312
 
313
+ saved_image = ilGetInteger(IL_CUR_IMAGE);
314
+
291
315
  ilGenImages(1, &image);
292
316
  ilBindImage(image);
293
317
 
294
318
  ilTexImage(width, height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, data);
295
319
 
320
+ ilBindImage(saved_image);
321
+
296
322
  return INT2NUM(image);
297
323
  }
298
324
 
@@ -302,6 +328,32 @@ static VALUE il_CloneCurImage(VALUE obj)
302
328
 
303
329
  return INT2NUM(clone);
304
330
  }
331
+
332
+ static VALUE il_OriginFunc(VALUE obj, VALUE rb_mode)
333
+ {
334
+ ILenum mode = NUM2INT(rb_mode);
335
+
336
+ ILboolean flag = ilOriginFunc(mode);
337
+ return flag ? Qtrue : Qfalse;
338
+ }
339
+
340
+ static VALUE il_ClearColour(VALUE obj, VALUE rb_red, VALUE rb_green, VALUE rb_blue, VALUE rb_alpha)
341
+ {
342
+ ILubyte red = NUM2INT(rb_red);
343
+ ILubyte green = NUM2INT(rb_green);
344
+ ILubyte blue = NUM2INT(rb_blue);
345
+ ILubyte alpha = NUM2INT(rb_alpha);
346
+
347
+ ilClearColour(red, green, blue, alpha);
348
+
349
+ return Qnil;
350
+ }
351
+
352
+ static VALUE il_ClearImage(VALUE obj)
353
+ {
354
+ ILboolean flag = ilClearImage();
355
+ return flag ? Qtrue : Qfalse;
356
+ }
305
357
  /* end of banisterfiend additions */
306
358
 
307
359
  void
@@ -338,11 +390,15 @@ InitializeIL() {
338
390
 
339
391
  /* methods added by baniterfiend */
340
392
  rb_define_module_function(mIL, "Enable", il_Enable, 1);
393
+ rb_define_module_function(mIL, "Disable", il_Disable, 1);
341
394
  rb_define_module_function(mIL, "GetInteger", il_GetInteger, 1);
342
395
  rb_define_module_function(mIL, "ConvertImage", il_ConvertImage, 2);
343
396
  rb_define_module_function(mIL, "ToBlob", bf_ToBlob, 0);
344
397
  rb_define_module_function(mIL, "FromBlob", bf_FromBlob, 3);
345
398
  rb_define_module_function(mIL, "CloneCurImage", il_CloneCurImage, 0);
399
+ rb_define_module_function(mIL, "OriginFunc", il_OriginFunc, 1);
400
+ rb_define_module_function(mIL, "ClearColour", il_ClearColour, 4);
401
+ rb_define_module_function(mIL, "ClearImage", il_ClearImage, 0);
346
402
  /* end of methods added by banisterfiend */
347
403
 
348
404
  //////////////////////////////////
@@ -434,11 +490,17 @@ InitializeIL() {
434
490
  rb_define_const(mIL, "LIB_MNG_ERROR", INT2NUM(IL_LIB_MNG_ERROR));
435
491
  rb_define_const(mIL, "UNKNOWN_ERROR", INT2NUM(IL_UNKNOWN_ERROR));
436
492
 
437
- // CONSTANTS BELOW ADDED BY BANISTERFIEND
493
+ /* CONSTANTS BELOW ADDED BY BANISTERFIEND */
494
+ rb_define_const(mIL, "IMAGE_DEPTH", INT2NUM(IL_IMAGE_DEPTH));
438
495
  rb_define_const(mIL, "IMAGE_WIDTH", INT2NUM(IL_IMAGE_WIDTH));
439
496
  rb_define_const(mIL, "IMAGE_HEIGHT", INT2NUM(IL_IMAGE_HEIGHT));
440
497
  rb_define_const(mIL, "IMAGE_FORMAT", INT2NUM(IL_IMAGE_FORMAT));
441
498
  rb_define_const(mIL, "FILE_OVERWRITE", INT2NUM(IL_FILE_OVERWRITE));
499
+ rb_define_const(mIL, "ORIGIN_SET", INT2NUM(IL_ORIGIN_SET));
500
+ rb_define_const(mIL, "CONV_PAL", INT2NUM(IL_CONV_PAL));
501
+ rb_define_const(mIL, "CUR_IMAGE", INT2NUM(IL_CUR_IMAGE));
502
+ rb_define_const(mIL, "ORIGIN_LOWER_LEFT", INT2NUM(IL_ORIGIN_LOWER_LEFT));
503
+ rb_define_const(mIL, "ORIGIN_UPPER_LEFT", INT2NUM(IL_ORIGIN_UPPER_LEFT));
442
504
  }
443
505
  //////////////////////////////////////////
444
506
 
data/ext/devil/ruby_ilu.c CHANGED
@@ -103,17 +103,66 @@ static VALUE ilu_Rotate(VALUE obj, VALUE rb_angle) {
103
103
  return flag ? Qtrue : Qfalse;
104
104
  }
105
105
 
106
- static VALUE ilu_Crop(VALUE obj, VALUE rb_XOff, VALUE rb_YOff, VALUE rb_width, VALUE rb_height)
106
+ static VALUE ilu_Crop(VALUE obj, VALUE rb_XOff, VALUE rb_YOff, VALUE rb_ZOff, VALUE rb_width, VALUE rb_height, VALUE rb_depth)
107
107
  {
108
108
  ILuint XOff = NUM2INT(rb_XOff);
109
109
  ILuint YOff = NUM2INT(rb_YOff);
110
+ ILuint ZOff = NUM2INT(rb_ZOff);
110
111
  ILuint width = NUM2INT(rb_width);
111
112
  ILuint height = NUM2INT(rb_height);
113
+ ILuint depth = NUM2INT(rb_depth);
112
114
 
113
- ILboolean flag = iluCrop(XOff, YOff, 1, width, height, 1);
115
+ ILboolean flag = iluCrop(XOff, YOff, ZOff, width, height, depth);
114
116
 
115
117
  return flag ? Qtrue : Qfalse;
116
118
  }
119
+
120
+ static VALUE ilu_EnlargeCanvas(VALUE obj, VALUE rb_width, VALUE rb_height, VALUE rb_depth)
121
+ {
122
+ ILuint width = NUM2INT(rb_width);
123
+ ILuint height = NUM2INT(rb_height);
124
+ ILuint depth = NUM2INT(rb_depth);
125
+
126
+ ILboolean flag = iluEnlargeCanvas(width, height, depth);
127
+
128
+ return flag ? Qtrue : Qfalse;
129
+ }
130
+
131
+ static VALUE ilu_EdgeDetectP(VALUE obj)
132
+ {
133
+ ILboolean flag = iluEdgeDetectP();
134
+
135
+ return flag ? Qtrue : Qfalse;
136
+ }
137
+
138
+ static VALUE ilu_EdgeDetectS(VALUE obj)
139
+ {
140
+ ILboolean flag = iluEdgeDetectS();
141
+
142
+ return flag ? Qtrue : Qfalse;
143
+ }
144
+
145
+ static VALUE ilu_Emboss(VALUE obj)
146
+ {
147
+ ILboolean flag = iluEmboss();
148
+
149
+ return flag ? Qtrue : Qfalse;
150
+ }
151
+
152
+ static VALUE ilu_Mirror(VALUE obj)
153
+ {
154
+ ILboolean flag = iluMirror();
155
+
156
+ return flag ? Qtrue : Qfalse;
157
+ }
158
+
159
+ static VALUE ilu_SwapColours(VALUE obj)
160
+ {
161
+ ILboolean flag = iluSwapColours();
162
+
163
+ return flag ? Qtrue : Qfalse;
164
+ }
165
+
117
166
  /* end of functions added by banisterfiend */
118
167
 
119
168
  void
@@ -138,9 +187,16 @@ InitializeILU() {
138
187
  /* methods added by banisterfiend */
139
188
  rb_define_module_function(mILU, "FlipImage", ilu_FlipImage, 0);
140
189
  rb_define_module_function(mILU, "Rotate", ilu_Rotate, 1);
141
- rb_define_module_function(mILU, "Crop", ilu_Crop, 4);
190
+ rb_define_module_function(mILU, "Crop", ilu_Crop, 6);
191
+ rb_define_module_function(mILU, "EnlargeCanvas", ilu_EnlargeCanvas, 3);
192
+ rb_define_module_function(mILU, "EdgeDetectP", ilu_EdgeDetectP, 0);
193
+ rb_define_module_function(mILU, "EdgeDetectS", ilu_EdgeDetectS, 0);
194
+ rb_define_module_function(mILU, "Emboss", ilu_Emboss, 0);
195
+ rb_define_module_function(mILU, "Mirror", ilu_Mirror, 0);
196
+ rb_define_module_function(mILU, "SwapColours", ilu_SwapColours, 0);
142
197
  /* end of functions added by banisterfiend */
143
198
 
199
+ /* constants added by banisterfiend */
144
200
  rb_define_const(mILU, "FILTER", INT2NUM(ILU_FILTER));
145
201
  rb_define_const(mILU, "NEAREST", INT2NUM(ILU_NEAREST));
146
202
  rb_define_const(mILU, "LINEAR", INT2NUM(ILU_LINEAR));
@@ -151,4 +207,13 @@ InitializeILU() {
151
207
  rb_define_const(mILU, "SCALE_BSPLINE", INT2NUM(ILU_SCALE_BSPLINE));
152
208
  rb_define_const(mILU, "SCALE_LANCZOS3", INT2NUM(ILU_SCALE_LANCZOS3));
153
209
  rb_define_const(mILU, "SCALE_MITCHELL", INT2NUM(ILU_SCALE_MITCHELL));
210
+
211
+ rb_define_const(mILU, "PLACEMENT", INT2NUM(ILU_PLACEMENT));
212
+ rb_define_const(mILU, "UPPER_LEFT", INT2NUM(ILU_UPPER_LEFT));
213
+ rb_define_const(mILU, "LOWER_LEFT", INT2NUM(ILU_LOWER_LEFT));
214
+ rb_define_const(mILU, "LOWER_RIGHT", INT2NUM(ILU_LOWER_RIGHT));
215
+ rb_define_const(mILU, "UPPER_RIGHT", INT2NUM(ILU_UPPER_RIGHT));
216
+ rb_define_const(mILU, "CENTER", INT2NUM(ILU_CENTER));
217
+ /* end of constants added by banisterfiend */
218
+
154
219
  }
data/lib/devil.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # (C) John Mair 2009, under the MIT licence
2
+
1
3
  require 'rbconfig'
2
4
 
3
5
  direc = File.dirname(__FILE__)
@@ -14,7 +16,10 @@ end
14
16
 
15
17
  # Provides a high level wrapper for the low-level DevIL Ruby bindings
16
18
  module Devil
17
- VERSION = '0.1.6'
19
+ include IL
20
+ include ILU
21
+
22
+ VERSION = '0.1.8'
18
23
 
19
24
  class << self
20
25
 
@@ -25,6 +30,11 @@ module Devil
25
30
  IL.BindImage(name)
26
31
  IL.LoadImage(file)
27
32
 
33
+ if (error_code = IL.GetError) != IL::NO_ERROR
34
+ raise RuntimeError, "an error occured while trying to "+
35
+ "load the image #{file}. #{ILU.ErrorString(error_code)}"
36
+ end
37
+
28
38
  img = Image.new(name, file)
29
39
  if block
30
40
  block.call(img)
@@ -33,27 +43,88 @@ module Devil
33
43
  img
34
44
  end
35
45
 
46
+ alias_method :with_image, :load_image
47
+ alias_method :load, :load_image
48
+
36
49
  # convert an image +blob+ with +width+ and +height+
37
50
  # to a bona fide image
38
51
  def from_blob(blob, width, height)
39
52
  Image.new(IL.FromBlob(blob, width, height), nil)
40
53
  end
41
54
 
42
- # initializes Devil and sets defaults
55
+ # configure Devil.
56
+ # accepts hash parameters: :scale_filter, :placement, :clear_color,
57
+ # :window_size, :edge_filter.
58
+ #
59
+ # :scale_filter accepts a valid scaling algorithm: (default is LANCZOS3).
60
+ # Devil::NEAREST, Devil::LINEAR, Devil::BILINEAR, Devil::SCALE_BOX,
61
+ # Devil::SCALE_TRIANGLE, Devil::SCALE_BELL, Devil::SCALE_BSPLINE,
62
+ # Devil::SCALE_LANCZOS3, Devil::SCALE_MITCHELL
63
+ #
64
+ # :placement determines where in the canvas the image will be placed after
65
+ # the canvas has been enlarged using the 'enlarge_canvas' method.
66
+ # Valid parameters are: Devil::Center, Devil::LOWER_LEFT, Devil::UPPER_RIGHT, etc
67
+ #
68
+ # :clear_color sets the current clearing colour to be used by future
69
+ # calls to clear. rotate and enlarge_canvas both use these values to
70
+ # clear blank space in images, too.
71
+ # e.g Devil.set_options(:clear_color => [255, 255, 0, 255])
72
+ # Above sets the clear color to yellow with full opacity.
73
+ #
74
+ # :window_size sets the display window size Gosu will use when displaying images
75
+ # that invoked the 'show' method. (default is 1024 x 768)
76
+ # e.g Devil.set_options(:window_size => [2000, 768])
77
+ # Example above sets a window size of 2000x768.
78
+ # Note: :window_size is only relevant when require 'devil/gosu' is used.
79
+ #
80
+ # :edge_filter sets the edge detection algorithm to use when invoking
81
+ # the 'edge_detect' method. (defaults to :prewitt)
82
+ # Allowed values are :prewitt and :sobel
83
+ def set_options(options={})
84
+ @options.merge!(options)
85
+
86
+ # update the scale_filter
87
+ ILU.ImageParameter(ILU::FILTER, @options[:scale_filter])
88
+ ILU.ImageParameter(ILU::PLACEMENT, @options[:placement])
89
+ IL.ClearColour(*@options[:clear_color])
90
+ end
91
+
92
+ # return the current Devil configuration.
93
+ def get_options
94
+ @options
95
+ end
96
+
97
+ # initializes Devil and sets defaults.
43
98
  # This method should never need to be called directly.
44
99
  def init
45
100
  # initialize DevIL
46
101
  IL.Init
102
+ ILU.Init
47
103
 
48
- # default options
49
- IL.Enable(IL::FILE_OVERWRITE)
50
- ILU.ImageParameter(ILU::FILTER, ILU::BILINEAR)
104
+ set_option_defaults
51
105
  end
52
106
 
53
- alias_method :with_image, :load_image
54
- alias_method :load, :load_image
55
- end
107
+ private
108
+
109
+ def set_option_defaults
110
+ @options = {
111
+ :scale_filter => ILU::SCALE_LANCZOS3,
112
+ :edge_filter => :prewitt,
113
+ :window_size => [1024, 768],
114
+ :clear_color => [255, 248, 230, 0],
115
+ :placement => ILU::CENTER,
116
+ }
117
+
118
+ # configurable options
119
+ ILU.ImageParameter(ILU::FILTER, @options[:scale_filter])
120
+ ILU.ImageParameter(ILU::PLACEMENT, @options[:placement])
121
+ IL.ClearColour(*@options[:clear_color])
56
122
 
123
+ # fixed options
124
+ IL.Enable(IL::FILE_OVERWRITE)
125
+ end
126
+ end
127
+
57
128
  class Image
58
129
  attr_reader :name, :file
59
130
 
@@ -64,83 +135,147 @@ module Devil
64
135
  ObjectSpace.define_finalizer( self, proc { IL.DeleteImages(1, [name]) } )
65
136
  end
66
137
 
67
- # returns the width of the image
138
+ # returns the width of the image.
68
139
  def width
69
- set_binding
70
- IL.GetInteger(IL::IMAGE_WIDTH)
140
+ action { IL.GetInteger(IL::IMAGE_WIDTH) }
71
141
  end
72
142
 
73
- # returns the height of the image
143
+ alias_method :columns, :width
144
+
145
+ # returns the height of the image.
74
146
  def height
75
- set_binding
76
- IL.GetInteger(IL::IMAGE_HEIGHT)
147
+ action { IL.GetInteger(IL::IMAGE_HEIGHT) }
77
148
  end
78
149
 
150
+ alias_method :rows, :height
151
+
79
152
  # saves the image to +file+. If no +file+ is provided default to the opened file.
80
153
  def save(file = @file)
81
- set_binding
82
- IL.SaveImage(file)
154
+ raise "This image does not have an associated file. Please provide an explicit file name when saving." if !file
155
+
156
+ action { IL.SaveImage(file) }
83
157
  self
84
158
  end
85
159
 
86
160
  # resize the image to +width+ and +height+. Aspect ratios of the image do not have to be the same.
87
161
  def resize(width, height)
88
- set_binding
89
- ILU.Scale(width, height, 1)
162
+ action { ILU.Scale(width, height, 1) }
90
163
  self
91
164
  end
92
165
 
93
- # Creates a proportional thumbnail of the image scaled so its longest
94
- # edge is resized to +size+
166
+ # Creates a proportional thumbnail of the image scaled so its longest.
167
+ # edge is resized to +size+.
95
168
  def thumbnail(size)
169
+
96
170
  # this thumbnail code from image_science.rb
97
-
98
171
  w, h = width, height
99
172
  scale = size.to_f / (w > h ? w : h)
100
173
  resize((w * scale).to_i, (h * scale).to_i)
101
174
  self
102
175
  end
103
176
 
104
- # return a deep copy of the current image
177
+ # return a deep copy of the current image.
105
178
  def dup
106
- set_binding
107
- Image.new(IL.CloneCurImage, nil)
179
+ new_image_name = action { IL.CloneCurImage }
180
+ Image.new(new_image_name, nil)
108
181
  end
109
182
 
110
- # crop the current image
111
- # +xoff+ number of pixels to skip in x direction
112
- # +yoff+ number of pixels to skip in y direction
113
- # +width+ number of pixels to preserve in x direction
114
- # +height+ number of pixels to preserve in y direction
183
+ alias_method :clone, :dup
184
+
185
+ # crop the current image.
186
+ # +xoff+ number of pixels to skip in x direction.
187
+ # +yoff+ number of pixels to skip in y direction.
188
+ # +width+ number of pixels to preserve in x direction.
189
+ # +height+ number of pixels to preserve in y direction.
115
190
  def crop(xoff, yoff, width, height)
116
- set_binding
117
- ILU.Crop(xoff, yoff, width, height)
191
+ action { ILU.Crop(xoff, yoff, 1, width, height, 1) }
192
+ self
193
+ end
194
+
195
+ # enlarge the canvas of current image to +width+ and +height+.
196
+ def enlarge_canvas(width, height)
197
+ if width < self.width || height < self.height
198
+ raise "width and height parameters must be larger than current image width and height"
199
+ end
200
+
201
+ action { ILU.EnlargeCanvas(width, height, 1) }
202
+ self
203
+ end
204
+
205
+ # splice the +source+ image into current image at position +x+ and +y+.
206
+ # Takes an optional +:crop+ hash parameter that has the following format: +:crop => [sx, sy, width, height]+
207
+ # +sx+, +sy+, +width, +height+ crop the source image to be spliced.
208
+ # +sx+ is how many pixels to skip in x direction of source image.
209
+ # +sy+ is how many pixels to skip in y direction of source image.
210
+ # +width+ number of pixels to preserve in x direction of source image.
211
+ # +height+ number of pixels to preserve in y direction of source image.
212
+ # if no +:crop+ parameter is provided then the whole image is spliced in.
213
+ def blit(source, x, y, options = {})
214
+ options = {
215
+ :crop => [0, 0, source.width, source.height]
216
+ }.merge!(options)
217
+
218
+ action do
219
+ IL.Blit(source.name, x, y, 0, options[:crop][0], options[:crop][1], 0,
220
+ options[:crop][2], options[:crop][3], 1)
221
+ end
222
+
223
+ self
224
+ end
225
+
226
+ alias_method :composite, :blit
227
+
228
+ # reflect image about its y axis.
229
+ def mirror
230
+ action { ILU.Mirror }
231
+ self
232
+ end
233
+
234
+ # use prewitt or sobel filters to detect the edges in the current image.
235
+ def edge_detect
236
+ case Devil.get_options[:edge_filter]
237
+ when :prewitt
238
+ action { ILU.EdgeDetectP }
239
+ when :sobel
240
+ action { ILU.EdgeDetectS }
241
+ else
242
+ raise "No such edge filter #{Devil.get_options[:edge_filter]}. Use :prewitt or :sobel"
243
+ end
244
+ self
245
+ end
246
+
247
+ # embosses an image, causing it to have a "relief" feel to it using a convolution filter.
248
+ def emboss
249
+ action { ILU.Emboss }
250
+ self
251
+ end
252
+
253
+ # applies a strange color distortion effect to the image giving a preternatural feel
254
+ def alienify
255
+ action { ILU.Alienify }
118
256
  self
119
257
  end
120
258
 
121
259
  # performs a gaussian blur on the image. The blur is performed +iter+ times.
122
260
  def blur(iter)
123
- set_binding
124
- ILU.BlurGaussian(iter)
261
+ action { ILU.BlurGaussian(iter) }
125
262
  self
126
263
  end
127
264
 
128
- # 'pixelize' the image using a pixel size of +pixel_size+
265
+ # 'pixelize' the image using a pixel size of +pixel_size+.
129
266
  def pixelize(pixel_size)
130
- set_binding
131
- ILU.Pixelize(pixel_size)
267
+ action { ILU.Pixelize(pixel_size) }
132
268
  self
133
269
  end
134
270
 
135
271
  # add random noise to the image. +factor+ is the tolerance to use.
136
- # accepeted values range from 0.0 - 1.0
272
+ # accepeted values range from 0.0 - 1.0.
137
273
  def noisify(factor)
138
- set_binding
139
- ILU.Noisify(factor)
274
+ action { ILU.Noisify(factor) }
140
275
  self
141
276
  end
142
277
 
143
- # The sharpening +factor+ must be in the range of 0.0 - 2.5. A value of 1.0 for the sharpening
278
+ # The sharpening +factor+ must be in the range of 0.0 - 2.5. A value of 1.0 for the sharpening.
144
279
  # factor will have no effect on the image. Values in the range 1.0 - 2.5 will sharpen the
145
280
  # image, with 2.5 having the most pronounced sharpening effect. Values from 0.0 to 1.0 do
146
281
  # a type of reverse sharpening, blurring the image. Values outside of the 0.0 - 2.5 range
@@ -149,8 +284,7 @@ module Devil
149
284
  # The number of +iter+ (iterations) to perform will usually be 1, but to achieve more sharpening,
150
285
  # increase the number of iterations.
151
286
  def sharpen(factor, iter)
152
- set_binding
153
- ILU.Sharpen(factor, iter)
287
+ action { ILU.Sharpen(factor, iter) }
154
288
  self
155
289
  end
156
290
 
@@ -160,66 +294,77 @@ module Devil
160
294
  # Values in the range 0.0 - 1.0 darken the image
161
295
  # Values above 1.0 brighten the image.
162
296
  def gamma_correct(factor)
163
- set_binding
164
- ILU.GammaCorrect(factor)
297
+ action { ILU.GammaCorrect(factor) }
165
298
  self
166
299
  end
167
300
 
168
301
  # invert the color of every pixel in the image.
169
- def negative
170
- set_binding
171
- ILU.Negative
302
+ def negate
303
+ action { ILU.Negative }
172
304
  self
173
305
  end
174
306
 
307
+ alias_method :negative, :negate
308
+
175
309
  # +factor+ describes desired contrast to use
176
310
  # A value of 1.0 has no effect on the image.
177
311
  # Values between 1.0 and 1.7 increase the amount of contrast (values above 1.7 have no effect)
178
- # Valid range of +factor+ is 0.0 - 1.7
312
+ # Valid range of +factor+ is 0.0 - 1.7.
179
313
  def contrast(factor)
180
- set_binding
181
- ILU.Contrast(factor)
314
+ action { ILU.Contrast(factor) }
182
315
  self
183
316
  end
184
317
 
185
318
  # darkens the bright colours and lightens the dark
186
319
  # colours, reducing the contrast in an image or 'equalizing' it.
187
320
  def equalize
188
- set_binding
189
- ILU.Equalize
321
+ action { ILU.Equalize }
190
322
  self
191
323
  end
192
324
 
193
- # returns the image data in the form of a ruby string
194
- # The image data is formatted to RGBA / UNSIGNED BYTE
325
+ # returns the image data in the form of a ruby string.
326
+ # The image data is formatted to RGBA / UNSIGNED BYTE.
195
327
  def to_blob
196
- set_binding
197
- IL.ToBlob
328
+ action { IL.ToBlob }
198
329
  end
199
330
 
200
- # flip the image about its x axis
331
+ # flip the image about its x axis.
201
332
  def flip
202
- set_binding
203
- ILU.FlipImage
333
+ action { ILU.FlipImage }
204
334
  self
205
335
  end
206
336
 
207
- # rotate an image about its central point by +angle+ degrees
337
+ # rotate an image about its central point by +angle+ degrees (counter clockwise).
208
338
  def rotate(angle)
209
- set_binding
210
- ILU.Rotate(angle)
339
+ action { ILU.Rotate(angle) }
211
340
  self
212
341
  end
213
342
 
214
- alias_method :columns, :width
215
- alias_method :rows, :height
343
+ # simply clears the image to the 'clear color' (specified using Devil.set_options(:clear_color => [r, g, b, a])
344
+ def clear
345
+ action { IL.ClearImage }
346
+ self
347
+ end
216
348
 
217
349
  private
218
-
350
+
219
351
  def set_binding
220
352
  IL.BindImage(@name)
221
353
  end
222
354
 
355
+ def error_check
356
+ if (error_code = IL.GetError) != IL::NO_ERROR
357
+ raise RuntimeError, "An error occured. #{ILU.ErrorString(error_code)}"
358
+ end
359
+ end
360
+
361
+ def action
362
+ set_binding
363
+ result = yield
364
+ error_check
365
+
366
+ result
367
+ end
223
368
  end
224
369
  end
225
370
 
data/lib/devil/gosu.rb CHANGED
@@ -1,19 +1,19 @@
1
1
  require 'texplay'
2
2
  require 'devil'
3
3
 
4
+ # monkey patches for TexPlay module (and by proxy the Gosu::Image class)
4
5
  module TexPlay
5
6
 
6
7
  # save a Gosu::Image to +file+
7
8
  # This method is only available if require 'devil/gosu' is used
8
9
  def save(file)
9
10
  capture {
10
- save_image = Devil.from_blob(self.to_blob, self.width, self.height)
11
- save_image.flip
12
- save_image.save(file)
11
+ to_devil.save(file)
13
12
  }
13
+ self
14
14
  end
15
15
 
16
- # convert a Gosu::Image to a Devil::Image
16
+ # convert a Gosu::Image to a Devil::Image.
17
17
  # This method is only available if require 'devil/gosu' is used
18
18
  def to_devil
19
19
  devil_img = nil
@@ -25,9 +25,10 @@ module TexPlay
25
25
  end
26
26
  end
27
27
 
28
+ # monkey patches for Gosu::Window class
28
29
  class Gosu::Window
29
30
 
30
- # return a screenshot of the framebuffer as a Devil::Image
31
+ # return a screenshot of the framebuffer as a Devil::Image.
31
32
  # This method is only available if require 'devil/gosu' is used
32
33
  def screenshot
33
34
  require 'opengl'
@@ -54,10 +55,27 @@ class Gosu::Window
54
55
  end
55
56
  end
56
57
 
58
+ class Gosu::Image
59
+ class << self
60
+ alias_method :original_new_redux, :new
61
+
62
+ # monkey patching to support multiple image formats.
63
+ # This method is only available if require 'devil/gosu' is used
64
+ def new(window, file, *args, &block)
65
+ if file.respond_to?(:to_blob) || file =~ /\.(bmp|png)$/
66
+ original_new_redux(window, file, *args, &block)
67
+ else
68
+ original_new_redux(window, Devil.load(file), *args, &block)
69
+ end
70
+ end
71
+ end
72
+ end
73
+
57
74
  class Devil::Image
58
75
 
59
76
  # convert a Devil::Image to a Gosu::Image.
60
77
  # Must provide a +window+ parameter, as per Gosu::Image#new()
78
+ # This method is only available if require 'devil/gosu' is used
61
79
  def to_gosu(window)
62
80
  Gosu::Image.new(window, self)
63
81
  end
@@ -66,13 +84,15 @@ class Devil::Image
66
84
  # if +x+ and +y+ are specified then show the image centered at this location, otherwise
67
85
  # draw the image at the center of the screen
68
86
  # This method is only available if require 'devil/gosu' is used
69
- def show(x = 512, y = 384)
87
+ def show(x = Devil.get_options[:window_size][0] / 2,
88
+ y = Devil.get_options[:window_size][1] / 2)
89
+
70
90
  if !Devil.const_defined?(:Window)
71
91
  c = Class.new(Gosu::Window) do
72
92
  attr_accessor :show_list
73
93
 
74
94
  def initialize
75
- super(1024, 768, false)
95
+ super(Devil.get_options[:window_size][0], Devil.get_options[:window_size][1], false)
76
96
  @show_list = []
77
97
  end
78
98
 
@@ -89,8 +109,10 @@ class Devil::Image
89
109
 
90
110
  at_exit { @@window.show }
91
111
  end
92
-
93
- @@window.show_list.push :image => Gosu::Image.new(@@window, self), :x => x, :y => y
94
- end
95
112
 
113
+ # note we dup the image so the displayed image is a snapshot taken at the time #show is invoked
114
+ @@window.show_list.push :image => Gosu::Image.new(@@window, self.dup), :x => x, :y => y
115
+
116
+ self
117
+ end
96
118
  end
data/test/red.png ADDED
Binary file
data/test/test_blit.rb ADDED
@@ -0,0 +1,22 @@
1
+ $direc = File.dirname(__FILE__)
2
+
3
+ $LOAD_PATH.push("#{$direc}/../lib/")
4
+
5
+ require 'rubygems'
6
+ require 'devil/gosu'
7
+
8
+ Devil.with_image("#{$direc}/texture.png") do |img|
9
+ img2 = Devil.load("#{$direc}/red.png")
10
+
11
+ img.show(200,200)
12
+
13
+ img.blit img2, 100, 100, :crop => [0, 0, img2.width / 2, img2.height / 2]
14
+
15
+ img.show
16
+ end
17
+
18
+
19
+
20
+
21
+
22
+
@@ -5,7 +5,7 @@ $LOAD_PATH.push("#{direc}/../lib/")
5
5
  require 'rubygems'
6
6
  require "devil/gosu"
7
7
 
8
- img = Devil.load_image("#{direc}/texture.png")
8
+ img = Devil.load_image("#{direc}/texture.jpg")
9
9
 
10
10
  img.crop(100,100, 200, 200)
11
11
  img_dup = img.dup
@@ -3,16 +3,13 @@ $direc = File.dirname(__FILE__)
3
3
  $LOAD_PATH.push("#{$direc}/../lib/")
4
4
 
5
5
  require 'rubygems'
6
- require 'gosu'
7
- require 'devil'
6
+ require 'devil/gosu'
8
7
 
9
8
  class W < Gosu::Window
10
9
  def initialize
11
10
  super(1024, 768, false, 20)
12
11
 
13
- img = Devil.load_image("#{$direc}/texture.jpg")
14
-
15
- @img = Gosu::Image.new(self, img)
12
+ @img = Gosu::Image.new(self, "#{$direc}/texture.jpg")
16
13
  end
17
14
 
18
15
  def draw
data/test/test_new_api.rb CHANGED
@@ -1,23 +1,23 @@
1
- direc = File.dirname(__FILE__)
1
+ $direc = File.dirname(__FILE__)
2
2
 
3
- $LOAD_PATH.push("#{direc}/../lib/")
3
+ $LOAD_PATH.push("#{$direc}/../lib/")
4
4
 
5
5
  require 'rubygems'
6
6
  require "devil"
7
7
 
8
- Devil.load_image("#{direc}/texture.png") do |img|
8
+ Devil.with_image("#{$direc}/texture.png") do |img|
9
9
  img.negative
10
- img.save("#{direc}/texture_neg.png")
10
+ img.save("#{$direc}/texture_neg.png")
11
11
  end
12
12
 
13
- img = Devil.load_image("#{direc}/texture.png")
14
- bink = Devil.load_image("#{direc}/texture.png")
13
+ img = Devil.load_image("#{$direc}/texture.png")
14
+ bink = Devil.load_image("#{$direc}/texture.png")
15
15
 
16
16
  img.gamma_correct(1.6)
17
17
  bink.resize(50, 50)
18
18
 
19
- img.save("#{direc}/texture_blur.png")
20
- bink.save("#{direc}/texture_tiny.png")
19
+ img.save("#{$direc}/texture_gamma.png")
20
+ bink.save("#{$direc}/texture_tiny.png")
21
21
 
22
22
 
23
23
 
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'devil'
3
+
4
+ algorithms = {
5
+ ILU::NEAREST => :nearest,
6
+ ILU::LINEAR => :linear,
7
+ ILU::BILINEAR => :bilinear,
8
+ ILU::SCALE_BOX => :scale_box,
9
+ ILU::SCALE_TRIANGLE => :scale_triangle,
10
+ ILU::SCALE_BELL => :scale_bell,
11
+ ILU::SCALE_BSPLINE => :scale_bspline,
12
+ ILU::SCALE_LANCZOS3 => :scale_lanczos3,
13
+ ILU::SCALE_MITCHELL => :scale_mitchell
14
+ }
15
+
16
+
17
+ algorithms.each do |key, value|
18
+ puts "Generating image using filter: #{value}"
19
+ IL.Init
20
+
21
+ name = IL.GenImages(1)[0]
22
+ IL.BindImage(name)
23
+ IL.LoadImage("texture.jpg")
24
+ ILU.ImageParameter(ILU::FILTER, key)
25
+
26
+ ILU.Scale(100, 100, 1)
27
+ IL.Enable(IL::FILE_OVERWRITE)
28
+ IL.SaveImage("scaling_test_#{value}.jpg")
29
+
30
+ end
@@ -6,7 +6,6 @@ require 'rubygems'
6
6
  require 'devil/gosu'
7
7
 
8
8
  Devil.load("texture.png") do |img|
9
- img.thumbnail(300)
10
- img.show
9
+ img.thumbnail(150).show
11
10
  end
12
11
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devil
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaroslaw Tworek, John Mair (banisterfiend)
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-12 00:00:00 -04:00
12
+ date: 2009-10-20 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -24,6 +24,7 @@ extra_rdoc_files:
24
24
  files:
25
25
  - Rakefile
26
26
  - README
27
+ - CHANGELOG
27
28
  - LICENSE
28
29
  - lib/devil.rb
29
30
  - lib/devil/gosu.rb
@@ -32,7 +33,9 @@ files:
32
33
  - ext/devil/ruby_devil_ext.c
33
34
  - ext/devil/ruby_il.c
34
35
  - ext/devil/ruby_ilu.c
36
+ - test/test_blit.rb
35
37
  - test/test_gosu_load.rb
38
+ - test/test_scale_algos.rb
36
39
  - test/test_new_api.rb
37
40
  - test/test_clone_and_crop.rb
38
41
  - test/test_gosu_show.rb
@@ -41,6 +44,7 @@ files:
41
44
  - test/test_thumbnail.rb
42
45
  - test/tank.png
43
46
  - test/texture.png
47
+ - test/red.png
44
48
  - test/texture.jpg
45
49
  has_rdoc: true
46
50
  homepage: http://banisterfiend.wordpress.com