riiif 1.1.1 → 1.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b0af476f4ae806dfd50b80d55822b1b4e737bca3
4
- data.tar.gz: a19cc06b6257e2e8bfc20e10ebca47d842b71521
3
+ metadata.gz: 9ad33e2e0d258079efa25eef4e206dd4099996dd
4
+ data.tar.gz: 960a01a9a73dcf961ce4c945f6a2fcd64adca6ad
5
5
  SHA512:
6
- metadata.gz: bcfa15704d359abae49010c15e118f24a4107c56d0f5839a5cb8494216dabf7e6b8207338988b13f54b4ed39d37fa8857e6426a5974d376011d5bcdc1a1036f9
7
- data.tar.gz: 521ca263dd137a5a96e9d816f84576f04b3e175e0fc7c9382fdc33a88be375ff39a23b288645054f3c64142c9921fbd4c188ad8f0d57bccbf97ab7003ac96a60
6
+ metadata.gz: 4d6ead011f1e16fd7559fd67df911a1e964a4a8f17c73a549e4f9473b511021b675bbbe6b731cb86528a899138445a27427aab42e1a264ffb8e5b7d1869ba10d
7
+ data.tar.gz: 58eea4d035b7ac49adb4fa8fc91537e76114ee76d025fde5538502e0bfb9c5e672cae5b109a9a63ad0ddbd853652820b9612b7ac2297c7055eb40ac29865cd47
data/.rubocop.yml CHANGED
@@ -1,4 +1,12 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
+ AllCops:
4
+ TargetRubyVersion: 2.1
5
+ DisplayCopNames: true
6
+
3
7
  Style/IndentationConsistency:
4
8
  EnforcedStyle: rails
9
+
10
+ Metrics/BlockLength:
11
+ Exclude:
12
+ - spec/**/*
data/.rubocop_todo.yml CHANGED
@@ -28,11 +28,6 @@ Lint/UselessAssignment:
28
28
  Metrics/AbcSize:
29
29
  Max: 38
30
30
 
31
- # Offense count: 12
32
- # Configuration parameters: CountComments, ExcludedMethods.
33
- Metrics/BlockLength:
34
- Max: 143
35
-
36
31
  # Offense count: 1
37
32
  # Configuration parameters: CountComments.
38
33
  Metrics/ClassLength:
@@ -46,17 +41,13 @@ Metrics/CyclomaticComplexity:
46
41
  # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
47
42
  # URISchemes: http, https
48
43
  Metrics/LineLength:
49
- Max: 160
44
+ Max: 120
50
45
 
51
46
  # Offense count: 7
52
47
  # Configuration parameters: CountComments.
53
48
  Metrics/MethodLength:
54
49
  Max: 21
55
50
 
56
- # Offense count: 2
57
- Metrics/PerceivedComplexity:
58
- Max: 9
59
-
60
51
  # Offense count: 1
61
52
  # Cop supports --auto-correct.
62
53
  Performance/RedundantMatch:
@@ -59,7 +59,9 @@ module Riiif
59
59
  ##
60
60
  # @return [ActiveSupport::HashWithIndifferentAccess]
61
61
  def image_request_params
62
- params.permit(:region, :size, :rotation, :quality, :format).to_h
62
+ result = params.permit(:region, :size, :rotation, :quality, :format).to_h
63
+ return result.with_indifferent_access if Rails.version < '5'
64
+ result
63
65
  end
64
66
 
65
67
  def authorization_service
@@ -1,12 +1,9 @@
1
- require 'open3'
2
1
  module Riiif
3
2
  class File
4
- include Open3
5
- include ActiveSupport::Benchmarkable
6
-
7
3
  attr_reader :path
8
4
 
9
- delegate :logger, to: :Rails
5
+ class_attribute :info_extractor_class
6
+ self.info_extractor_class = ImageMagickInfoExtractor
10
7
 
11
8
  # @param input_path [String] The location of an image file
12
9
  def initialize(input_path, tempfile = nil)
@@ -34,48 +31,31 @@ module Riiif
34
31
 
35
32
  end
36
33
 
37
- def extract(options)
38
-
34
+ # @param [Transformation] transformation
35
+ def extract(transformation)
39
36
  command = 'convert'
