riiif 2.0.0.beta2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +2 -11
- data/.rubocop_todo.yml +76 -33
- data/README.md +17 -2
- data/app/controllers/riiif/images_controller.rb +8 -2
- data/app/models/riiif/image.rb +15 -20
- data/app/models/riiif/image_information.rb +12 -24
- data/app/services/riiif/crop.rb +99 -30
- data/app/services/riiif/image_magick_info_extractor.rb +9 -2
- data/app/services/riiif/imagemagick_command_factory.rb +9 -4
- data/app/services/riiif/kakadu_command_factory.rb +2 -2
- data/app/services/riiif/resize.rb +72 -7
- data/app/transformers/riiif/kakadu_transformer.rb +25 -2
- data/docs/benchmark.md +75 -0
- data/lib/riiif/engine.rb +2 -1
- data/lib/riiif/routes.rb +3 -0
- data/lib/riiif/version.rb +1 -1
- data/riiif.gemspec +3 -3
- data/spec/controllers/riiif/images_controller_spec.rb +14 -3
- data/spec/models/riiif/image_information_spec.rb +2 -10
- data/spec/models/riiif/image_spec.rb +10 -16
- data/spec/services/riiif/imagemagick_command_factory_spec.rb +6 -6
- data/spec/services/riiif/kakadu_command_factory_spec.rb +15 -15
- data/spec/transformers/riiif/kakadu_transformer_spec.rb +22 -22
- metadata +24 -46
- data/app/models/riiif/transformation.rb +0 -35
- data/app/services/riiif/imagemagick_transformer.rb +0 -8
- data/app/services/riiif/option_decoder.rb +0 -88
- data/app/services/riiif/region/absolute.rb +0 -23
- data/app/services/riiif/region/full.rb +0 -23
- data/app/services/riiif/region/percentage.rb +0 -68
- data/app/services/riiif/region/square.rb +0 -45
- data/app/services/riiif/size/absolute.rb +0 -39
- data/app/services/riiif/size/best_fit.rb +0 -18
- data/app/services/riiif/size/full.rb +0 -17
- data/app/services/riiif/size/height.rb +0 -24
- data/app/services/riiif/size/percent.rb +0 -44
- data/app/services/riiif/size/width.rb +0 -24
- data/spec/models/riiif/transformation_spec.rb +0 -42
- data/spec/services/riiif/region/absolute_spec.rb +0 -17
- data/spec/services/riiif/size/absolute_spec.rb +0 -17
- data/spec/services/riiif/size/height_spec.rb +0 -13
- data/spec/services/riiif/size/width_spec.rb +0 -13
@@ -1,23 +0,0 @@
|
|
1
|
-
module Riiif
|
2
|
-
module Region
|
3
|
-
# Represents an absolute specified region
|
4
|
-
class Absolute < Crop
|
5
|
-
# TODO: only kakadu needs image_info. So there's potenial to optimize by
|
6
|
-
# making image_info a proxy that fetches the info lazily when needed.
|
7
|
-
# @param [ImageInformation] image_info
|
8
|
-
# @param [String] x
|
9
|
-
# @param [String] y
|
10
|
-
# @param [String] width
|
11
|
-
# @param [String] height
|
12
|
-
def initialize(image_info, x, y, width, height)
|
13
|
-
@image_info = image_info
|
14
|
-
@offset_x = x.to_i
|
15
|
-
@offset_y = y.to_i
|
16
|
-
@width = width.to_i
|
17
|
-
@height = height.to_i
|
18
|
-
end
|
19
|
-
|
20
|
-
attr_reader :width, :height
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Riiif
|
2
|
-
module Region
|
3
|
-
# Represents the image or region requested at its full size.
|
4
|
-
# This is a nil crop operation.
|
5
|
-
class Full < Crop
|
6
|
-
def initialize(image_info)
|
7
|
-
@image_info = image_info
|
8
|
-
end
|
9
|
-
|
10
|
-
# @return [NilClass] a region for imagemagick to decode
|
11
|
-
# the nil implies no cropping needed
|
12
|
-
def to_imagemagick
|
13
|
-
nil
|
14
|
-
end
|
15
|
-
|
16
|
-
# @return [NilClass] a region for kakadu to decode
|
17
|
-
# the nil implies no cropping needed
|
18
|
-
def to_kakadu
|
19
|
-
nil
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
module Riiif
|
2
|
-
module Region
|
3
|
-
# represents request cooridnates specified as percentage
|
4
|
-
class Percentage < Crop
|
5
|
-
def initialize(image_info, x, y, width, height)
|
6
|
-
@image_info = image_info
|
7
|
-
@x_pct = x
|
8
|
-
@y_pct = y
|
9
|
-
@width_pct = width
|
10
|
-
@height_pct = height
|
11
|
-
end
|
12
|
-
|
13
|
-
# From the Imagemagick docs:
|
14
|
-
# The percentage symbol '%' can appear anywhere in a argument, and if
|
15
|
-
# given will refer to both width and height numbers. It is a flag that
|
16
|
-
# just declares that the 'image size' parts are a percentage fraction
|
17
|
-
# of the images virtual canvas or page size. Offsets are always given
|
18
|
-
# in pixels.
|
19
|
-
# @return [String] a region for imagemagick to decode
|
20
|
-
# (appropriate for passing to the -crop parameter)
|
21
|
-
def to_imagemagick
|
22
|
-
"#{@width_pct}%x#{@height_pct}+#{offset_x}+#{offset_y}"
|
23
|
-
end
|
24
|
-
|
25
|
-
def maintain_aspect_ratio?
|
26
|
-
@width_pct == @height_pct
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
# @param [String] n a percentage to convert
|
32
|
-
# @return [Float]
|
33
|
-
def percentage_to_fraction(n)
|
34
|
-
Integer(n).to_f / 100
|
35
|
-
end
|
36
|
-
|
37
|
-
# @return [Integer]
|
38
|
-
def offset_x
|
39
|
-
(@image_info.width * percentage_to_fraction(@x_pct)).round
|
40
|
-
end
|
41
|
-
|
42
|
-
# @return [Integer]
|
43
|
-
def offset_y
|
44
|
-
(@image_info.height * percentage_to_fraction(@y_pct)).round
|
45
|
-
end
|
46
|
-
|
47
|
-
# @return [Float]
|
48
|
-
def decimal_height
|
49
|
-
percentage_to_fraction(@height_pct)
|
50
|
-
end
|
51
|
-
|
52
|
-
# @return [Float]
|
53
|
-
def decimal_width
|
54
|
-
percentage_to_fraction(@width_pct)
|
55
|
-
end
|
56
|
-
|
57
|
-
# @return [Float]
|
58
|
-
def decimal_offset_y
|
59
|
-
percentage_to_fraction(@y_pct)
|
60
|
-
end
|
61
|
-
|
62
|
-
# @return [Float]
|
63
|
-
def decimal_offset_x
|
64
|
-
percentage_to_fraction(@x_pct)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module Riiif
|
2
|
-
module Region
|
3
|
-
# Represents requested square cooridnates
|
4
|
-
class Square < Crop
|
5
|
-
def initialize(image_info)
|
6
|
-
@image_info = image_info
|
7
|
-
@min, @max = [@image_info.width, @image_info.height].minmax
|
8
|
-
@offset = (@max - @min) / 2
|
9
|
-
end
|
10
|
-
|
11
|
-
# @return [String] a square region for imagemagick to decode
|
12
|
-
# (appropriate for passing to the -crop parameter)
|
13
|
-
def to_imagemagick
|
14
|
-
if @image_info.height >= @image_info.width
|
15
|
-
"#{height}x#{width}+0+#{@offset}"
|
16
|
-
else
|
17
|
-
"#{height}x#{width}+#{@offset}+0"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# @return [String] a region for kakadu to decode
|
22
|
-
# (appropriate for passing to the -region parameter)
|
23
|
-
def to_kakadu
|
24
|
-
# (top, left, height, width)
|
25
|
-
if @image_info.height >= @image_info.width
|
26
|
-
# Portrait
|
27
|
-
"\{#{decimal_height(@offset)},0\}," \
|
28
|
-
"\{#{decimal_height(height)},#{decimal_width(height)}\}"
|
29
|
-
else
|
30
|
-
# Landscape
|
31
|
-
"\{0,#{decimal_width(@offset)}\}," \
|
32
|
-
"\{#{decimal_height(width)},#{decimal_width(width)}\}"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def height
|
37
|
-
@min
|
38
|
-
end
|
39
|
-
|
40
|
-
def width
|
41
|
-
@min
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module Riiif
|
2
|
-
module Size
|
3
|
-
# The width and height of the returned image are exactly w and h.
|
4
|
-
# The aspect ratio of the returned image may be different than the extracted
|
5
|
-
# region, resulting in a distorted image.
|
6
|
-
class Absolute < Resize
|
7
|
-
# @param [ImageInformation] info
|
8
|
-
# @param [String] width
|
9
|
-
# @param [String] height
|
10
|
-
def initialize(info, width, height)
|
11
|
-
@image_info = info
|
12
|
-
@width = width.to_i
|
13
|
-
@height = height.to_i
|
14
|
-
end
|
15
|
-
|
16
|
-
# @return [String] a resize directive for imagemagick to use
|
17
|
-
def to_imagemagick
|
18
|
-
"#{@width}x#{@height}!"
|
19
|
-
end
|
20
|
-
|
21
|
-
attr_reader :height, :width
|
22
|
-
|
23
|
-
# Reduce this if the aspect ratio of the image is maintained.
|
24
|
-
def reduce?
|
25
|
-
in_delta?(image_info.aspect_ratio, aspect_ratio, 0.001)
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def aspect_ratio
|
31
|
-
width.to_f / height
|
32
|
-
end
|
33
|
-
|
34
|
-
def in_delta?(x1, x2, delta)
|
35
|
-
(x1 - x2).abs <= delta
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Riiif
|
2
|
-
module Size
|
3
|
-
# The image content is scaled for the best fit such that the resulting width and
|
4
|
-
# height are less than or equal to the requested width and height.
|
5
|
-
class BestFit < Resize
|
6
|
-
def initialize(info, width, height)
|
7
|
-
@image_info = info
|
8
|
-
@width = width
|
9
|
-
@height = height
|
10
|
-
end
|
11
|
-
|
12
|
-
# @return [String] a resize directive for imagemagick to use
|
13
|
-
def to_imagemagick
|
14
|
-
"#{@width}x#{@height}"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Riiif
|
2
|
-
module Size
|
3
|
-
# represents requested full size
|
4
|
-
class Full < Resize
|
5
|
-
# @return [NilClass] a size for imagemagick to decode
|
6
|
-
# the nil implies no resizing needed
|
7
|
-
def to_imagemagick
|
8
|
-
nil
|
9
|
-
end
|
10
|
-
|
11
|
-
# Should we reduce this image?
|
12
|
-
def reduce?
|
13
|
-
false
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module Riiif
|
2
|
-
module Size
|
3
|
-
# The image or region should be scaled so that its height is exactly equal
|
4
|
-
# to the provided parameter, and the width will be a calculated value that
|
5
|
-
# maintains the aspect ratio of the extracted region
|
6
|
-
class Height < Resize
|
7
|
-
def initialize(info, height)
|
8
|
-
@image_info = info
|
9
|
-
@height = height.to_i
|
10
|
-
end
|
11
|
-
|
12
|
-
# @return [String] a resize directive for imagemagick to use
|
13
|
-
def to_imagemagick
|
14
|
-
"x#{@height}"
|
15
|
-
end
|
16
|
-
|
17
|
-
def width
|
18
|
-
height * image_info.width / image_info.height
|
19
|
-
end
|
20
|
-
|
21
|
-
attr_reader :height
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module Riiif
|
2
|
-
module Size
|
3
|
-
# The width and height of the returned image is scaled to n% of the width and height
|
4
|
-
# of the extracted region. The aspect ratio of the returned image is the same as that
|
5
|
-
# of the extracted region.
|
6
|
-
class Percent < Resize
|
7
|
-
def initialize(info, percentage)
|
8
|
-
@image_info = info
|
9
|
-
@percentage = percentage
|
10
|
-
end
|
11
|
-
|
12
|
-
attr_reader :percentage
|
13
|
-
|
14
|
-
# @return [String] a resize directive for imagemagick to use
|
15
|
-
def to_imagemagick
|
16
|
-
"#{percentage}%"
|
17
|
-
end
|
18
|
-
|
19
|
-
# @return [Integer] the height in pixels
|
20
|
-
def height
|
21
|
-
percent_of(image_info.height)
|
22
|
-
end
|
23
|
-
|
24
|
-
# @return [Integer] the width in pixels
|
25
|
-
def width
|
26
|
-
percent_of(image_info.width)
|
27
|
-
end
|
28
|
-
|
29
|
-
# @param [Integer] factor number of times to reduce by 1/2
|
30
|
-
def reduce(factor)
|
31
|
-
pct = percentage.to_f * 2**factor
|
32
|
-
Percent.new(image_info, pct)
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
# @param [Integer] value a value to convert to the percentage
|
38
|
-
# @return [Float]
|
39
|
-
def percent_of(value)
|
40
|
-
value * Integer(percentage).to_f / 100
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module Riiif
|
2
|
-
module Size
|
3
|
-
# The image or region should be scaled so that its width is exactly equal
|
4
|
-
# to the provided parameter, and the height will be a calculated value that
|
5
|
-
# maintains the aspect ratio of the extracted region
|
6
|
-
class Width < Resize
|
7
|
-
def initialize(info, width)
|
8
|
-
@image_info = info
|
9
|
-
@width = width.to_i
|
10
|
-
end
|
11
|
-
|
12
|
-
# @return [String] a resize directive for imagemagick to use
|
13
|
-
def to_imagemagick
|
14
|
-
@width.to_s
|
15
|
-
end
|
16
|
-
|
17
|
-
attr_reader :width
|
18
|
-
|
19
|
-
def height
|
20
|
-
width * image_info.height / image_info.width
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe Riiif::Transformation do
|
6
|
-
subject(:transformation) do
|
7
|
-
Riiif::Transformation.new(region,
|
8
|
-
size,
|
9
|
-
quality,
|
10
|
-
rotation,
|
11
|
-
fmt)
|
12
|
-
end
|
13
|
-
|
14
|
-
let(:region) { Riiif::Region::Full.new(image_info) }
|
15
|
-
let(:size) { Riiif::Size::Percent.new(image_info, 20) }
|
16
|
-
let(:quality) { nil }
|
17
|
-
let(:rotation) { nil }
|
18
|
-
let(:fmt) { nil }
|
19
|
-
let(:image_info) { double('Image info', height: 4381, width: 6501) }
|
20
|
-
|
21
|
-
describe 'reduce' do
|
22
|
-
subject { transformation.reduce(factor) }
|
23
|
-
context 'when reduced by 2' do
|
24
|
-
let(:factor) { 2 }
|
25
|
-
let(:size) { Riiif::Size::Percent.new(image_info, 20) }
|
26
|
-
|
27
|
-
it 'downsamples the size' do
|
28
|
-
expect(subject.size).to be_kind_of Riiif::Size::Percent
|
29
|
-
expect(subject.size.percentage).to eq 80.0
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe 'without_crop' do
|
35
|
-
let(:region) { Riiif::Region::Absolute.new(image_info, 5, 6, 7, 8) }
|
36
|
-
|
37
|
-
subject { transformation.without_crop(image_info) }
|
38
|
-
it 'nullifies the crop' do
|
39
|
-
expect(subject.crop).to be_kind_of Riiif::Region::Full
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Riiif::Region::Absolute do
|
4
|
-
let(:image_info) { double }
|
5
|
-
|
6
|
-
context 'when initialized with strings' do
|
7
|
-
let(:instance) { described_class.new(image_info, '5', '15', '50', '100') }
|
8
|
-
|
9
|
-
it 'casts height to an integer' do
|
10
|
-
expect(instance.height).to eq 100
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'casts width to an integer' do
|
14
|
-
expect(instance.width).to eq 50
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Riiif::Size::Absolute do
|
4
|
-
let(:image_info) { double }
|
5
|
-
|
6
|
-
context 'when initialized with strings' do
|
7
|
-
let(:instance) { described_class.new(image_info, '50', '100') }
|
8
|
-
|
9
|
-
it 'casts height to an integer' do
|
10
|
-
expect(instance.height).to eq 100
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'casts width to an integer' do
|
14
|
-
expect(instance.width).to eq 50
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Riiif::Size::Height do
|
4
|
-
let(:image_info) { double }
|
5
|
-
|
6
|
-
context 'when initialized with strings' do
|
7
|
-
let(:instance) { described_class.new(image_info, '50') }
|
8
|
-
|
9
|
-
it 'casts height to an integer' do
|
10
|
-
expect(instance.height).to eq 50
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Riiif::Size::Width do
|
4
|
-
let(:image_info) { double }
|
5
|
-
|
6
|
-
context 'when initialized with strings' do
|
7
|
-
let(:instance) { described_class.new(image_info, '50') }
|
8
|
-
|
9
|
-
it 'casts height to an integer' do
|
10
|
-
expect(instance.width).to eq 50
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|