Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Resize now uses Catmull-Rom spline filter for better quality.

Added ICC Profile support.
Improved jpeg quality (beyond ICC profile support).
Refactored Data_Wrap_Struct/iv_set/ensure/yield.
Rewrote thumbnail in pure ruby, using resize.
bench.rb can now convert to another image type before running.
Fixed doco.

[git-p4: depot-paths = "//src/image_science/dev/": change = 3039]
  • Loading branch information...
commit cca1635b57269ddc968f36189ca7d8fac82d52c1 1 parent 9b535a8
@zenspider zenspider authored
Showing with 67 additions and 43 deletions.
  1. +9 −4 History.txt
  2. +12 −9 README.txt
  3. +11 −6 bench.rb
  4. +35 −24 lib/image_science.rb
View
13 History.txt
@@ -1,8 +1,13 @@
-== 1.1.1 / 2007-01-09
+== 1.1.1 / 2007-03-08
-* N minor enhancements:
- * Added errar handler that raises with information about what went wrong.
-* N bug fixes:
+* 5 minor enhancements:
+ * Added error handler that raises with information about what went wrong.
+ * thumbnail is now pure ruby, everything now uses resize.
+ * Produces cleaner JPEG files, with a small cost to file size/speed.
+ * resize now uses Catmull-Rom spline filter for better quality.
+ * resize copies existing ICC Profile to thumbnail, producing better color.
+ * ICC Profile NOT copied for PNG as it seems to be buggy.
+* 1 bug fix:
* Fixed rdoc
== 1.1.0 / 2007-01-05
View
21 README.txt
@@ -1,6 +1,6 @@
ImageScience
+ http://seattlerb.rubyforge.org/ImageScience.html
http://rubyforge.org/projects/seattlerb
- http://seattlerb.rubyforge.org/
by Ryan Davis
== DESCRIPTION:
@@ -13,18 +13,20 @@ For more information including build steps, see http://seattlerb.rubyforge.org/
== FEATURES/PROBLEMS:
-* 93 glorious lines of graphics manipulation magi... errr, SCIENCE!
-* Supports both square and proportional thumbnails.
+* Glorious graphics manipulation magi... errr, SCIENCE! in less than 200 LoC!
+* Supports square and proportional thumbnails, as well as arbitrary resizes.
* Pretty much any graphics format you could want. No really.
== SYNOPSYS:
ImageScience.with_image(file) do |img|
- img.cropped_thumbnail("#{file}_cropped.png", 100)
- end
-
- ImageScience.with_image(file) do |img|
- img.thumbnail("#{file}_thumb.png", 100)
+ img.cropped_thumbnail(100) do |thumb|
+ thumb.save "#{file}_cropped.png"
+ end
+
+ img.thumbnail(100) do |thumb|
+ thumb.save "#{file}_thumb.png"
+ end
end
== REQUIREMENTS:
@@ -36,12 +38,13 @@ For more information including build steps, see http://seattlerb.rubyforge.org/
* Download and install FreeImage. See notes at url above.
* sudo gem install -y image_science
+* see http://seattlerb.rubyforge.org/ImageScience.html for more info.
== LICENSE:
(The MIT License)
-Copyright (c) 2006 Ryan Davis, Seattle.rb
+Copyright (c) 2006-2007 Ryan Davis, Seattle.rb
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
View
17 bench.rb
@@ -4,7 +4,10 @@
require 'rubygems'
require 'image_science'
-file = "blah_big.png"
+max = (ARGV.shift || 100).to_i
+ext = ARGV.shift || "png"
+
+file = "blah_big.#{ext}"
if RUBY_PLATFORM =~ /darwin/ then
# how fucking cool is this???
@@ -14,7 +17,9 @@
abort "You need to plonk down #{file} or buy a mac"
end unless test ?f, "#{file}"
-max = (ARGV.shift || 100).to_i
+ImageScience.with_image(file.sub(/#{ext}$/, 'png')) do |img|
+ img.save(file)
+end if ext != "png"
puts "# of iterations = #{max}"
Benchmark::bm(20) do |x|
@@ -28,7 +33,7 @@
for i in 0..max do
ImageScience.with_image(file) do |img|
img.cropped_thumbnail(100) do |thumb|
- thumb.save("blah_cropped.png")
+ thumb.save("blah_cropped.#{ext}")
end
end
end
@@ -38,7 +43,7 @@
for i in 0..max do
ImageScience.with_image(file) do |img|
img.thumbnail(100) do |thumb|
- thumb.save("blah_thumb.png")
+ thumb.save("blah_thumb.#{ext}")
end
end
end
@@ -48,11 +53,11 @@
for i in 0..max do
ImageScience.with_image(file) do |img|
img.resize(200, 200) do |resize|
- resize.save("blah_resize.png")
+ resize.save("blah_resize.#{ext}")
end
end
end
}
end
-# File.unlink(*Dir["blah*png"])
+# File.unlink(*Dir["blah*#{ext}"])
View
59 lib/image_science.rb
@@ -50,10 +50,16 @@ def resize(width, height) # :yields: image
end
##
- # Creates a proportional thumbnail of the image scaled so its widest
+ # Creates a proportional thumbnail of the image scaled so its longest
# edge is resized to +size+ and yields the new image.
def thumbnail(size) # :yields: image
+ w, h = width, height
+ scale = size.to_f / (w > h ? w : h)
+
+ self.resize((w * scale).to_i, (h * scale).to_i) do |image|
+ yield image
+ end
end
##
@@ -94,6 +100,24 @@ def cropped_thumbnail(size) # :yields: image
DATA_PTR(self) = NULL;
return Qnil;
}
+
+ VALUE wrap_and_yield(FIBITMAP *image, VALUE self, FREE_IMAGE_FORMAT fif) {
+ VALUE klass = fif ? self : CLASS_OF(self);
+ VALUE type = fif ? INT2FIX(fif) : rb_iv_get(self, "@file_type");
+ VALUE obj = Data_Wrap_Struct(klass, NULL, NULL, image);
+ rb_iv_set(obj, "@file_type", type);
+ return rb_ensure(rb_yield, obj, unload, obj);
+ }
+
+ void copy_icc_profile(VALUE self, FIBITMAP *from, FIBITMAP *to) {
+ FREE_IMAGE_FORMAT fif = FIX2INT(rb_iv_get(self, "@file_type"));
+ if (fif != FIF_PNG && FreeImage_FIFSupportsICCProfiles(fif)) {
+ FIICCPROFILE *profile = FreeImage_GetICCProfile(from);
+ if (profile && profile->data) {
+ FreeImage_CreateICCProfile(to, profile->data, profile->size);
+ }
+ }
+ }
END
builder.prefix <<-"END"
@@ -116,10 +140,9 @@ def cropped_thumbnail(size) # :yields: image
if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
FIBITMAP *bitmap;
VALUE result = Qnil;
- if (bitmap = FreeImage_Load(fif, input, 0)) {
- VALUE obj = Data_Wrap_Struct(self, NULL, NULL, bitmap);
- rb_iv_set(obj, "@file_type", INT2FIX(fif));
- result = rb_ensure(rb_yield, obj, unload, obj);
+ int flags = fif == FIF_JPEG ? JPEG_ACCURATE : 0;
+ if (bitmap = FreeImage_Load(fif, input, flags)) {
+ result = wrap_and_yield(bitmap, self, fif);
}
return result;
}
@@ -134,8 +157,8 @@ def cropped_thumbnail(size) # :yields: image
GET_BITMAP(bitmap);
if (copy = FreeImage_Copy(bitmap, l, t, r, b)) {
- VALUE obj = Data_Wrap_Struct(CLASS_OF(self), NULL, NULL, copy);
- result = rb_ensure(rb_yield, obj, unload, obj);
+ copy_icc_profile(self, bitmap, copy);
+ result = wrap_and_yield(copy, self, 0);
}
return result;
}
@@ -158,20 +181,11 @@ def cropped_thumbnail(size) # :yields: image
END
builder.c <<-"END"
- VALUE thumbnail(int size) {
- GET_BITMAP(bitmap);
- FIBITMAP *image = FreeImage_MakeThumbnail(bitmap, size, TRUE);
- VALUE obj = Data_Wrap_Struct(CLASS_OF(self), NULL, NULL, image);
- return rb_ensure(rb_yield, obj, unload, obj);
- }
- END
-
- builder.c <<-"END"
VALUE resize(int w, int h) {
GET_BITMAP(bitmap);
- FIBITMAP *image = FreeImage_Rescale(bitmap, w, h, FILTER_BSPLINE);
- VALUE obj = Data_Wrap_Struct(CLASS_OF(self), NULL, NULL, image);
- return rb_ensure(rb_yield, obj, unload, obj);
+ FIBITMAP *image = FreeImage_Rescale(bitmap, w, h, FILTER_CATMULLROM);
+ copy_icc_profile(self, bitmap, image);
+ return wrap_and_yield(image, self, 0);
}
END
@@ -181,11 +195,8 @@ def cropped_thumbnail(size) # :yields: image
if (fif == FIF_UNKNOWN) fif = FIX2INT(rb_iv_get(self, "@file_type"));
if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsWriting(fif)) {
GET_BITMAP(bitmap);
-
- if (FreeImage_Save(fif, bitmap, output, 0)) {
- return Qtrue;
- }
- return Qfalse;
+ int flags = fif == FIF_JPEG ? JPEG_QUALITYSUPERB : 0;
+ return FreeImage_Save(fif, bitmap, output, flags) ? Qtrue : Qfalse;
}
rb_raise(rb_eTypeError, "Unknown file format");
}
Please sign in to comment.
Something went wrong with that request. Please try again.