40
- command << " -crop #{options[:crop]}" if options[:crop]
41
- command << " -resize #{options[:size]}" if options[:size]
42
- if options[:rotation]
43
- command << " -virtual-pixel white +distort srt #{options[:rotation]}"
37
+ command << " -crop #{transformation.crop}" if transformation.crop
38
+ command << " -resize #{transformation.size}" if transformation.size
39
+ if transformation.rotation
40
+ command << " -virtual-pixel white +distort srt #{transformation.rotation}"
44
41
  end
45
42
 
46
- case options[:quality]
43
+ case transformation.quality
47
44
  when 'grey'
48
45
  command << ' -colorspace Gray'
49
46
  when 'bitonal'
50
47
  command << ' -colorspace Gray'
51
48
  command << ' -type Bilevel'
52
49
  end
53
- command << " #{path} #{options[:format]}:-"
50
+ command << " #{path} #{transformation.format}:-"
54
51
  execute(command)
55
52
  end
56
53
 
57
54
  def info
58
- return @info if @info
59
- height, width = execute("identify -format %hx%w #{path}").split('x')
60
- @info = { height: Integer(height), width: Integer(width) }
55
+ @info ||= info_extractor_class.new(path).extract
61
56
  end
62
57
 
63
- private
64
-
65
- def execute(command)
66
- out = nil
67
- benchmark("Riiif executed #{command}") do
68
- stdin, stdout, stderr, wait_thr = popen3(command)
69
- stdin.close
70
- stdout.binmode
71
- out = stdout.read
72
- stdout.close
73
- err = stderr.read
74
- stderr.close
75
- raise "Unable to execute command \"#{command}\"\n#{err}" unless wait_thr.value.success?
76
- end
77
- out
78
- end
79
-
58
+ delegate :execute, to: Riiif::CommandRunner
59
+ private :execute
80
60
  end
81
61
  end
@@ -42,7 +42,10 @@ module Riiif
42
42
  end
43
43
 
44
44
  def info
45
- info_service.call(id, image)
45
+ @info ||= begin
46
+ result = info_service.call(id, image)
47
+ ImageInformation.new(result[:width], result[:height])
48
+ end
46
49
  end
47
50
 
48
51
  class << self
@@ -52,7 +55,7 @@ module Riiif
52
55
 
53
56
 
54
57
  def cache_key(id, options)
55
- str = options.merge(id: id).delete_if { |_, v| v.nil? }.to_s
58
+ str = options.to_h.merge(id: id).delete_if { |_, v| v.nil? }.to_s
56
59
  # Use a MD5 digest to ensure the keys aren't too long.
57
60
  Digest::MD5.hexdigest(str)
58
61
  end
@@ -62,14 +65,15 @@ module Riiif
62
65
 
63
66
  ##
64
67
  # @param [ActiveSupport::HashWithIndifferentAccess] options
68
+ # @return [Transformation]
65
69
  def decode_options!(options)
66
70
  raise ArgumentError, "You must provide a format. You provided #{options}" unless options[:format]
67
- options[:crop] = decode_region(options.delete(:region))
68
- options[:size] = decode_size(options.delete(:size))
69
- options[:quality] = decode_quality(options[:quality])
70
- options[:rotation] = decode_rotation(options[:rotation])
71
71
  validate_format!(options[:format])
72
- options
72
+ Riiif::Transformation.new(decode_region(options.delete(:region)),
73
+ decode_size(options.delete(:size)),
74
+ decode_quality(options[:quality]),
75
+ decode_rotation(options[:rotation]),
76
+ options[:format])
73
77
  end
74
78
 
75
79
  def decode_quality(quality)
@@ -94,47 +98,37 @@ module Riiif
94
98
 
95
99
  def decode_region(region)
96
100
  if region.nil? || region == 'full'
97
- nil
101
+ Riiif::Region::Imagemagick::FullDecoder.new.decode
98
102
  elsif md = /^pct:(\d+),(\d+),(\d+),(\d+)$/.match(region)
99
- # Image magic can't do percentage offsets, so we have to calculate it
100
- offset_x = (info[:width] * Integer(md[1]).to_f / 100).round
101
- offset_y = (info[:height] * Integer(md[2]).to_f / 100).round
102
- "#{md[3]}%x#{md[4]}+#{offset_x}+#{offset_y}"
103
+ Riiif::Region::Imagemagick::PercentageDecoder
104
+ .new(info, md[1], md[2], md[3], md[4]).decode
103
105
  elsif md = /^(\d+),(\d+),(\d+),(\d+)$/.match(region)
