insano_image_resizer 0.3.9 → 0.4.0
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/lib/insano_image_resizer/processor.rb +21 -22
- metadata +2 -2
@@ -7,7 +7,7 @@ module InsanoImageResizer
|
|
7
7
|
include Configurable
|
8
8
|
include Shell
|
9
9
|
include Loggable
|
10
|
-
|
10
|
+
|
11
11
|
def initialize(options = {vips_path: "vips"})
|
12
12
|
@vips_path = options[:vips_path]
|
13
13
|
end
|
@@ -43,7 +43,7 @@ module InsanoImageResizer
|
|
43
43
|
if (interest_point[:xf])
|
44
44
|
interest_point[:x] = input_properties[:w] * interest_point[:xf]
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
if (interest_point[:yf])
|
48
48
|
interest_point[:y] = input_properties[:h] * interest_point[:yf]
|
49
49
|
end
|
@@ -64,16 +64,16 @@ module InsanoImageResizer
|
|
64
64
|
interest_size = {w: input_properties[:w] * interest_point[:region], h: input_properties[:h] * interest_point[:region]}
|
65
65
|
|
66
66
|
# Has the user specified both the width and the height of the viewport? If they haven't,
|
67
|
-
# let's go ahead and fill in the missing properties for them so that they get output at
|
67
|
+
# let's go ahead and fill in the missing properties for them so that they get output at
|
68
68
|
# the original aspect ratio of the image.
|
69
69
|
if ((viewport_size[:w] == nil) && (viewport_size[:h] == nil))
|
70
70
|
viewport_size = {w: input_properties[:w], h: input_properties[:h]}
|
71
|
-
|
71
|
+
|
72
72
|
elsif (viewport_size[:w] == nil)
|
73
|
-
viewport_size[:w] = (viewport_size[:h] * (input_properties[:w].to_f / input_properties[:h].to_f))
|
73
|
+
viewport_size[:w] = (viewport_size[:h] * (input_properties[:w].to_f / input_properties[:h].to_f))
|
74
74
|
|
75
75
|
elsif (viewport_size[:h] == nil)
|
76
|
-
viewport_size[:h] = (viewport_size[:w] * (input_properties[:h].to_f / input_properties[:w].to_f))
|
76
|
+
viewport_size[:h] = (viewport_size[:w] * (input_properties[:h].to_f / input_properties[:w].to_f))
|
77
77
|
end
|
78
78
|
|
79
79
|
# how can we take our current image and fit it into the viewport? Time for
|
@@ -86,7 +86,6 @@ module InsanoImageResizer
|
|
86
86
|
# showing just the 1/3 around the interest_point.
|
87
87
|
|
88
88
|
scale_to_fill = [viewport_size[:w] / input_properties[:w].to_f, viewport_size[:h] / input_properties[:h].to_f].max
|
89
|
-
|
90
89
|
scale_to_interest = [interest_size[:w] / input_properties[:w].to_f, interest_size[:h] / input_properties[:h].to_f].max
|
91
90
|
|
92
91
|
log.debug("POI: ")
|
@@ -102,25 +101,25 @@ module InsanoImageResizer
|
|
102
101
|
scale_for_best_region = [scale_to_fill, scale_to_interest].max
|
103
102
|
|
104
103
|
# cool! Now, let's figure out what the content offset within the image should be.
|
105
|
-
# We want to keep the point of interest in view whenever possible. First, let's
|
104
|
+
# We want to keep the point of interest in view whenever possible. First, let's
|
106
105
|
# compute an optimal frame around the POI:
|
107
|
-
best_region = {x: interest_point[:x].to_f - (input_properties[:w].to_f * scale_for_best_region) / 2,
|
106
|
+
best_region = {x: interest_point[:x].to_f - (input_properties[:w].to_f * scale_for_best_region) / 2,
|
108
107
|
y: interest_point[:y].to_f - (input_properties[:h].to_f * scale_for_best_region) / 2,
|
109
108
|
w: input_properties[:w].to_f * scale_for_best_region,
|
110
109
|
h: input_properties[:h].to_f * scale_for_best_region}
|
111
|
-
|
112
|
-
# Up to this point, we've been using 'scale_for_best_region' to be the preferred scale of the image.
|
110
|
+
|
111
|
+
# Up to this point, we've been using 'scale_for_best_region' to be the preferred scale of the image.
|
113
112
|
# So, scale could be 1/3 if we want to show the area around the POI, or 1 if we're fitting a whole image
|
114
113
|
# in a viewport that is exactly the same aspect ratio.
|
115
114
|
|
116
|
-
# The next step is to compute a scale that should be applied to the image to make this desired section of
|
115
|
+
# The next step is to compute a scale that should be applied to the image to make this desired section of
|
117
116
|
# the image fit within the viewport. This is different from the previous scale—if we wanted to fit 1/3 of
|
118
117
|
# the image in a 100x100 pixel viewport, we computed best_region using that 1/3, and now we need to find
|
119
118
|
# the scale that will fit it into 100px.
|
120
119
|
scale = [scale_to_fill, viewport_size[:w].to_f / best_region[:w], viewport_size[:h].to_f / best_region[:h]].max
|
121
120
|
|
122
|
-
# Next, we scale the best_region so that it is in final coordinates. When we perform the affine transform,
|
123
|
-
# it will SCALE the entire image and then CROP it to a region, so our transform rect needs to be in the
|
121
|
+
# Next, we scale the best_region so that it is in final coordinates. When we perform the affine transform,
|
122
|
+
# it will SCALE the entire image and then CROP it to a region, so our transform rect needs to be in the
|
124
123
|
# coordinate space of the SCALED image, not the initial image.
|
125
124
|
transform = {}
|
126
125
|
transform[:x] = best_region[:x] * scale
|
@@ -130,13 +129,13 @@ module InsanoImageResizer
|
|
130
129
|
transform[:scale] = scale
|
131
130
|
|
132
131
|
# transform now represents the region we'd like to have in the final image. All of it, or part of it, may
|
133
|
-
# not actually be within the bounds of the image! We're about to apply some constraints, but first let's
|
132
|
+
# not actually be within the bounds of the image! We're about to apply some constraints, but first let's
|
134
133
|
# trim the best_region so that it's the SHAPE of the viewport, not just the SCALE of the viewport. Remember,
|
135
134
|
# since the region is still centered around the POI, we can just trim equally on either the W or H as necessary.
|
136
135
|
transform[:x] -= (viewport_size[:w] - transform[:w]) / 2
|
137
136
|
transform[:y] -= (viewport_size[:h] - transform[:h]) / 2
|
138
|
-
transform[:w] = viewport_size[:w]
|
139
|
-
transform[:h] = viewport_size[:h]
|
137
|
+
transform[:w] = viewport_size[:w].floor
|
138
|
+
transform[:h] = viewport_size[:h].floor
|
140
139
|
|
141
140
|
# alright—now our transform most likely extends beyond the bounds of the image
|
142
141
|
# data. Let's add some constraints that push it within the bounds of the image.
|
@@ -162,7 +161,7 @@ module InsanoImageResizer
|
|
162
161
|
return transform
|
163
162
|
end
|
164
163
|
|
165
|
-
def run_transform(input_path, output_path, transform, quality =
|
164
|
+
def run_transform(input_path, output_path, transform, quality = 90)
|
166
165
|
# Call through to VIPS:
|
167
166
|
# int im_affinei(in, out, interpolate, a, b, c, d, dx, dy, x, y, w, h)
|
168
167
|
# The first six params are a transformation matrix. A and D are used for X and Y
|
@@ -175,9 +174,9 @@ module InsanoImageResizer
|
|
175
174
|
if (output_extension == "jpg")
|
176
175
|
quality_extension = ":#{quality}"
|
177
176
|
end
|
178
|
-
|
177
|
+
|
179
178
|
if (transform[:scale] < 0.5)
|
180
|
-
# If we're shrinking the image by more than a factor of two, let's do a two-pass operation. The reason we do this
|
179
|
+
# If we're shrinking the image by more than a factor of two, let's do a two-pass operation. The reason we do this
|
181
180
|
# is that the interpolators, such as bilinear and bicubic, don't produce very good results when scaling an image
|
182
181
|
# by more than 1/2. Instead, we use a high-speed shrinking function to reduce the image by the smallest integer scale
|
183
182
|
# greater than the desired scale, and then go the rest of the way with an interpolated affine transform.
|
@@ -201,10 +200,10 @@ module InsanoImageResizer
|
|
201
200
|
run("#{@vips_path} im_affine '#{intermediate_path}' '#{output_path}#{quality_extension}' #{transform[:scale]} 0 0 #{transform[:scale]} 0 0 #{transform[:x]} #{transform[:y]} #{transform[:w]} #{transform[:h]}")
|
202
201
|
FileUtils.rm(intermediate_path)
|
203
202
|
|
204
|
-
else
|
203
|
+
else
|
205
204
|
run("#{@vips_path} im_affine '#{input_path}' '#{output_path}#{quality_extension}' #{transform[:scale]} 0 0 #{transform[:scale]} 0 0 #{transform[:x]} #{transform[:y]} #{transform[:w]} #{transform[:h]}")
|
206
205
|
end
|
207
|
-
|
206
|
+
|
208
207
|
FileUtils.rm(input_path)
|
209
208
|
return output_path
|
210
209
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: insano_image_resizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|