image_science 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/History.txt +12 -0
  2. data/README.txt +12 -9
  3. data/bench.rb +11 -6
  4. data/lib/image_science.rb +62 -30
  5. metadata +10 -10
data/History.txt CHANGED
@@ -1,3 +1,15 @@
1
+ == 1.1.1 / 2007-03-08
2
+
3
+ * 5 minor enhancements:
4
+ * Added error handler that raises with information about what went wrong.
5
+ * thumbnail is now pure ruby, everything now uses resize.
6
+ * Produces cleaner JPEG files, with a small cost to file size/speed.
7
+ * resize now uses Catmull-Rom spline filter for better quality.
8
+ * resize copies existing ICC Profile to thumbnail, producing better color.
9
+ * ICC Profile NOT copied for PNG as it seems to be buggy.
10
+ * 1 bug fix:
11
+ * Fixed rdoc
12
+
1
13
  == 1.1.0 / 2007-01-05
2
14
 
3
15
  * 3 major enhancements:
data/README.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  ImageScience
2
+ http://seattlerb.rubyforge.org/ImageScience.html
2
3
  http://rubyforge.org/projects/seattlerb
3
- http://seattlerb.rubyforge.org/
4
4
  by Ryan Davis
5
5
 
6
6
  == DESCRIPTION:
@@ -13,18 +13,20 @@ For more information including build steps, see http://seattlerb.rubyforge.org/
13
13
 
14
14
  == FEATURES/PROBLEMS:
15
15
 
16
- * 93 glorious lines of graphics manipulation magi... errr, SCIENCE!
17
- * Supports both square and proportional thumbnails.
16
+ * Glorious graphics manipulation magi... errr, SCIENCE! in less than 200 LoC!
17
+ * Supports square and proportional thumbnails, as well as arbitrary resizes.
18
18
  * Pretty much any graphics format you could want. No really.
19
19
 
20
20
  == SYNOPSYS:
21
21
 
22
22
  ImageScience.with_image(file) do |img|
23
- img.cropped_thumbnail("#{file}_cropped.png", 100)
24
- end
25
-
26
- ImageScience.with_image(file) do |img|
27
- img.thumbnail("#{file}_thumb.png", 100)
23
+ img.cropped_thumbnail(100) do |thumb|
24
+ thumb.save "#{file}_cropped.png"
25
+ end
26
+
27
+ img.thumbnail(100) do |thumb|
28
+ thumb.save "#{file}_thumb.png"
29
+ end
28
30
  end
29
31
 
30
32
  == REQUIREMENTS:
@@ -36,12 +38,13 @@ For more information including build steps, see http://seattlerb.rubyforge.org/
36
38
 
37
39
  * Download and install FreeImage. See notes at url above.
38
40
  * sudo gem install -y image_science
41
+ * see http://seattlerb.rubyforge.org/ImageScience.html for more info.
39
42
 
40
43
  == LICENSE:
41
44
 
42
45
  (The MIT License)
43
46
 
44
- Copyright (c) 2006 Ryan Davis, Seattle.rb
47
+ Copyright (c) 2006-2007 Ryan Davis, Seattle.rb
45
48
 
46
49
  Permission is hereby granted, free of charge, to any person obtaining