104
- "#{md[3]}x#{md[4]}+#{md[1]}+#{md[2]}"
106
+ Riiif::Region::Imagemagick::AbsoluteDecoder.new(md[1], md[2], md[3], md[4]).decode
105
107
  elsif region == 'square'
106
- w = info[:width]
107
- h = info[:height]
108
- min, max = [w, h].minmax
109
-
110
- offset = (max - min) / 2
111
- if h >= w
112
- "#{min}x#{min}+0+#{offset}"
113
- else
114
- "#{min}x#{min}+#{offset}+0"
115
- end
108
+ Riiif::Region::Imagemagick::SquareDecoder.new(info).decode
116
109
  else
117
110
  raise InvalidAttributeError, "Invalid region: #{region}"
118
111
  end
119
112
  end
120
113
 
114
+ # rubocop:disable Metrics/PerceivedComplexity
121
115
  def decode_size(size)
122
116
  if size.nil? || size == 'full'
123
- nil
117
+ Riiif::Size::Imagemagick::FullDecoder.new.decode
124
118
  elsif md = /^,(\d+)$/.match(size)
125
- "x#{md[1]}"
119
+ Riiif::Size::Imagemagick::HeightDecoder.new(md[1]).decode
126
120
  elsif md = /^(\d+),$/.match(size)
127
- (md[1]).to_s
121
+ Riiif::Size::Imagemagick::WidthDecoder.new(md[1]).decode
128
122
  elsif md = /^pct:(\d+(.\d+)?)$/.match(size)
129
- "#{md[1]}%"
123
+ Riiif::Size::Imagemagick::PercentDecoder.new(md[1]).decode
130
124
  elsif md = /^(\d+),(\d+)$/.match(size)
131
- "#{md[1]}x#{md[2]}!"
125
+ Riiif::Size::Imagemagick::AbsoluteDecoder.new(md[1], md[2]).decode
132
126
  elsif md = /^!(\d+),(\d+)$/.match(size)
133
- "#{md[1]}x#{md[2]}"
127
+ Riiif::Size::Imagemagick::BestFitDecoder.new(md[1], md[2]).decode
134
128
  else
135
129
  raise InvalidAttributeError, "Invalid size: #{size}"
136
130
  end
137
131
  end
138
-
132
+ # rubocop:enable Metrics/PerceivedComplexity
139
133
  end
140
134
  end
