riiif 2.0.0.beta2 → 2.0.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.
- 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
|