47
50
  a copy of this software and associated documentation files (the
data/bench.rb CHANGED
@@ -4,7 +4,10 @@ require 'benchmark'
4
4
  require 'rubygems'
5
5
  require 'image_science'
6
6
 
7
- file = "blah_big.png"
7
+ max = (ARGV.shift || 100).to_i
8
+ ext = ARGV.shift || "png"
9
+
10
+ file = "blah_big.#{ext}"
8
11
 
9
12
  if RUBY_PLATFORM =~ /darwin/ then
10
13
  # how fucking cool is this???
@@ -14,7 +17,9 @@ else
14
17
  abort "You need to plonk down #{file} or buy a mac"
15
18
  end unless test ?f, "#{file}"
16
19
 
17
- max = (ARGV.shift || 100).to_i
20
+ ImageScience.with_image(file.sub(/#{ext}$/, 'png')) do |img|
21
+ img.save(file)
22
+ end if ext != "png"
18
23
 
19
24
  puts "# of iterations = #{max}"
20
25
  Benchmark::bm(20) do |x|
@@ -28,7 +33,7 @@ Benchmark::bm(20) do |x|
28
33
  for i in 0..max do
29
34
  ImageScience.with_image(file) do |img|
30
35
  img.cropped_thumbnail(100) do |thumb|
31
- thumb.save("blah_cropped.png")
36
+ thumb.save("blah_cropped.#{ext}")
32
37
  end
33
38
  end
34
39
  end
@@ -38,7 +43,7 @@ Benchmark::bm(20) do |x|
38
43
  for i in 0..max do
39
44
  ImageScience.with_image(file) do |img|
40
45
  img.thumbnail(100) do |thumb|
41
- thumb.save("blah_thumb.png")
46
+ thumb.save("blah_thumb.#{ext}")
42
47
  end
43
48
  end
44
49
  end
@@ -48,11 +53,11 @@ Benchmark::bm(20) do |x|
48
53
  for i in 0..max do
49
54
  ImageScience.with_image(file) do |img|
50
55
  img.resize(200, 200) do |resize|
51
- resize.save("blah_resize.png")
56
+ resize.save("blah_resize.#{ext}")
52
57
  end
53
58
  end
54
59
  end
55
60
  }
56
61
  end
57
62
 
58
- # File.unlink(*Dir["blah*png"])
63
+ # File.unlink(*Dir["blah*#{ext}"])
data/lib/image_science.rb CHANGED
@@ -4,25 +4,27 @@ require 'rubygems'
4
4
  require 'inline'
5
5
 
6
6
  ##
7
- # Provides a simple and clean API to generate thumbnails using
7
+ # Provides a clean and simple API to generate thumbnails using
8
8
  # FreeImage as the underlying mechanism.
9
9
  #
10
10
  # For more information or if you have build issues with FreeImage, see
11
11
  # http://seattlerb.rubyforge.org/ImageScience.html
12
12
 
13
13
  class ImageScience
14
- VERSION = '1.1.0'
14
+ VERSION = '1.1.1'
15
15
 
16
16
  ##
17
17
  # The top-level image loader opens +path+ and then yields the image.
18
18
 
19
- def self.with_image(path); end # :yields: image
19
+ def self.with_image(path) # :yields: image
20
+ end
20
21
 
21
22
  ##
22
23
  # Crops an image to +left+, +top+, +right+, and +bottom+ and then
23
24
  # yields the new image.
24
25
 
25
- def with_crop(left, top, right, bottom); end # :yields: image
26
+ def with_crop(left, top, right, bottom) # :yields: image
27
+ end
26
28
 
27
29
  ##
28
30
  # Returns the width of the image, in pixels.
@@ -34,17 +36,31 @@ class ImageScience
34
36
 
35
37
  def height; end
36
38
 
39
+ ##
40
+ # Saves the image out to +path+. Changing the file extension will
41
+ # convert the file type to the appropriate format.
42
+
43
+ def save(path); end
44
+
37
45
  ##
38
46
  # Resizes the image to +width+ and +height+ using a cubic-bspline
39
47
  # filter and yields the new image.
40
48
 
41
- def resize(width, height); end # :yields: image
49
+ def resize(width, height) # :yields: image
50
+ end
42
51
 
43
52
  ##
44
- # Creates a proportional thumbnail of the image scaled so its widest
53
+ # Creates a proportional thumbnail of the image scaled so its longest
45
54
  # edge is resized to +size+ and yields the new image.
46
55
 
47
- def thumbnail(size); end # :yields: image
56
+ def thumbnail(size) # :yields: image
57
+ w, h = width, height
58
+ scale = size.to_f / (w > h ? w : h)
59
+
60
+ self.resize((w * scale).to_i, (h * scale).to_i) do |image|
61
+ yield image
62
+ end
63
+ end
48
64
 
49
65
  ##
50
66
  # Creates a square thumbnail of the image cropping the longest edge
@@ -84,8 +100,37 @@ class ImageScience
84
100
  DATA_PTR(self) = NULL;
85
101
  return Qnil;
86
102
  }
103
+
104
+ VALUE wrap_and_yield(FIBITMAP *image, VALUE self, FREE_IMAGE_FORMAT fif) {
105
+ VALUE klass = fif ? self : CLASS_OF(self);
106
+ VALUE type = fif ? INT2FIX(fif) : rb_iv_get(self, "@file_type");
107
+ VALUE obj = Data_Wrap_Struct(klass, NULL, NULL, image);
108
+ rb_iv_set(obj, "@file_type", type);
109
+ return rb_ensure(rb_yield, obj, unload, obj);
110
+ }
111
+
112
+ void copy_icc_profile(VALUE self, FIBITMAP *from, FIBITMAP *to) {
113
+ FREE_IMAGE_FORMAT fif = FIX2INT(rb_iv_get(self, "@file_type"));
114
+ if (fif != FIF_PNG && FreeImage_FIFSupportsICCProfiles(fif)) {
115
+ FIICCPROFILE *profile = FreeImage_GetICCProfile(from);
116
+ if (profile && profile->data) {
117
+ FreeImage_CreateICCProfile(to, profile->data, profile->size);
118
+ }
119
+ }
120
+ }
121
+ END
122
+
123
+ builder.prefix <<-"END"
124
+ void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
125
+ rb_raise(rb_eRuntimeError,
126
+ "FreeImage exception for type %s: %s",
127
+ (fif == FIF_UNKNOWN) ? "???" : FreeImage_GetFormatFromFIF(fif),
128
+ message);
129
+ }
87
130
  END
88
131
 
132
+ builder.add_to_init "FreeImage_SetOutputMessage(FreeImageErrorHandler);"
133
+
89
134
  builder.c_singleton <<-"END"