@@ -0,0 +1,28 @@
1
+ require 'open3'
2
+ module Riiif
3
+ # Runs shell commands under benchmark and saves the output
4
+ class CommandRunner
5
+ include Open3
6
+ include ActiveSupport::Benchmarkable
7
+ delegate :logger, to: :Rails
8
+
9
+ def execute(command)
10
+ out = nil
11
+ benchmark("Riiif executed #{command}") do
12
+ stdin, stdout, stderr, wait_thr = popen3(command)
13
+ stdin.close
14
+ stdout.binmode
15
+ out = stdout.read
16
+ stdout.close
17
+ err = stderr.read
18
+ stderr.close
19
+ raise "Unable to execute command \"#{command}\"\n#{err}" unless wait_thr.value.success?
20
+ end
21
+ out
22
+ end
23
+
24
+ def self.execute(command)
25
+ new.execute(command)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module Riiif
2
+ # Get height and width information using imagemagick to interrogate the file
3
+ class ImageMagickInfoExtractor
4
+ def initialize(path)
5
+ @path = path
6
+ end
7
+
8
+ def extract
9
+ height, width = Riiif::CommandRunner.execute("identify -format %hx%w #{@path}").split('x')
10
+ { height: Integer(height), width: Integer(width) }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ module Riiif
2
+ module Region
3
+ module Imagemagick
4
+ # decodes requested cooridnates into an imagemagick crop directive
5
+ class AbsoluteDecoder
6
+ def initialize(x, y, width, height)
7
+ @x = x
8
+ @y = y
9
+ @width = width
10
+ @height = height
11
+ end
12
+
13
+ # @return [String] a region for imagemagick to decode
14
+ # (appropriate for passing to the -crop parameter)
15
+ def decode
16
+ "#{@width}x#{@height}+#{@x}+#{@y}"
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ module Riiif
2
+ module Region
3
+ module Imagemagick
4
+ # The image or region is not scaled, and is returned at its full size.
5
+ class FullDecoder
6
+ # @return [NilClass] a region for imagemagick to decode
7
+ # the nil implies no cropping needed
8
+ def decode
9
+ nil
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ module Riiif
2
+ module Region
3
+ module Imagemagick
4
+ # decodes requested cooridnates into an imagemagick crop directive
5
+ class PercentageDecoder
6
+ def initialize(image_info, x, y, width, height)
7
+ @image_info = image_info
8
+ @x = x
9
+ @y = y
10
+ @width = width
11
+ @height = height
12
+ end
13
+
14
+ # Imagemagick can't do percentage offsets, so we have to calculate it
15
+ # @return [String] a region for imagemagick to decode
16
+ # (appropriate for passing to the -crop parameter)
17
+ def decode
18
+ "#{@width}%x#{@height}+#{offset_x}+#{offset_y}"
19
+ end
20
+
21
+ private
22
+
23
+ def offset_x
24
+ (@image_info.width * Integer(@x).to_f / 100).round
25
+ end
26
+
27
+ def offset_y
28
+ (@image_info.height * Integer(@y).to_f / 100).round
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,25 @@
1
+ module Riiif
2
+ module Region
3
+ module Imagemagick
4
+ # decodes requested cooridnates into an imagemagick crop directive
5
+ class SquareDecoder
6
+ def initialize(image_info)
7
+ @image_info = image_info
8
+ end
9
+
10
+ # @return [String] a square region for imagemagick to decode
11
+ # (appropriate for passing to the -crop parameter)
12
+ def decode
13
+ min, max = [@image_info.width, @image_info.height].minmax
14
+
15
+ offset = (max - min) / 2
16
+ if @image_info.height >= @image_info.width
17
+ "#{min}x#{min}+0+#{offset}"
18
+ else
19
+ "#{min}x#{min}+#{offset}+0"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ module Riiif
2
+ module Size
3
+ module Imagemagick
4
+ # The width and height of the returned image are exactly w and h.
5
+ # The aspect ratio of the returned image may be different than the extracted
6
+ # region, resulting in a distorted image.
7
+ class AbsoluteDecoder
8
+ def initialize(width, height)
9
+ @width = width
10
+ @height = height
11
+ end
12
+
13
+ # @return [String] a resize directive for imagemagick to use
14
+ def decode
15
+ "#{@width}x#{@height}!"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Riiif
2
+ module Size
3
+ module Imagemagick
4
+ # The image content is scaled for the best fit such that the resulting width and
5
+ # height are less than or equal to the requested width and height.
6
+ class BestFitDecoder
7
+ def initialize(width, height)
8
+ @width = width
9
+ @height = height
10
+ end
11
+
12
+ # @return [String] a resize directive for imagemagick to use
13
+ def decode
14
+ "#{@width}x#{@height}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ module Riiif
2
+ module Size
3
+ module Imagemagick
4
+ # decodes requested size into an imagemagick resize directive
5
+ class FullDecoder
6
+ # @return [NilClass] a size for imagemagick to decode
7
+ # the nil implies no resizing needed
8
+ def decode
9
+ nil
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ module Riiif
2
+ module Size
3
+ module Imagemagick
4
+ # The image or region should be scaled so that its height is exactly equal
5
+ # to the provided parameter, and the width will be a calculated value that
6
+ # maintains the aspect ratio of the extracted region
7
+ class HeightDecoder
8
+ def initialize(height)
9
+ @height = height
10
+ end
11
+
12
+ # @return [String] a resize directive for imagemagick to use
13
+ def decode
14
+ "x#{@height}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Riiif
2
+ module Size
3
+ module Imagemagick
4
+ # The width and height of the returned image is scaled to n% of the width and height
5
+ # of the extracted region. The aspect ratio of the returned image is the same as that
6
+ # of the extracted region.
7
+ class PercentDecoder
8
+ def initialize(n)
9
+ @n = n
10
+ end
11
+
12
+ # @return [String] a resize directive for imagemagick to use
13
+ def decode
14
+ "#{@n}%"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Riiif
2
+ module Size
3
+ module Imagemagick
4
+ # The image or region should be scaled so that its width is exactly equal
5
+ # to the provided parameter, and the height will be a calculated value that
6
+ # maintains the aspect ratio of the extracted region
7
+ class WidthDecoder
8
+ def initialize(width)
9
+ @width = width
10
+ end
11
+
12
+ # @return [String] a resize directive for imagemagick to use
13
+ def decode
14
+ @width.to_s
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
data/lib/riiif/routes.rb CHANGED
@@ -22,7 +22,9 @@ module Riiif
22
22
  defaults: { format: 'jpg', rotation: '0', region: 'full', quality: 'default', model: resource },
