g1nn13-image_science 1.2.3
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/History.txt +93 -0
- data/Manifest.txt +9 -0
- data/README.txt +73 -0
- data/Rakefile +37 -0
- data/bench.rb +63 -0
- data/bin/image_science_thumb +31 -0
- data/lib/image_science.rb +387 -0
- data/test/pix.png +0 -0
- data/test/test_image_science.rb +190 -0
- metadata +131 -0
data/History.txt
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
|
2
|
+
=== 1.2.3 / 2010-01-22
|
3
|
+
|
4
|
+
* 2 minor enhancements
|
5
|
+
|
6
|
+
* switched to gemcutter
|
7
|
+
* added fit_within() method to resize an image to fit within a height and
|
8
|
+
width without changing the aspect ratio
|
9
|
+
|
10
|
+
=== 1.2.2 / 2010-01-01
|
11
|
+
|
12
|
+
* 1 minor enhancements
|
13
|
+
|
14
|
+
* added buffer() method to return a buffer for an image so we can write images
|
15
|
+
to Amazon S3
|
16
|
+
|
17
|
+
=== 1.2.1 / 2009-08-14
|
18
|
+
|
19
|
+
* 2 minor enhancements:
|
20
|
+
|
21
|
+
* Added luis' patches to make it build properly on windows.
|
22
|
+
* with_image now raises on missing/bad files.
|
23
|
+
|
24
|
+
== 1.2.0 / 2009-06-23
|
25
|
+
|
26
|
+
* 7 minor enhancements:
|
27
|
+
|
28
|
+
* Moved quick_thumb to bin/image_science_thumb and properly added.
|
29
|
+
* Added -s (square) flag to bin/image_science_thumb
|
30
|
+
* Added autorotating on image load. (choonkeat)
|
31
|
+
* Added ruby_inline to clean globs
|
32
|
+
* Added with_image_from_memory. (sumbach)
|
33
|
+
* Switched to minitest.
|
34
|
+
* Updated rakefile for now hoe capabilities.
|
35
|
+
|
36
|
+
* 3 bug fixes:
|
37
|
+
|
38
|
+
* Check and convert to 24 BPP if save type is jpg. Caused by 32bpp png to jpg.
|
39
|
+
* Fixed 1.9isms
|
40
|
+
* Fixed BMP support. Tweaked whitespace.
|
41
|
+
|
42
|
+
== 1.1.3 / 2007-05-30
|
43
|
+
|
44
|
+
* 2 minor enhancements:
|
45
|
+
|
46
|
+
* Added quick_thumb as an example to look at.
|
47
|
+
* Error handler doesn't raise by default. Raises if $DEBUG==true.
|
48
|
+
|
49
|
+
== 1.1.2 / 2007-04-18
|
50
|
+
|
51
|
+
* 2 bug fixes:
|
52
|
+
|
53
|
+
* reports bad height/width values for resize
|
54
|
+
* explicitly removes ICC color profiles from PNGs (bug in freeimage).
|
55
|
+
|
56
|
+
== 1.1.1 / 2007-03-08
|
57
|
+
|
58
|
+
* 5 minor enhancements:
|
59
|
+
|
60
|
+
* Added error handler that raises with information about what went wrong.
|
61
|
+
* thumbnail is now pure ruby, everything now uses resize.
|
62
|
+
* Produces cleaner JPEG files, with a small cost to file size/speed.
|
63
|
+
* resize now uses Catmull-Rom spline filter for better quality.
|
64
|
+
* resize copies existing ICC Profile to thumbnail, producing better color.
|
65
|
+
* ICC Profile NOT copied for PNG as it seems to be buggy.
|
66
|
+
|
67
|
+
* 1 bug fix:
|
68
|
+
|
69
|
+
* Fixed rdoc
|
70
|
+
|
71
|
+
== 1.1.0 / 2007-01-05
|
72
|
+
|
73
|
+
* 3 major enhancements:
|
74
|
+
|
75
|
+
* Added resize(width, height)
|
76
|
+
* Added save(path)
|
77
|
+
* All thumbnail and resize methods yield instead of saving directly.
|
78
|
+
|
79
|
+
* 1 minor enhancement:
|
80
|
+
|
81
|
+
* Will now try to use FreeImage from ports if /opt/local exists.
|
82
|
+
|
83
|
+
* 2 bug fixes:
|
84
|
+
|
85
|
+
* Fixed the linker issue on PPC.
|
86
|
+
* Rakefile will now clean the image files created by bench.rb
|
87
|
+
|
88
|
+
== 1.0.0 / 2006-12-01
|
89
|
+
|
90
|
+
* 1 major enhancement
|
91
|
+
|
92
|
+
* Birthday!
|
93
|
+
|
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
= ImageScience
|
2
|
+
|
3
|
+
* http://seattlerb.rubyforge.org/ImageScience.html
|
4
|
+
* http://rubyforge.org/projects/seattlerb
|
5
|
+
|
6
|
+
== g1nn13 fork changes
|
7
|
+
|
8
|
+
* added buffer() method to get image buffer for writing (in our case to Amazon S3)
|
9
|
+
* added
|
10
|
+
* added .gitignore to ignore netbeans project directory
|
11
|
+
* bumped versions so our code could config.gem our fork
|
12
|
+
|
13
|
+
== DESCRIPTION:
|
14
|
+
|
15
|
+
ImageScience is a clean and happy Ruby library that generates
|
16
|
+
thumbnails -- and kicks the living crap out of RMagick. Oh, and it
|
17
|
+
doesn't leak memory like a sieve. :)
|
18
|
+
|
19
|
+
For more information including build steps, see http://seattlerb.rubyforge.org/
|
20
|
+
|
21
|
+
== FEATURES/PROBLEMS:
|
22
|
+
|
23
|
+
* Glorious graphics manipulation magi... errr, SCIENCE! in less than 200 LoC!
|
24
|
+
* Supports square and proportional thumbnails, as well as arbitrary resizes.
|
25
|
+
* Pretty much any graphics format you could want. No really.
|
26
|
+
|
27
|
+
== SYNOPSYS:
|
28
|
+
|
29
|
+
ImageScience.with_image(file) do |img|
|
30
|
+
img.cropped_thumbnail(100) do |thumb|
|
31
|
+
thumb.save "#{file}_cropped.png"
|
32
|
+
end
|
33
|
+
|
34
|
+
img.thumbnail(100) do |thumb|
|
35
|
+
thumb.save "#{file}_thumb.png"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
== REQUIREMENTS:
|
40
|
+
|
41
|
+
* FreeImage
|
42
|
+
* ImageScience
|
43
|
+
|
44
|
+
== INSTALL:
|
45
|
+
|
46
|
+
* Download and install FreeImage. See notes at url above.
|
47
|
+
* sudo gem install -y image_science
|
48
|
+
* see http://seattlerb.rubyforge.org/ImageScience.html for more info.
|
49
|
+
|
50
|
+
== LICENSE:
|
51
|
+
|
52
|
+
(The MIT License)
|
53
|
+
|
54
|
+
Copyright (c) 2006-2009 Ryan Davis, Seattle.rb
|
55
|
+
|
56
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
57
|
+
a copy of this software and associated documentation files (the
|
58
|
+
'Software'), to deal in the Software without restriction, including
|
59
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
60
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
61
|
+
permit persons to whom the Software is furnished to do so, subject to
|
62
|
+
the following conditions:
|
63
|
+
|
64
|
+
The above copyright notice and this permission notice shall be
|
65
|
+
included in all copies or substantial portions of the Software.
|
66
|
+
|
67
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
68
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
69
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
70
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
71
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
72
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
73
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
##
|
4
|
+
# we are using the hotelicopter_gemcutter hoe plugin to publish to gemcutter
|
5
|
+
# so we want to make sure we disable rubyforge and the regular gemcutter
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
require 'hoe'
|
10
|
+
|
11
|
+
Hoe.plugins.delete :rubyforge
|
12
|
+
Hoe.plugins.delete :gemcutter
|
13
|
+
|
14
|
+
Hoe.plugin :doofus, :git, :inline, :telicopter
|
15
|
+
|
16
|
+
Hoe.spec 'g1nn13-image_science' do
|
17
|
+
|
18
|
+
developer "jim nist", "jim@hotelicopter.com"
|
19
|
+
|
20
|
+
extra_deps << %w(hoe >=2.5.0)
|
21
|
+
extra_deps << %w(gemcutter >=0.3.0)
|
22
|
+
extra_dev_deps << %w(hoe-doofus >=1.0.0)
|
23
|
+
extra_dev_deps << %w(hoe-git >=1.3.0)
|
24
|
+
|
25
|
+
clean_globs << 'blah*png' << 'images/*_thumb.*'
|
26
|
+
|
27
|
+
email_to << 'jim@hotelicopter.com'
|
28
|
+
|
29
|
+
# this can be set in ~/.hoerc or overridden here.
|
30
|
+
# self.prefix = 'g1nn13'
|
31
|
+
|
32
|
+
# set the name as that is how the prefixed and forked gems
|
33
|
+
# are allowed on gemcutter
|
34
|
+
# self.name = "#{self.prefix}#{self.name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
# vim: syntax=Ruby
|
data/bench.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
require 'benchmark'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'image_science'
|
6
|
+
|
7
|
+
max = (ARGV.shift || 100).to_i
|
8
|
+
ext = ARGV.shift || "png"
|
9
|
+
|
10
|
+
file = "blah_big.#{ext}"
|
11
|
+
|
12
|
+
if RUBY_PLATFORM =~ /darwin/ then
|
13
|
+
# how fucking cool is this???
|
14
|
+
puts "taking screenshot for thumbnailing benchmarks"
|
15
|
+
system "screencapture -SC #{file}"
|
16
|
+
else
|
17
|
+
abort "You need to plonk down #{file} or buy a mac"
|
18
|
+
end unless test ?f, "#{file}"
|
19
|
+
|
20
|
+
ImageScience.with_image(file.sub(/#{ext}$/, 'png')) do |img|
|
21
|
+
img.save(file)
|
22
|
+
end if ext != "png"
|
23
|
+
|
24
|
+
puts "# of iterations = #{max}"
|
25
|
+
Benchmark::bm(20) do |x|
|
26
|
+
x.report("null_time") {
|
27
|
+
for i in 0..max do
|
28
|
+
# do nothing
|
29
|
+
end
|
30
|
+
}
|
31
|
+
|
32
|
+
x.report("cropped") {
|
33
|
+
for i in 0..max do
|
34
|
+
ImageScience.with_image(file) do |img|
|
35
|
+
img.cropped_thumbnail(100) do |thumb|
|
36
|
+
thumb.save("blah_cropped.#{ext}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
}
|
41
|
+
|
42
|
+
x.report("proportional") {
|
43
|
+
for i in 0..max do
|
44
|
+
ImageScience.with_image(file) do |img|
|
45
|
+
img.thumbnail(100) do |thumb|
|
46
|
+
thumb.save("blah_thumb.#{ext}")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
}
|
51
|
+
|
52
|
+
x.report("resize") {
|
53
|
+
for i in 0..max do
|
54
|
+
ImageScience.with_image(file) do |img|
|
55
|
+
img.resize(200, 200) do |resize|
|
56
|
+
resize.save("blah_resize.#{ext}")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
# File.unlink(*Dir["blah*#{ext}"])
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/local/bin/ruby -ws
|
2
|
+
|
3
|
+
$s ||= false
|
4
|
+
|
5
|
+
abort "#{File.basename $0} max_length files..." unless ARGV.size > 1
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'image_science'
|
9
|
+
|
10
|
+
max_length = ARGV.shift.to_i
|
11
|
+
|
12
|
+
msg = $s ? :cropped_thumbnail : :thumbnail
|
13
|
+
|
14
|
+
ARGV.each do |file|
|
15
|
+
begin
|
16
|
+
result = ImageScience.with_image file do |img|
|
17
|
+
begin
|
18
|
+
img.send(msg, max_length) do |thumb|
|
19
|
+
# add _thumb and switch from gif to png. Really. gif just sucks.
|
20
|
+
out = file.sub(/(\.[^\.]+)$/, '_thumb\1').sub(/gif$/, 'png')
|
21
|
+
thumb.save(out)
|
22
|
+
end
|
23
|
+
rescue => e
|
24
|
+
warn "Exception thumbnailing #{file}: #{e}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
p file => result
|
28
|
+
rescue => e
|
29
|
+
warn "Exception opening #{file}: #{e}"
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,387 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'inline'
|
5
|
+
|
6
|
+
##
|
7
|
+
# Provides a clean and simple API to generate thumbnails using
|
8
|
+
# FreeImage as the underlying mechanism.
|
9
|
+
#
|
10
|
+
# For more information or if you have build issues with FreeImage, see
|
11
|
+
# http://seattlerb.rubyforge.org/ImageScience.html
|
12
|
+
|
13
|
+
class ImageScience
|
14
|
+
VERSION = '1.2.3'
|
15
|
+
|
16
|
+
##
|
17
|
+
# The top-level image loader opens +path+ and then yields the image.
|
18
|
+
|
19
|
+
def self.with_image(path) # :yields: image
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# The top-level image loader, opens an image from the string +data+ and then yields the image.
|
24
|
+
|
25
|
+
def self.with_image_from_memory(data) # :yields: image
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Crops an image to +left+, +top+, +right+, and +bottom+ and then
|
30
|
+
# yields the new image.
|
31
|
+
|
32
|
+
def with_crop(left, top, right, bottom) # :yields: image
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Returns the width of the image, in pixels.
|
37
|
+
|
38
|
+
def width; end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Returns the height of the image, in pixels.
|
42
|
+
|
43
|
+
def height; end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Saves the image out to +path+. Changing the file extension will
|
47
|
+
# convert the file type to the appropriate format.
|
48
|
+
|
49
|
+
def save(path); end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Returns the image in a buffer (String). Changing the file
|
53
|
+
# extension converts the file type to the appropriate format.
|
54
|
+
|
55
|
+
def buffer(extension); end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Resizes the image to +width+ and +height+ using a cubic-bspline
|
59
|
+
# filter and yields the new image.
|
60
|
+
|
61
|
+
def resize(width, height) # :yields: image
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Creates a proportional thumbnail of the image scaled so its longest
|
66
|
+
# edge is resized to +size+ and yields the new image.
|
67
|
+
|
68
|
+
def thumbnail(size) # :yields: image
|
69
|
+
w, h = width, height
|
70
|
+
scale = size.to_f / (w > h ? w : h)
|
71
|
+
|
72
|
+
self.resize((w * scale).to_i, (h * scale).to_i) do |image|
|
73
|
+
yield image
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Creates a square thumbnail of the image cropping the longest edge
|
79
|
+
# to match the shortest edge, resizes to +size+, and yields the new
|
80
|
+
# image.
|
81
|
+
|
82
|
+
def cropped_thumbnail(size) # :yields: image
|
83
|
+
w, h = width, height
|
84
|
+
l, t, r, b, half = 0, 0, w, h, (w - h).abs / 2
|
85
|
+
|
86
|
+
l, r = half, half + h if w > h
|
87
|
+
t, b = half, half + w if h > w
|
88
|
+
|
89
|
+
with_crop(l, t, r, b) do |img|
|
90
|
+
img.thumbnail(size) do |thumb|
|
91
|
+
yield thumb
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
inline do |builder|
|
97
|
+
if test ?d, "/opt/local" then
|
98
|
+
builder.add_compile_flags "-I/opt/local/include"
|
99
|
+
builder.add_link_flags "-L/opt/local/lib"
|
100
|
+
end
|
101
|
+
|
102
|
+
builder.add_link_flags "-lfreeimage"
|
103
|
+
unless RUBY_PLATFORM =~ /mswin/
|
104
|
+
builder.add_link_flags "-lfreeimage"
|
105
|
+
# TODO: detect PPC
|
106
|
+
builder.add_link_flags "-lstdc++" # only needed on PPC for some reason
|
107
|
+
else
|
108
|
+
builder.add_link_flags "freeimage.lib"
|
109
|
+
end
|
110
|
+
builder.include '"FreeImage.h"'
|
111
|
+
|
112
|
+
builder.prefix <<-"END"
|
113
|
+
#define GET_BITMAP(name) Data_Get_Struct(self, FIBITMAP, (name)); if (!(name)) rb_raise(rb_eTypeError, "Bitmap has already been freed");
|
114
|
+
END
|
115
|
+
|
116
|
+
builder.prefix <<-"END"
|
117
|
+
VALUE unload(VALUE self) {
|
118
|
+
FIBITMAP *bitmap;
|
119
|
+
GET_BITMAP(bitmap);
|
120
|
+
|
121
|
+
FreeImage_Unload(bitmap);
|
122
|
+
DATA_PTR(self) = NULL;
|
123
|
+
return Qnil;
|
124
|
+
}
|
125
|
+
END
|
126
|
+
|
127
|
+
builder.prefix <<-"END"
|
128
|
+
VALUE wrap_and_yield(FIBITMAP *image, VALUE self, FREE_IMAGE_FORMAT fif) {
|
129
|
+
unsigned int self_is_class = rb_type(self) == T_CLASS;
|
130
|
+
VALUE klass = self_is_class ? self : CLASS_OF(self);
|
131
|
+
VALUE type = self_is_class ? INT2FIX(fif) : rb_iv_get(self, "@file_type");
|
132
|
+
VALUE obj = Data_Wrap_Struct(klass, NULL, NULL, image);
|
133
|
+
rb_iv_set(obj, "@file_type", type);
|
134
|
+
return rb_ensure(rb_yield, obj, unload, obj);
|
135
|
+
}
|
136
|
+
END
|
137
|
+
|
138
|
+
builder.prefix <<-"END"
|
139
|
+
void copy_icc_profile(VALUE self, FIBITMAP *from, FIBITMAP *to) {
|
140
|
+
FREE_IMAGE_FORMAT fif = FIX2INT(rb_iv_get(self, "@file_type"));
|
141
|
+
if (fif != FIF_PNG && FreeImage_FIFSupportsICCProfiles(fif)) {
|
142
|
+
FIICCPROFILE *profile = FreeImage_GetICCProfile(from);
|
143
|
+
if (profile && profile->data) {
|
144
|
+
FreeImage_CreateICCProfile(to, profile->data, profile->size);
|
145
|
+
}
|
146
|
+
}
|
147
|
+
}
|
148
|
+
END
|
149
|
+
|
150
|
+
builder.prefix <<-"END"
|
151
|
+
void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
|
152
|
+
rb_raise(rb_eRuntimeError,
|
153
|
+
"FreeImage exception for type %s: %s",
|
154
|
+
(fif == FIF_UNKNOWN) ? "???" : FreeImage_GetFormatFromFIF(fif),
|
155
|
+
message);
|
156
|
+
}
|
157
|
+
END
|
158
|
+
|
159
|
+
builder.add_to_init "FreeImage_SetOutputMessage(FreeImageErrorHandler);"
|
160
|
+
|
161
|
+
builder.c_singleton <<-"END"
|
162
|
+
VALUE with_image(char * input) {
|
163
|
+
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
|
164
|
+
int flags;
|
165
|
+
|
166
|
+
fif = FreeImage_GetFileType(input, 0);
|
167
|
+
if (fif == FIF_UNKNOWN) fif = FreeImage_GetFIFFromFilename(input);
|
168
|
+
if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
|
169
|
+
FIBITMAP *bitmap;
|
170
|
+
VALUE result = Qnil;
|
171
|
+
flags = fif == FIF_JPEG ? JPEG_ACCURATE : 0;
|
172
|
+
if (bitmap = FreeImage_Load(fif, input, flags)) {
|
173
|
+
FITAG *tagValue = NULL;
|
174
|
+
FreeImage_GetMetadata(FIMD_EXIF_MAIN, bitmap, "Orientation", &tagValue);
|
175
|
+
switch (tagValue == NULL ? 0 : *((short *) FreeImage_GetTagValue(tagValue))) {
|
176
|
+
case 6:
|
177
|
+
bitmap = FreeImage_RotateClassic(bitmap, 270);
|
178
|
+
break;
|
179
|
+
case 3:
|
180
|
+
bitmap = FreeImage_RotateClassic(bitmap, 180);
|
181
|
+
break;
|
182
|
+
case 8:
|
183
|
+
bitmap = FreeImage_RotateClassic(bitmap, 90);
|
184
|
+
break;
|
185
|
+
default:
|
186
|
+
break;
|
187
|
+
}
|
188
|
+
|
189
|
+
result = wrap_and_yield(bitmap, self, fif);
|
190
|
+
}
|
191
|
+
return result;
|
192
|
+
}
|
193
|
+
rb_raise(rb_eTypeError, "Unknown file format");
|
194
|
+
}
|
195
|
+
END
|
196
|
+
|
197
|
+
builder.c_singleton <<-"END"
|
198
|
+
VALUE with_image_from_memory(VALUE image_data) {
|
199
|
+
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
|
200
|
+
|
201
|
+
Check_Type(image_data, T_STRING);
|
202
|
+
BYTE *image_data_ptr = (BYTE*)RSTRING_PTR(image_data);
|
203
|
+
DWORD image_data_length = RSTRING_LEN(image_data);
|
204
|
+
FIMEMORY *stream = FreeImage_OpenMemory(image_data_ptr, image_data_length);
|
205
|
+
|
206
|
+
if (NULL == stream) {
|
207
|
+
rb_raise(rb_eTypeError, "Unable to open image_data");
|
208
|
+
}
|
209
|
+
|
210
|
+
fif = FreeImage_GetFileTypeFromMemory(stream, 0);
|
211
|
+
if ((fif == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading(fif)) {
|
212
|
+
rb_raise(rb_eTypeError, "Unknown file format");
|
213
|
+
}
|
214
|
+
|
215
|
+
FIBITMAP *bitmap = NULL;
|
216
|
+
VALUE result = Qnil;
|
217
|
+
int flags = fif == FIF_JPEG ? JPEG_ACCURATE : 0;
|
218
|
+
bitmap = FreeImage_LoadFromMemory(fif, stream, flags);
|
219
|
+
FreeImage_CloseMemory(stream);
|
220
|
+
if (bitmap) {
|
221
|
+
result = wrap_and_yield(bitmap, self, fif);
|
222
|
+
}
|
223
|
+
return result;
|
224
|
+
}
|
225
|
+
END
|
226
|
+
|
227
|
+
builder.c <<-"END"
|
228
|
+
VALUE with_crop(int l, int t, int r, int b) {
|
229
|
+
FIBITMAP *copy, *bitmap;
|
230
|
+
VALUE result = Qnil;
|
231
|
+
GET_BITMAP(bitmap);
|
232
|
+
|
233
|
+
if (copy = FreeImage_Copy(bitmap, l, t, r, b)) {
|
234
|
+
copy_icc_profile(self, bitmap, copy);
|
235
|
+
result = wrap_and_yield(copy, self, 0);
|
236
|
+
}
|
237
|
+
return result;
|
238
|
+
}
|
239
|
+
END
|
240
|
+
|
241
|
+
builder.c <<-"END"
|
242
|
+
int height() {
|
243
|
+
FIBITMAP *bitmap;
|
244
|
+
GET_BITMAP(bitmap);
|
245
|
+
|
246
|
+
return FreeImage_GetHeight(bitmap);
|
247
|
+
}
|
248
|
+
END
|
249
|
+
|
250
|
+
builder.c <<-"END"
|
251
|
+
int width() {
|
252
|
+
FIBITMAP *bitmap;
|
253
|
+
GET_BITMAP(bitmap);
|
254
|
+
|
255
|
+
return FreeImage_GetWidth(bitmap);
|
256
|
+
}
|
257
|
+
END
|
258
|
+
|
259
|
+
builder.c <<-"END"
|
260
|
+
VALUE resize(long w, long h) {
|
261
|
+
FIBITMAP *bitmap, *image;
|
262
|
+
if (w <= 0) rb_raise(rb_eArgError, "Width <= 0");
|
263
|
+
if (h <= 0) rb_raise(rb_eArgError, "Height <= 0");
|
264
|
+
GET_BITMAP(bitmap);
|
265
|
+
image = FreeImage_Rescale(bitmap, w, h, FILTER_CATMULLROM);
|
266
|
+
if (image) {
|
267
|
+
copy_icc_profile(self, bitmap, image);
|
268
|
+
return wrap_and_yield(image, self, 0);
|
269
|
+
}
|
270
|
+
return Qnil;
|
271
|
+
}
|
272
|
+
END
|
273
|
+
|
274
|
+
builder.c <<-"END"
|
275
|
+
VALUE save(char * output) {
|
276
|
+
int flags;
|
277
|
+
FIBITMAP *bitmap;
|
278
|
+
FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(output);
|
279
|
+
if (fif == FIF_UNKNOWN) fif = FIX2INT(rb_iv_get(self, "@file_type"));
|
280
|
+
if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsWriting(fif)) {
|
281
|
+
GET_BITMAP(bitmap);
|
282
|
+
flags = fif == FIF_JPEG ? JPEG_QUALITYSUPERB : 0;
|
283
|
+
BOOL result = 0, unload = 0;
|
284
|
+
|
285
|
+
if (fif == FIF_PNG) FreeImage_DestroyICCProfile(bitmap);
|
286
|
+
if (fif == FIF_JPEG && FreeImage_GetBPP(bitmap) != 24)
|
287
|
+
bitmap = FreeImage_ConvertTo24Bits(bitmap), unload = 1; // sue me
|
288
|
+
|
289
|
+
result = FreeImage_Save(fif, bitmap, output, flags);
|
290
|
+
|
291
|
+
if (unload) FreeImage_Unload(bitmap);
|
292
|
+
|
293
|
+
return result ? Qtrue : Qfalse;
|
294
|
+
}
|
295
|
+
rb_raise(rb_eTypeError, "Unknown file format");
|
296
|
+
}
|
297
|
+
END
|
298
|
+
|
299
|
+
builder.c <<-"END"
|
300
|
+
VALUE buffer(char * extension) {
|
301
|
+
VALUE str;
|
302
|
+
int flags;
|
303
|
+
FIBITMAP *bitmap;
|
304
|
+
<<<<<<< HEAD:lib/image_science.rb
|
305
|
+
FIMEMORY *mem = NULL;
|
306
|
+
long file_size;
|
307
|
+
BYTE *mem_buffer = NULL;
|
308
|
+
DWORD size_in_bytes = 0;
|
309
|
+
char message[1024];
|
310
|
+
FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(extension);
|
311
|
+
|
312
|
+
if (fif == FIF_UNKNOWN) {
|
313
|
+
fif = FIX2INT(rb_iv_get(self, "@file_type"));
|
314
|
+
}
|
315
|
+
if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsWriting(fif)) {
|
316
|
+
GET_BITMAP(bitmap);
|
317
|
+
flags = (fif == FIF_JPEG ? JPEG_QUALITYSUPERB : 0);
|
318
|
+
=======
|
319
|
+
FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(extension);
|
320
|
+
FIMEMORY *mem = NULL;
|
321
|
+
long file_size;
|
322
|
+
BYTE *mem_buffer = NULL;
|
323
|
+
DWORD size_in_bytes = 0;
|
324
|
+
|
325
|
+
if (fif == FIF_UNKNOWN) fif = FIX2INT(rb_iv_get(self, "@file_type"));
|
326
|
+
if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsWriting(fif)) {
|
327
|
+
GET_BITMAP(bitmap);
|
328
|
+
flags = fif == FIF_JPEG ? JPEG_QUALITYSUPERB : 0;
|
329
|
+
>>>>>>> 82c4446fc3ddc3121f6e9d36af299b5109aa7eed:lib/image_science.rb
|
330
|
+
BOOL result = 0, unload = 0;
|
331
|
+
|
332
|
+
if (fif == FIF_PNG) FreeImage_DestroyICCProfile(bitmap);
|
333
|
+
if (fif == FIF_JPEG && FreeImage_GetBPP(bitmap) != 24)
|
334
|
+
<<<<<<< HEAD:lib/image_science.rb
|
335
|
+
bitmap = FreeImage_ConvertTo24Bits(bitmap), unload = 1;
|
336
|
+
|
337
|
+
// create a memory stream and save to it
|
338
|
+
=======
|
339
|
+
bitmap = FreeImage_ConvertTo24Bits(bitmap), unload = 1; // sue me
|
340
|
+
|
341
|
+
>>>>>>> 82c4446fc3ddc3121f6e9d36af299b5109aa7eed:lib/image_science.rb
|
342
|
+
mem = FreeImage_OpenMemory(0,0);
|
343
|
+
result = FreeImage_SaveToMemory(fif, bitmap, mem, flags);
|
344
|
+
|
345
|
+
// get the buffer from the memory stream
|
346
|
+
FreeImage_AcquireMemory(mem, &mem_buffer, &size_in_bytes);
|
347
|
+
|
348
|
+
// convert to ruby string
|
349
|
+
str = rb_str_new(mem_buffer, size_in_bytes);
|
350
|
+
|
351
|
+
// clean up
|
352
|
+
if (unload) FreeImage_Unload(bitmap);
|
353
|
+
FreeImage_CloseMemory(mem);
|
354
|
+
|
355
|
+
<<<<<<< HEAD:lib/image_science.rb
|
356
|
+
// yield the string, or return it
|
357
|
+
if (rb_block_given_p()) {
|
358
|
+
if (result && str) {
|
359
|
+
rb_yield(str);
|
360
|
+
} else {
|
361
|
+
rb_yield(Qnil);
|
362
|
+
}
|
363
|
+
}
|
364
|
+
if (result && str) {
|
365
|
+
return str;
|
366
|
+
} else {
|
367
|
+
return Qnil;
|
368
|
+
}
|
369
|
+
}
|
370
|
+
snprintf(message,
|
371
|
+
1023,
|
372
|
+
"Unknown file format: %s",
|
373
|
+
extension);
|
374
|
+
rb_raise(rb_eTypeError, message);
|
375
|
+
=======
|
376
|
+
if (result) {
|
377
|
+
return str;
|
378
|
+
} else {
|
379
|
+
return Qfalse;
|
380
|
+
}
|
381
|
+
}
|
382
|
+
rb_raise(rb_eTypeError, "Unknown file format");
|
383
|
+
>>>>>>> 82c4446fc3ddc3121f6e9d36af299b5109aa7eed:lib/image_science.rb
|
384
|
+
}
|
385
|
+
END
|
386
|
+
end
|
387
|
+
end
|
data/test/pix.png
ADDED
Binary file
|
@@ -0,0 +1,190 @@
|
|
1
|
+
dir = File.expand_path "~/.ruby_inline"
|
2
|
+
if test ?d, dir then
|
3
|
+
require 'fileutils'
|
4
|
+
puts "nuking #{dir}"
|
5
|
+
# force removal, Windoze is bitching at me, something to hunt later...
|
6
|
+
FileUtils.rm_r dir, :force => true
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'minitest/unit'
|
11
|
+
require 'minitest/autorun' if $0 == __FILE__
|
12
|
+
require 'image_science'
|
13
|
+
|
14
|
+
class TestImageScience < MiniTest::Unit::TestCase
|
15
|
+
def setup
|
16
|
+
@path = 'test/pix.png'
|
17
|
+
@tmppath = 'test/pix-tmp.png'
|
18
|
+
@h = @w = 50
|
19
|
+
end
|
20
|
+
|
21
|
+
def teardown
|
22
|
+
File.unlink @tmppath if File.exist? @tmppath
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_class_with_image
|
26
|
+
ImageScience.with_image @path do |img|
|
27
|
+
assert_kind_of ImageScience, img
|
28
|
+
assert_equal @h, img.height
|
29
|
+
assert_equal @w, img.width
|
30
|
+
assert img.save(@tmppath)
|
31
|
+
end
|
32
|
+
|
33
|
+
assert File.exists?(@tmppath)
|
34
|
+
|
35
|
+
ImageScience.with_image @tmppath do |img|
|
36
|
+
assert_kind_of ImageScience, img
|
37
|
+
assert_equal @h, img.height
|
38
|
+
assert_equal @w, img.width
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_class_with_image_missing
|
43
|
+
assert_raises TypeError do
|
44
|
+
ImageScience.with_image @path + "nope" do |img|
|
45
|
+
flunk
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_class_with_image_missing_with_img_extension
|
51
|
+
assert_raises RuntimeError do
|
52
|
+
assert_nil ImageScience.with_image("nope#{@path}") do |img|
|
53
|
+
flunk
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_class_with_image_from_memory
|
59
|
+
data = File.new(@path).binmode.read
|
60
|
+
|
61
|
+
ImageScience.with_image_from_memory data do |img|
|
62
|
+
assert_kind_of ImageScience, img
|
63
|
+
assert_equal @h, img.height
|
64
|
+
assert_equal @w, img.width
|
65
|
+
assert img.save(@tmppath)
|
66
|
+
end
|
67
|
+
|
68
|
+
assert File.exists?(@tmppath)
|
69
|
+
|
70
|
+
ImageScience.with_image @tmppath do |img|
|
71
|
+
assert_kind_of ImageScience, img
|
72
|
+
assert_equal @h, img.height
|
73
|
+
assert_equal @w, img.width
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_class_with_image_from_memory_empty_string
|
78
|
+
assert_raises TypeError do
|
79
|
+
ImageScience.with_image_from_memory "" do |img|
|
80
|
+
flunk
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_resize
|
86
|
+
ImageScience.with_image @path do |img|
|
87
|
+
img.resize(25, 25) do |thumb|
|
88
|
+
assert thumb.save(@tmppath)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
assert File.exists?(@tmppath)
|
93
|
+
|
94
|
+
ImageScience.with_image @tmppath do |img|
|
95
|
+
assert_kind_of ImageScience, img
|
96
|
+
assert_equal 25, img.height
|
97
|
+
assert_equal 25, img.width
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
<<<<<<< HEAD:test/test_image_science.rb
|
102
|
+
def test_buffer_return
|
103
|
+
ImageScience.with_image @path do |img|
|
104
|
+
img.resize(25, 25) do |thumb|
|
105
|
+
assert thumb.buffer('.jpg')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_buffer_yield
|
111
|
+
ImageScience.with_image @path do |img|
|
112
|
+
img.resize(25, 25) do |thumb|
|
113
|
+
thumb.buffer('.jpg') do |buffer|
|
114
|
+
assert buffer
|
115
|
+
end
|
116
|
+
=======
|
117
|
+
def test_buffer
|
118
|
+
buffer = nil
|
119
|
+
ImageScience.with_image @path do |img|
|
120
|
+
img.resize(25, 25) do |thumb|
|
121
|
+
buffer = thumb.buffer('.jpg')
|
122
|
+
File.open('/tmp/foo.jpg', 'w') { |f|
|
123
|
+
f.write buffer
|
124
|
+
}
|
125
|
+
assert buffer
|
126
|
+
>>>>>>> 82c4446fc3ddc3121f6e9d36af299b5109aa7eed:test/test_image_science.rb
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_resize_floats
|
132
|
+
ImageScience.with_image @path do |img|
|
133
|
+
img.resize(25.2, 25.7) do |thumb|
|
134
|
+
assert thumb.save(@tmppath)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
assert File.exists?(@tmppath)
|
139
|
+
|
140
|
+
ImageScience.with_image @tmppath do |img|
|
141
|
+
assert_kind_of ImageScience, img
|
142
|
+
assert_equal 25, img.height
|
143
|
+
assert_equal 25, img.width
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_resize_zero
|
148
|
+
assert_raises ArgumentError do
|
149
|
+
ImageScience.with_image @path do |img|
|
150
|
+
img.resize(0, 25) do |thumb|
|
151
|
+
assert thumb.save(@tmppath)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
refute File.exists?(@tmppath)
|
157
|
+
|
158
|
+
assert_raises ArgumentError do
|
159
|
+
ImageScience.with_image @path do |img|
|
160
|
+
img.resize(25, 0) do |thumb|
|
161
|
+
assert thumb.save(@tmppath)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
refute File.exists?(@tmppath)
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_resize_negative
|
170
|
+
assert_raises ArgumentError do
|
171
|
+
ImageScience.with_image @path do |img|
|
172
|
+
img.resize(-25, 25) do |thumb|
|
173
|
+
assert thumb.save(@tmppath)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
refute File.exists?(@tmppath)
|
179
|
+
|
180
|
+
assert_raises ArgumentError do
|
181
|
+
ImageScience.with_image @path do |img|
|
182
|
+
img.resize(25, -25) do |thumb|
|
183
|
+
assert thumb.save(@tmppath)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
refute File.exists?(@tmppath)
|
189
|
+
end
|
190
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: g1nn13-image_science
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- jim nist
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-24 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hoe
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.5.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: gemcutter
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.3.0
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: gemcutter
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.3.0
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: hoe-doofus
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.0.0
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: hoe-git
|
57
|
+
type: :development
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 1.3.0
|
64
|
+
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: hoe
|
67
|
+
type: :development
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 2.5.0
|
74
|
+
version:
|
75
|
+
description: |-
|
76
|
+
ImageScience is a clean and happy Ruby library that generates
|
77
|
+
thumbnails -- and kicks the living crap out of RMagick. Oh, and it
|
78
|
+
doesn't leak memory like a sieve. :)
|
79
|
+
|
80
|
+
For more information including build steps, see http://seattlerb.rubyforge.org/
|
81
|
+
email:
|
82
|
+
- jim@hotelicopter.com
|
83
|
+
executables:
|
84
|
+
- image_science_thumb
|
85
|
+
extensions: []
|
86
|
+
|
87
|
+
extra_rdoc_files:
|
88
|
+
- History.txt
|
89
|
+
- Manifest.txt
|
90
|
+
- README.txt
|
91
|
+
files:
|
92
|
+
- History.txt
|
93
|
+
- Manifest.txt
|
94
|
+
- README.txt
|
95
|
+
- Rakefile
|
96
|
+
- bench.rb
|
97
|
+
- bin/image_science_thumb
|
98
|
+
- lib/image_science.rb
|
99
|
+
- test/pix.png
|
100
|
+
- test/test_image_science.rb
|
101
|
+
has_rdoc: true
|
102
|
+
homepage: http://seattlerb.rubyforge.org/ImageScience.html
|
103
|
+
licenses: []
|
104
|
+
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options:
|
107
|
+
- --main
|
108
|
+
- README.txt
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: "0"
|
116
|
+
version:
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: "0"
|
122
|
+
version:
|
123
|
+
requirements: []
|
124
|
+
|
125
|
+
rubyforge_project: g1nn13-image_science
|
126
|
+
rubygems_version: 1.3.5
|
127
|
+
signing_key:
|
128
|
+
specification_version: 3
|
129
|
+
summary: ImageScience is a clean and happy Ruby library that generates thumbnails -- and kicks the living crap out of RMagick
|
130
|
+
test_files:
|
131
|
+
- test/test_image_science.rb
|