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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +2 -11
  3. data/.rubocop_todo.yml +76 -33
  4. data/README.md +17 -2
  5. data/app/controllers/riiif/images_controller.rb +8 -2
  6. data/app/models/riiif/image.rb +15 -20
  7. data/app/models/riiif/image_information.rb +12 -24
  8. data/app/services/riiif/crop.rb +99 -30
  9. data/app/services/riiif/image_magick_info_extractor.rb +9 -2
  10. data/app/services/riiif/imagemagick_command_factory.rb +9 -4
  11. data/app/services/riiif/kakadu_command_factory.rb +2 -2
  12. data/app/services/riiif/resize.rb +72 -7
  13. data/app/transformers/riiif/kakadu_transformer.rb +25 -2
  14. data/docs/benchmark.md +75 -0
  15. data/lib/riiif/engine.rb +2 -1
  16. data/lib/riiif/routes.rb +3 -0
  17. data/lib/riiif/version.rb +1 -1
  18. data/riiif.gemspec +3 -3
  19. data/spec/controllers/riiif/images_controller_spec.rb +14 -3
  20. data/spec/models/riiif/image_information_spec.rb +2 -10
  21. data/spec/models/riiif/image_spec.rb +10 -16
  22. data/spec/services/riiif/imagemagick_command_factory_spec.rb +6 -6
  23. data/spec/services/riiif/kakadu_command_factory_spec.rb +15 -15
  24. data/spec/transformers/riiif/kakadu_transformer_spec.rb +22 -22
  25. metadata +24 -46
  26. data/app/models/riiif/transformation.rb +0 -35
  27. data/app/services/riiif/imagemagick_transformer.rb +0 -8
  28. data/app/services/riiif/option_decoder.rb +0 -88
  29. data/app/services/riiif/region/absolute.rb +0 -23
  30. data/app/services/riiif/region/full.rb +0 -23
  31. data/app/services/riiif/region/percentage.rb +0 -68
  32. data/app/services/riiif/region/square.rb +0 -45
  33. data/app/services/riiif/size/absolute.rb +0 -39
  34. data/app/services/riiif/size/best_fit.rb +0 -18
  35. data/app/services/riiif/size/full.rb +0 -17
  36. data/app/services/riiif/size/height.rb +0 -24
  37. data/app/services/riiif/size/percent.rb +0 -44
  38. data/app/services/riiif/size/width.rb +0 -24
  39. data/spec/models/riiif/transformation_spec.rb +0 -42
  40. data/spec/services/riiif/region/absolute_spec.rb +0 -17
  41. data/spec/services/riiif/size/absolute_spec.rb +0 -17
  42. data/spec/services/riiif/size/height_spec.rb +0 -13
  43. 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