23
23
  as: options[:as] || 'image'
24
24
 
25
- get "#{route_prefix}/:id/info.json" => 'riiif/images#info', defaults: { format: 'json', model: resource }, as: [options[:as], 'info'].compact.join('_')
25
+ get "#{route_prefix}/:id/info.json" => 'riiif/images#info',
26
+ defaults: { format: 'json', model: resource },
27
+ as: [options[:as], 'info'].compact.join('_')
26
28
 
27
29
  # This doesn't work presently
28
30
  # get "#{route_prefix}/:id", to: redirect("#{route_prefix}/%{id}/info.json")
data/lib/riiif/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Riiif
2
- VERSION = '1.1.1'.freeze
2
+ VERSION = '1.1.2'.freeze
3
3
  end
data/lib/riiif.rb CHANGED
@@ -20,5 +20,7 @@ module Riiif
20
20
  end
21
21
  end
22
22
 
23
+ Transformation = Struct.new(:crop, :size, :quality, :rotation, :format)
24
+ ImageInformation = Struct.new(:width, :height)
23
25
  mattr_accessor :not_found_image # the image to use when a lookup fails
24
26
  end
data/riiif.gemspec CHANGED
@@ -24,6 +24,6 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency 'engine_cart', '~> 0.8'
25
25
  spec.add_development_dependency 'rspec-rails'
26
26
  spec.add_development_dependency 'sqlite3'
27
- spec.add_development_dependency 'rubocop', '~> 0.41.2'
28
- spec.add_development_dependency 'rubocop-rspec', '~> 1.5'
27
+ spec.add_development_dependency 'rubocop', '~> 0.47.1'
28
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.13'
29
29
  end
@@ -7,6 +7,7 @@ describe Riiif::AkubraSystemFileResolver do
7
7
  end
8
8
 
9
9
  it 'gets the jpeg2000 file' do
10
- expect(subject.find('demo:1').path).to eq Riiif::File.new(Dir.glob(subject.pathroot + '22/7e/9/info%3Afedora%2Fdemo%3A1%2Fjp2%2Fjp2.0').first).path
10
+ file = Dir.glob(subject.pathroot + '22/7e/9/info%3Afedora%2Fdemo%3A1%2Fjp2%2Fjp2.0').first
11
+ expect(subject.find('demo:1').path).to eq Riiif::File.new(file).path
11
12
  end
12
13
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Riiif::Image do
3
+ RSpec.describe Riiif::Image do
4
4
  before { Rails.cache.clear }
5
5
  let(:filename) { File.expand_path('spec/samples/world.jp2') }
6
6
  subject { described_class.new('world') }
@@ -16,7 +16,7 @@ describe Riiif::Image do
16
16
  it 'is able to override the file used for the Image' do
17
17
  img = described_class.new('some_id', Riiif::File.new(filename))
18
18
  expect(img.id).to eq 'some_id'
19
- expect(img.info).to eq height: 400, width: 800
19
+ expect(img.info).to eq Riiif::ImageInformation.new(800, 400)
20
20
  end
21
21
 
22
22
  describe 'without a format' do
@@ -27,7 +27,7 @@ describe Riiif::Image do
27
27
 
28
28
  describe 'info' do
29
29
  it 'returns the data' do
30
- expect(subject.info).to eq height: 400, width: 800
30
+ expect(subject.info).to eq Riiif::ImageInformation.new(800, 400)
31
31
  end
32
32
  end
33
33
 
@@ -45,7 +45,7 @@ describe Riiif::Image do
45
45
  describe 'get info' do
46
46
  subject { described_class.new('Cave_26,_Ajanta') }
47
47
  it 'is easy' do
48
- expect(subject.info).to eq height: 390, width: 600
48
+ expect(subject.info).to eq Riiif::ImageInformation.new(600, 390)
49
49
  end