90
135
  VALUE with_image(char * input) {
91
136
  FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
@@ -95,10 +140,9 @@ class ImageScience
95
140
  if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
96
141
  FIBITMAP *bitmap;
97
142
  VALUE result = Qnil;
98
- if (bitmap = FreeImage_Load(fif, input, 0)) {
99
- VALUE obj = Data_Wrap_Struct(self, NULL, NULL, bitmap);
100
- rb_iv_set(obj, "@file_type", INT2FIX(fif));
101
- result = rb_ensure(rb_yield, obj, unload, obj);
143
+ int flags = fif == FIF_JPEG ? JPEG_ACCURATE : 0;
144
+ if (bitmap = FreeImage_Load(fif, input, flags)) {
145
+ result = wrap_and_yield(bitmap, self, fif);
102
146
  }
103
147
  return result;
104
148
  }
@@ -113,8 +157,8 @@ class ImageScience
113
157
  GET_BITMAP(bitmap);
114
158
 
115
159
  if (copy = FreeImage_Copy(bitmap, l, t, r, b)) {
116
- VALUE obj = Data_Wrap_Struct(CLASS_OF(self), NULL, NULL, copy);
117
- result = rb_ensure(rb_yield, obj, unload, obj);
160
+ copy_icc_profile(self, bitmap, copy);
161
+ result = wrap_and_yield(copy, self, 0);
118
162
  }
119
163
  return result;
120
164
  }
@@ -136,21 +180,12 @@ class ImageScience
136
180
  }
137
181
  END
138
182
 
139
- builder.c <<-"END"
140
- VALUE thumbnail(int size) {
141
- GET_BITMAP(bitmap);
142
- FIBITMAP *image = FreeImage_MakeThumbnail(bitmap, size, TRUE);
143
- VALUE obj = Data_Wrap_Struct(CLASS_OF(self), NULL, NULL, image);
144
- return rb_ensure(rb_yield, obj, unload, obj);
145
- }
146
- END
147
-
148
183
  builder.c <<-"END"
149
184
  VALUE resize(int w, int h) {
150
185
  GET_BITMAP(bitmap);
151
- FIBITMAP *image = FreeImage_Rescale(bitmap, w, h, FILTER_BSPLINE);
152
- VALUE obj = Data_Wrap_Struct(CLASS_OF(self), NULL, NULL, image);
153
- return rb_ensure(rb_yield, obj, unload, obj);
186
+ FIBITMAP *image = FreeImage_Rescale(bitmap, w, h, FILTER_CATMULLROM);
187
+ copy_icc_profile(self, bitmap, image);
188
+ return wrap_and_yield(image, self, 0);
154
189
  }
155
190
  END
156
191
 
@@ -160,11 +195,8 @@ class ImageScience
160
195
  if (fif == FIF_UNKNOWN) fif = FIX2INT(rb_iv_get(self, "@file_type"));
161
196
  if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsWriting(fif)) {
162
197
  GET_BITMAP(bitmap);
163
-
164
- if (FreeImage_Save(fif, bitmap, output, 0)) {
165
- return Qtrue;
166
- }
167
- return Qfalse;
198
+ int flags = fif == FIF_JPEG ? JPEG_QUALITYSUPERB : 0;
199
+ return FreeImage_Save(fif, bitmap, output, flags) ? Qtrue : Qfalse;
168
200
  }
169
201
  rb_raise(rb_eTypeError, "Unknown file format");
170
202
  }
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0.8
2
+ rubygems_version: 0.9.0.9
3
3
  specification_version: 1
4
4
  name: image_science
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.1.0
7
- date: 2007-01-05 00:00:00 -08:00
6
+ version: 1.1.1
7
+ date: 2007-03-08 00:00:00 -08:00
8
8
  summary: ImageScience is a clean and happy Ruby library that generates thumbnails -- and kicks the living crap out of RMagick.
9
9
  require_paths:
10
10
  - lib
11
11
  email: ryand-ruby@zenspider.com
12
- homepage: http://rubyforge.org/projects/seattlerb
12
+ homepage: http://seattlerb.rubyforge.org/ImageScience.html
13
13
  rubyforge_project: seattlerb
14
14
  description: ImageScience is a clean and happy Ruby library that generates thumbnails -- and kicks the living crap out of RMagick. Oh, and it doesn't leak memory like a sieve. :) For more information including build steps, see http://seattlerb.rubyforge.org/
15
15
  autorequire:
@@ -49,20 +49,20 @@ requirements: []
49
49
 
50
50
  dependencies:
51
51
  - !ruby/object:Gem::Dependency
52
- name: hoe
52
+ name: RubyInline
53
53
  version_requirement:
54
54
  version_requirements: !ruby/object:Gem::Version::Requirement
55
55
  requirements:
56
- - - ">="
56
+ - - ">"
57
57
  - !ruby/object:Gem::Version
58
- version: 1.1.6
58
+ version: 0.0.0
59
59
  version:
60
60
  - !ruby/object:Gem::Dependency
61
- name: RubyInline
61
+ name: hoe
62
62
  version_requirement:
63
63
  version_requirements: !ruby/object:Gem::Version::Requirement
64
64
  requirements:
65
- - - ">"
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: 0.0.0
67
+ version: 1.2.0
68
68
  version: