devil 0.1.6 → 0.1.8

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