50
50
  end
51
51
 
@@ -63,21 +63,25 @@ describe Riiif::Image do
63
63
  describe 'mogrify' do
64
64
  describe 'region' do
65
65
  it 'returns the original when specifing full size' do
66
- expect(subject.image).to receive(:execute).with("convert #{filename} png:-")
66
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert #{filename} png:-")
67
67
  subject.render(region: 'full', format: 'png')
68
68
  end
69
69
  it 'handles absolute geometry' do
70
- expect(subject.image).to receive(:execute).with("convert -crop 60x75+80+15 #{filename} png:-")
70
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert -crop 60x75+80+15 #{filename} png:-")
71
71
  subject.render(region: '80,15,60,75', format: 'png')
72
72
  end
73
+
73
74
  it 'handles percent geometry' do
74
- expect(subject.image).to receive(:execute).with("identify -format %hx%w #{filename}").and_return('131x175')
75
- expect(subject.image).to receive(:execute).with("convert -crop 80%x70+18+13 #{filename} png:-")
75
+ expect(Riiif::CommandRunner).to receive(:execute)
76
+ .with("identify -format %hx%w #{filename}").and_return('131x175')
77
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert -crop 80%x70+18+13 #{filename} png:-")
76
78
  subject.render(region: 'pct:10,10,80,70', format: 'png')
77
79
  end
80
+
78
81
  it 'handles square geometry' do
79
- expect(subject.image).to receive(:execute).with("identify -format %hx%w #{filename}").and_return('131x175')
80
- expect(subject.image).to receive(:execute).with("convert -crop 131x131+22+0 #{filename} png:-")
82
+ expect(Riiif::CommandRunner).to receive(:execute)
83
+ .with("identify -format %hx%w #{filename}").and_return('131x175')
84
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert -crop 131x131+22+0 #{filename} png:-")
81
85
  subject.render(region: 'square', format: 'png')
82
86
  end
83
87
  it 'raises an error for invalid geometry' do
@@ -87,31 +91,31 @@ describe Riiif::Image do
87
91
 
88
92
  describe 'resize' do
89
93
  it 'returns the original when specifing full size' do
90
- expect(subject.image).to receive(:execute).with("convert #{filename} png:-")
94
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert #{filename} png:-")
91
95
  subject.render(size: 'full', format: 'png')
92
96
  end
93
97
  it 'handles integer percent sizes' do
94
- expect(subject.image).to receive(:execute).with("convert -resize 50% #{filename} png:-")
98
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert -resize 50% #{filename} png:-")
95
99
  subject.render(size: 'pct:50', format: 'png')
96
100
  end
97
101
  it 'handles float percent sizes' do
98
- expect(subject.image).to receive(:execute).with("convert -resize 12.5% #{filename} png:-")
102
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert -resize 12.5% #{filename} png:-")
99
103
  subject.render(size: 'pct:12.5', format: 'png')
100
104
  end
101
105
  it 'handles w,' do
102
- expect(subject.image).to receive(:execute).with("convert -resize 50 #{filename} png:-")
106
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert -resize 50 #{filename} png:-")
103
107
  subject.render(size: '50,', format: 'png')
104
108
  end
105
109
  it 'handles ,h' do
106
- expect(subject.image).to receive(:execute).with("convert -resize x50 #{filename} png:-")
110
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert -resize x50 #{filename} png:-")
107
111
  subject.render(size: ',50', format: 'png')
108
112
  end
109
113
  it 'handles w,h' do
110
- expect(subject.image).to receive(:execute).with("convert -resize 150x75! #{filename} png:-")
114
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert -resize 150x75! #{filename} png:-")
111
115
  subject.render(size: '150,75', format: 'png')
112
116
  end
113
117
  it 'handles bestfit (!w,h)' do
114
- expect(subject.image).to receive(:execute).with("convert -resize 150x75 #{filename} png:-")
118
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert -resize 150x75 #{filename} png:-")
115
119
  subject.render(size: '!150,75', format: 'png')
116
120
  end
117
121
  it 'raises an error for invalid size' do
@@ -121,11 +125,12 @@ describe Riiif::Image do
121
125
 
122
126
  describe 'rotate' do
123
127
  it 'returns the original when specifing full size' do
124
- expect(subject.image).to receive(:execute).with("convert #{filename} png:-")
128
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert #{filename} png:-")
125
129
  subject.render(rotation: '0', format: 'png')
126
130
  end
127
131
  it 'handles floats' do
128
- expect(subject.image).to receive(:execute).with("convert -virtual-pixel white +distort srt 22.5 #{filename} png:-")
132
+ expect(Riiif::CommandRunner).to receive(:execute)
133
+ .with("convert -virtual-pixel white +distort srt 22.5 #{filename} png:-")
129
134
  subject.render(rotation: '22.5', format: 'png')
130
135
  end
131
136
  it 'raises an error for invalid angle' do
@@ -135,19 +140,20 @@ describe Riiif::Image do
135
140
 
136
141
  describe 'quality' do
137
142
  it 'returns the original when specifing default' do
138
- expect(subject.image).to receive(:execute).with("convert #{filename} png:-")
143
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert #{filename} png:-")
139
144
  subject.render(quality: 'default', format: 'png')
140
145
  end
141
146
  it 'returns the original when specifing color' do
142
- expect(subject.image).to receive(:execute).with("convert #{filename} png:-")
147
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert #{filename} png:-")
143
148
  subject.render(quality: 'color', format: 'png')
144
149
  end
145
150
  it 'converts to grayscale' do
146
- expect(subject.image).to receive(:execute).with("convert -colorspace Gray #{filename} png:-")
151
+ expect(Riiif::CommandRunner).to receive(:execute).with("convert -colorspace Gray #{filename} png:-")
147
152
  subject.render(quality: 'grey', format: 'png')
148
153
  end
149
154
  it 'converts to bitonal' do
150
- expect(subject.image).to receive(:execute).with("convert -colorspace Gray -type Bilevel #{filename} png:-")
155
+ expect(Riiif::CommandRunner).to receive(:execute)
156
+ .with("convert -colorspace Gray -type Bilevel #{filename} png:-")
151
157
  subject.render(quality: 'bitonal', format: 'png')
152
158
  end
153
159
  it 'raises an error for invalid angle' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riiif
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-09 00:00:00.000000000 Z
11
+ date: 2017-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -106,28 +106,28 @@ dependencies:
106
106
  requirements:
107
107
  - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: 0.41.2
109
+ version: 0.47.1
110
110
  type: :development
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: 0.41.2
116
+ version: 0.47.1
117
117
  - !ruby/object:Gem::Dependency
118
118
  name: rubocop-rspec
119
119
  requirement: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: '1.5'
123
+ version: '1.13'
124
124
  type: :development
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: '1.5'
130
+ version: '1.13'
131
131
  description: A IIIF image server
132
132
  email:
133
133
  - justin@curationexperts.com
@@ -148,6 +148,18 @@ files:
148
148
  - app/controllers/riiif/images_controller.rb
149
149
  - app/models/riiif/file.rb
150
150
  - app/models/riiif/image.rb
151
+ - app/services/riiif/command_runner.rb
152
+ - app/services/riiif/image_magick_info_extractor.rb
153
+ - app/services/riiif/region/imagemagick/absolute_decoder.rb
154
+ - app/services/riiif/region/imagemagick/full_decoder.rb
155
+ - app/services/riiif/region/imagemagick/percentage_decoder.rb
156
+ - app/services/riiif/region/imagemagick/square_decoder.rb
157
+ - app/services/riiif/size/imagemagick/absolute_decoder.rb
158
+ - app/services/riiif/size/imagemagick/best_fit_decoder.rb
159
+ - app/services/riiif/size/imagemagick/full_decoder.rb
160
+ - app/services/riiif/size/imagemagick/height_decoder.rb
161
+ - app/services/riiif/size/imagemagick/percent_decoder.rb
162
+ - app/services/riiif/size/imagemagick/width_decoder.rb
151
163
  - config/routes.rb
152
164
  - lib/riiif.rb
153
165
  - lib/riiif/abstract_file_system_resolver.rb
@@ -190,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
202
  version: '0'
191
203
  requirements: []
192
204
  rubyforge_project:
193
- rubygems_version: 2.6.10
205
+ rubygems_version: 2.6.8
194
206
  signing_key:
195
207
  specification_version: 4
196
208
  summary: A rails engine that support IIIF requests