riiif 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -0
- data/app/controllers/riiif/images_controller.rb +26 -0
- data/app/models/riiif/file.rb +87 -0
- data/app/models/riiif/image.rb +16 -36
- data/app/views/riiif/images/view.html.erb +21 -0
- data/config/routes.rb +5 -1
- data/lib/riiif.rb +1 -0
- data/lib/riiif/file_system_file_resolver.rb +1 -1
- data/lib/riiif/http_file_resolver.rb +24 -0
- data/lib/riiif/version.rb +1 -1
- data/riiif.gemspec +1 -2
- data/spec/controllers/images_controller_spec.rb +17 -0
- data/spec/models/image_spec.rb +45 -33
- data/spec/routing/resize_routes_spec.rb +26 -6
- data/vendor/assets/images/openseadragon/fullpage_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/fullpage_hover.png +0 -0
- data/vendor/assets/images/openseadragon/fullpage_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/fullpage_rest.png +0 -0
- data/vendor/assets/images/openseadragon/home_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/home_hover.png +0 -0
- data/vendor/assets/images/openseadragon/home_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/home_rest.png +0 -0
- data/vendor/assets/images/openseadragon/next_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/next_hover.png +0 -0
- data/vendor/assets/images/openseadragon/next_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/next_rest.png +0 -0
- data/vendor/assets/images/openseadragon/previous_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/previous_hover.png +0 -0
- data/vendor/assets/images/openseadragon/previous_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/previous_rest.png +0 -0
- data/vendor/assets/images/openseadragon/zoomin_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/zoomin_hover.png +0 -0
- data/vendor/assets/images/openseadragon/zoomin_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/zoomin_rest.png +0 -0
- data/vendor/assets/images/openseadragon/zoomout_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/zoomout_hover.png +0 -0
- data/vendor/assets/images/openseadragon/zoomout_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/zoomout_rest.png +0 -0
- data/vendor/assets/javascripts/openseadragon.js +12279 -0
- metadata +30 -18
- data/spec/samples/world.jp2 +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2267ef01c3a2abbf3991710ef5c4c9f6ac55500c
|
4
|
+
data.tar.gz: 13fc80e6e72c789bac048f66fc020d8a0cb2e314
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d45589ca6d5e13de6d7a40a61b09c48e9d062118c1845d9fd786e7d8f5066980d9e1adb8d1a4b1df7b419a6729248fec8bc8ea6338d0e9216324a94d9cec7eb
|
7
|
+
data.tar.gz: 64600eb8e05f1f613b7a039ed6c25b36f5f87d75f1993b9dad667ae3eea9e47e5fe9b66200ef4a03f3fc96862e307cdc2adf936e69609206e02cd4014562553b
|
data/README.md
CHANGED
@@ -15,7 +15,32 @@ And then execute:
|
|
15
15
|
Or install it yourself as:
|
16
16
|
|
17
17
|
$ gem install riiif
|
18
|
+
|
19
|
+
## Configure
|
18
20
|
|
21
|
+
### Images on the servers file system.
|
22
|
+
|
23
|
+
By default Riiif is set to load images from the filesystem using the Riiif::FileSystemFileResolver.
|
24
|
+
You can configure how this resolver finds the files by setting this property:
|
25
|
+
```
|
26
|
+
Riiif::FileSystemFileResolver.base_path = '/opt/repository/images/'
|
27
|
+
```
|
28
|
+
When the Id passed in is "foo_image", then it will look for an image file using this glob:
|
29
|
+
```
|
30
|
+
/opt/repository/images/foo_image.{png,jpg,tiff,jp,jp2}
|
31
|
+
```
|
32
|
+
|
33
|
+
### Images retrieved over HTTP
|
34
|
+
To source the images from the network instead of the file system, we first configure Riiif to use an alternative resolver:
|
35
|
+
```
|
36
|
+
Riiif::Image.file_resolver = Riiif::HTTPFileResolver
|
37
|
+
```
|
38
|
+
Then we configure the resolver with a mechanism for mapping the provided id to a url:
|
39
|
+
```
|
40
|
+
Riiif::HTTPFileResolver.id_to_uri = lambda do |id|
|
41
|
+
"http://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/#{id}.jpg/600px-#{id}.jpg"
|
42
|
+
end
|
43
|
+
```
|
19
44
|
## Usage
|
20
45
|
|
21
46
|
Mount the gem as an engine:
|
@@ -1,9 +1,35 @@
|
|
1
1
|
module Riiif
|
2
2
|
class ImagesController < ::ApplicationController
|
3
|
+
before_filter :link_header, only: [:show, :info]
|
3
4
|
def show
|
4
5
|
image = Image.new(params[:id])
|
5
6
|
data = image.render(params.permit(:region, :size, :rotation, :quality, :format))
|
6
7
|
send_data data, type: Mime::Type.lookup_by_extension(params[:format]), :disposition => 'inline'
|
7
8
|
end
|
9
|
+
|
10
|
+
def info
|
11
|
+
image = Image.new(params[:id])
|
12
|
+
render json: image.info.merge(server_info)
|
13
|
+
end
|
14
|
+
|
15
|
+
def view
|
16
|
+
@image = Image.new(params[:id])
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def link_header
|
22
|
+
response.headers["Link"] = '<http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level2>;rel="profile"'
|
23
|
+
end
|
24
|
+
|
25
|
+
def server_info
|
26
|
+
{
|
27
|
+
"@context" => "http://library.stanford.edu/iiif/image-api/1.1/context.json",
|
28
|
+
"@id" => request.original_url.sub('/info.json', ''),
|
29
|
+
"formats" => Image::OUTPUT_FORMATS,
|
30
|
+
"profile" => "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level0"
|
31
|
+
|
32
|
+
}
|
33
|
+
end
|
8
34
|
end
|
9
35
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'open3'
|
2
|
+
module Riiif
|
3
|
+
class File
|
4
|
+
include Open3
|
5
|
+
attr_reader :path
|
6
|
+
# @param input_path [String] The location of an image file
|
7
|
+
def initialize(input_path, tempfile = nil)
|
8
|
+
raise "HUH" if input_path.is_a? Riiif::File
|
9
|
+
@path = input_path
|
10
|
+
@tempfile = tempfile # ensures that the tempfile will stick around until this file is garbage collected.
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.open(file_or_url, ext = nil)
|
14
|
+
file_or_url = file_or_url.to_s # Force it to be a String... hell or highwater
|
15
|
+
if file_or_url.include?("://")
|
16
|
+
require 'open-uri'
|
17
|
+
ext ||= ::File.extname(URI.parse(file_or_url).path)
|
18
|
+
Kernel::open(file_or_url) do |f|
|
19
|
+
self.read(f, ext)
|
20
|
+
end
|
21
|
+
else
|
22
|
+
self.new(file_or_url)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.read(stream, ext)
|
27
|
+
create(ext) do |f|
|
28
|
+
while chunk = stream.read(8192)
|
29
|
+
f.write(chunk)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.create(ext = nil, validate = true, &block)
|
35
|
+
begin
|
36
|
+
tempfile = Tempfile.new(['mini_magick', ext.to_s.downcase])
|
37
|
+
tempfile.binmode
|
38
|
+
block.call(tempfile)
|
39
|
+
tempfile.close
|
40
|
+
image = self.new(tempfile.path, tempfile)
|
41
|
+
ensure
|
42
|
+
tempfile.close if tempfile
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def extract(options)
|
47
|
+
|
48
|
+
command = 'convert'
|
49
|
+
command << " -crop #{options[:crop]}" if options[:crop]
|
50
|
+
command << " -resize #{options[:size]}" if options[:size]
|
51
|
+
if options[:rotation]
|
52
|
+
command << " -virtual-pixel white +distort srt #{options[:rotation]}"
|
53
|
+
end
|
54
|
+
|
55
|
+
case options[:quality]
|
56
|
+
when 'grey'
|
57
|
+
command << ' -colorspace Gray'
|
58
|
+
when 'bitonal'
|
59
|
+
command << ' -colorspace Gray'
|
60
|
+
command << ' -type Bilevel'
|
61
|
+
end
|
62
|
+
command << " #{path} #{options[:format]}:-"
|
63
|
+
Rails.logger.debug "RIIIF executed: #{command}"
|
64
|
+
execute(command)
|
65
|
+
end
|
66
|
+
|
67
|
+
def info
|
68
|
+
return @info if @info
|
69
|
+
height, width = execute("identify -format %hx%w #{path}").split('x')
|
70
|
+
@info = {height: Integer(height), width: Integer(width)}
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def execute(command)
|
75
|
+
stdin, stdout, stderr, wait_thr = popen3(command)
|
76
|
+
stdin.close
|
77
|
+
stdout.binmode
|
78
|
+
out = stdout.read
|
79
|
+
stdout.close
|
80
|
+
err = stderr.read
|
81
|
+
stderr.close
|
82
|
+
raise "Unable to execute command \"#{command}\"\n#{err}" unless wait_thr.value.success?
|
83
|
+
out
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
data/app/models/riiif/image.rb
CHANGED
@@ -1,37 +1,30 @@
|
|
1
|
-
require 'mini_magick'
|
2
1
|
module Riiif
|
3
2
|
class Image
|
3
|
+
|
4
4
|
class_attribute :file_resolver
|
5
5
|
self.file_resolver = FileSystemFileResolver
|
6
6
|
|
7
|
-
|
7
|
+
OUTPUT_FORMATS = %W{jpg png}
|
8
|
+
|
9
|
+
attr_reader :path_name, :id
|
8
10
|
|
9
11
|
# @param [String] id The identifier of the file
|
10
12
|
def initialize(id)
|
13
|
+
@id = id
|
11
14
|
@path_name = file_resolver.find(id)
|
12
15
|
end
|
13
16
|
|
14
17
|
def render(args)
|
15
18
|
options = decode_options!(args)
|
19
|
+
Rails.cache.fetch(options.merge(id: id), compress: true, expires_in: 3.days) do
|
20
|
+
image.extract(options)
|
21
|
+
end
|
22
|
+
end
|
16
23
|
|
17
|
-
|
18
|
-
c.crop options[:crop] if options[:crop]
|
19
|
-
c.resize options[:size] if options[:size]
|
20
|
-
if options[:rotation]
|
21
|
-
c.virtual_pixel 'white'
|
22
|
-
c.distort.+ 'srt', options[:rotation]
|
23
|
-
end
|
24
|
+
delegate :info, to: :image
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
c.colorspace "Gray"
|
28
|
-
when 'bitonal'
|
29
|
-
c.colorspace "Gray"
|
30
|
-
c.type 'Bilevel'
|
31
|
-
end
|
32
|
-
end
|
33
|
-
image.format(options[:format])
|
34
|
-
image.to_blob
|
26
|
+
def image
|
27
|
+
@image ||= Riiif::File.open(path_name)
|
35
28
|
end
|
36
29
|
|
37
30
|
private
|
@@ -63,7 +56,7 @@ module Riiif
|
|
63
56
|
end
|
64
57
|
|
65
58
|
def validate_format!(format)
|
66
|
-
raise InvalidAttributeError, "Unsupported format: #{format}" unless
|
59
|
+
raise InvalidAttributeError, "Unsupported format: #{format}" unless OUTPUT_FORMATS.include?(format)
|
67
60
|
|
68
61
|
end
|
69
62
|
|
@@ -72,8 +65,8 @@ module Riiif
|
|
72
65
|
nil
|
73
66
|
elsif md = /^pct:(\d+),(\d+),(\d+),(\d+)$/.match(region)
|
74
67
|
# Image magic can't do percentage offsets, so we have to calculate it
|
75
|
-
offset_x = (
|
76
|
-
offset_y = (
|
68
|
+
offset_x = (info[:width] * Integer(md[1]).to_f / 100).round
|
69
|
+
offset_y = (info[:height] * Integer(md[2]).to_f / 100).round
|
77
70
|
"#{md[3]}%x#{md[4]}+#{offset_x}+#{offset_y}"
|
78
71
|
elsif md = /^(\d+),(\d+),(\d+),(\d+)$/.match(region)
|
79
72
|
"#{md[3]}x#{md[4]}+#{md[1]}+#{md[2]}"
|
@@ -89,7 +82,7 @@ module Riiif
|
|
89
82
|
"x#{md[1]}"
|
90
83
|
elsif md = /^(\d+),$/.match(size)
|
91
84
|
"#{md[1]}"
|
92
|
-
elsif md = /^pct:(\d+)$/.match(size)
|
85
|
+
elsif md = /^pct:(\d+(.\d+)?)$/.match(size)
|
93
86
|
"#{md[1]}%"
|
94
87
|
elsif md = /^(\d+),(\d+)$/.match(size)
|
95
88
|
"#{md[1]}x#{md[2]}!"
|
@@ -100,18 +93,5 @@ module Riiif
|
|
100
93
|
end
|
101
94
|
end
|
102
95
|
|
103
|
-
def image
|
104
|
-
begin
|
105
|
-
@image ||= MiniMagick::Image.open(path_name)
|
106
|
-
rescue Errno::ENOENT => e
|
107
|
-
Rails.logger.error "Unable to find #{path_name}"
|
108
|
-
Rails.logger.error e.backtrace
|
109
|
-
raise Riiif::Error, "Unable to find #{path_name}"
|
110
|
-
rescue MiniMagick::Error => e
|
111
|
-
Rails.logger.error "Error trying to open #{path_name}"
|
112
|
-
Rails.logger.error e.backtrace
|
113
|
-
raise Riiif::Error, "Unable to open the image #{path_name}"
|
114
|
-
end
|
115
|
-
end
|
116
96
|
end
|
117
97
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<div id="openseadragon1" style="width: 800px; height: 600px;"></div>
|
2
|
+
<%=javascript_include_tag "openseadragon.js" %>
|
3
|
+
<script type="text/javascript">
|
4
|
+
var viewer = OpenSeadragon({
|
5
|
+
id: "openseadragon1",
|
6
|
+
prefixUrl: "/assets/openseadragon/",
|
7
|
+
tileSources: [{
|
8
|
+
"image_host": "http://localhost:8080/image-service",
|
9
|
+
"identifier": "irises",
|
10
|
+
"width": 4264,
|
11
|
+
"height": 3282,
|
12
|
+
"scale_factors": [1, 2, 3, 4, 5],
|
13
|
+
"tile_width": 1024,
|
14
|
+
"tile_height": 1024,
|
15
|
+
"formats": [ "jpg", "png" ],
|
16
|
+
"qualities": ["native", "bitonal", "grey", "color"],
|
17
|
+
"profile": "http://library.stanford.edu/iiif/image-api/compliance.html#level1"
|
18
|
+
}]
|
19
|
+
});
|
20
|
+
</script>
|
21
|
+
DOOD
|
data/config/routes.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
Riiif::Engine.routes.draw do
|
2
2
|
ALLOW_DOTS ||= /[\w.]+/
|
3
|
-
|
3
|
+
PERCENTAGE ||= /(pct:)?[\w.]+/
|
4
|
+
get "/:id/:region/:size/:rotation/:quality(.:format)" => "images#show",
|
5
|
+
constraints: { rotation: ALLOW_DOTS, size: PERCENTAGE}
|
6
|
+
get "/:id/info(.:format)" => "images#info", :constraints => { :format => /json/}
|
7
|
+
get "/:id/view(.:format)" => "images#view"
|
4
8
|
end
|
data/lib/riiif.rb
CHANGED
@@ -13,7 +13,7 @@ module Riiif
|
|
13
13
|
|
14
14
|
def self.pattern(id)
|
15
15
|
raise ArgumentException, "Invalid characters in id `#{id}`" unless /^\w+$/.match(id)
|
16
|
-
File.join(base_path, "#{id}.{#{input_types.join(',')}}")
|
16
|
+
::File.join(base_path, "#{id}.{#{input_types.join(',')}}")
|
17
17
|
end
|
18
18
|
|
19
19
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Riiif
|
2
|
+
module HTTPFileResolver
|
3
|
+
|
4
|
+
# Set a lambda that maps the first parameter (id) to a URL
|
5
|
+
# Example:
|
6
|
+
#
|
7
|
+
# Riiif::HTTPFileResolver.id_to_uri = lambda do |id|
|
8
|
+
# "http://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/#{id}.jpg/600px-#{id}.jpg"
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
mattr_accessor :id_to_uri
|
12
|
+
|
13
|
+
def self.find(id)
|
14
|
+
uri(id)
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def self.uri(id)
|
20
|
+
raise "Must set the id_to_uri lambda" if id_to_uri.nil?
|
21
|
+
id_to_uri.call(id)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/riiif/version.rb
CHANGED
data/riiif.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = ""
|
14
14
|
spec.license = "APACHE2"
|
15
15
|
|
16
|
-
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.files = `git ls-files|grep -v spec/samples`.split($/)
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
@@ -22,6 +22,5 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_development_dependency "engine_cart"
|
24
24
|
spec.add_development_dependency "rspec-rails"
|
25
|
-
spec.add_dependency 'mini_magick'
|
26
25
|
spec.add_dependency 'rails', '> 3.2.0'
|
27
26
|
end
|
@@ -12,5 +12,22 @@ describe Riiif::ImagesController do
|
|
12
12
|
rotation: '0', quality: 'native', format: 'jpg'
|
13
13
|
expect(response).to be_successful
|
14
14
|
expect(response.body).to eq 'IMAGEDATA'
|
15
|
+
expect(response.headers['Link']).to eq '<http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level2>;rel="profile"'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return info" do
|
19
|
+
image = double
|
20
|
+
expect(Riiif::Image).to receive(:new).with('abcd1234').and_return(image)
|
21
|
+
expect(image).to receive(:info).and_return({width: 6000, height: 4000 })
|
22
|
+
get :info, id: 'abcd1234', format: 'json'
|
23
|
+
expect(response).to be_successful
|
24
|
+
json = JSON.parse(response.body)
|
25
|
+
expect(json).to eq "@context"=>"http://library.stanford.edu/iiif/image-api/1.1/context.json",
|
26
|
+
"@id" =>"http://test.host/image-service/abcd1234",
|
27
|
+
"width" =>6000,
|
28
|
+
"height" =>4000,
|
29
|
+
"formats" => [ "jpg", "png" ],
|
30
|
+
"profile" => "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level0"
|
31
|
+
expect(response.headers['Link']).to eq '<http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level2>;rel="profile"'
|
15
32
|
end
|
16
33
|
end
|
data/spec/models/image_spec.rb
CHANGED
@@ -1,15 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Riiif::Image do
|
4
|
+
before { Rails.cache.clear }
|
5
|
+
let(:filename) { File.expand_path('spec/samples/world.jp2') }
|
4
6
|
subject { Riiif::Image.new('world') }
|
5
7
|
describe "happy path" do
|
6
|
-
let(:combinator) { double }
|
7
|
-
let(:inner) { double }
|
8
8
|
before do
|
9
|
-
expect(
|
10
|
-
expect(inner).to receive(:to_blob).and_return('imagedata')
|
11
|
-
inner.stub(:combine_options).and_yield(combinator)
|
12
|
-
subject.stub(:image).and_return(inner)
|
9
|
+
expect(subject.image).to receive(:execute).with("convert #{filename} jpg:-").and_return('imagedata')
|
13
10
|
end
|
14
11
|
it "should render" do
|
15
12
|
expect(subject.render('size' => 'full', format: 'jpg')).to eq 'imagedata'
|
@@ -22,27 +19,42 @@ describe Riiif::Image do
|
|
22
19
|
end
|
23
20
|
end
|
24
21
|
|
22
|
+
describe "info" do
|
23
|
+
it "should return the data" do
|
24
|
+
expect(subject.info).to eq height: 400, width:800
|
25
|
+
end
|
26
|
+
end
|
25
27
|
|
26
|
-
describe "
|
27
|
-
let(:combinator) { double }
|
28
|
-
let(:inner) { double(format: true, to_blob: 'imagedata') }
|
28
|
+
describe "get images from web" do
|
29
29
|
before do
|
30
|
-
|
31
|
-
|
30
|
+
Riiif::Image.file_resolver = Riiif::HTTPFileResolver
|
31
|
+
Riiif::HTTPFileResolver.id_to_uri = lambda do |id|
|
32
|
+
"http://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/#{id}.jpg/600px-#{id}.jpg"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
after do
|
36
|
+
Riiif::Image.file_resolver = Riiif::FileSystemFileResolver
|
37
|
+
end
|
38
|
+
subject { Riiif::Image.new('Cave_26,_Ajanta') }
|
39
|
+
it "should be easy" do
|
40
|
+
expect(subject.info).to eq height: 390, width:600
|
32
41
|
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
describe "mogrify" do
|
33
46
|
describe "region" do
|
34
47
|
it "should return the original when specifing full size" do
|
35
|
-
expect(
|
48
|
+
expect(subject.image).to receive(:execute).with("convert #{filename} png:-")
|
36
49
|
subject.render(region: 'full', format: 'png')
|
37
50
|
end
|
38
51
|
it "should handle absolute geometry" do
|
39
|
-
expect(
|
52
|
+
expect(subject.image).to receive(:execute).with("convert -crop 60x75+80+15 #{filename} png:-")
|
40
53
|
subject.render(region: '80,15,60,75', format: 'png')
|
41
54
|
end
|
42
55
|
it "should handle percent geometry" do
|
43
|
-
expect(
|
44
|
-
expect(
|
45
|
-
expect(combinator).to receive(:crop).with('80%x70+18+13')
|
56
|
+
expect(subject.image).to receive(:execute).with("identify -format %hx%w #{filename}").and_return('131x175')
|
57
|
+
expect(subject.image).to receive(:execute).with("convert -crop 80%x70+18+13 #{filename} png:-")
|
46
58
|
subject.render(region: 'pct:10,10,80,70', format: 'png')
|
47
59
|
end
|
48
60
|
it "should raise an error for invalid geometry" do
|
@@ -52,27 +64,31 @@ describe Riiif::Image do
|
|
52
64
|
|
53
65
|
describe "resize" do
|
54
66
|
it "should return the original when specifing full size" do
|
55
|
-
expect(
|
67
|
+
expect(subject.image).to receive(:execute).with("convert #{filename} png:-")
|
56
68
|
subject.render(size: 'full', format: 'png')
|
57
69
|
end
|
58
|
-
it "should handle percent sizes" do
|
59
|
-
expect(
|
70
|
+
it "should handle integer percent sizes" do
|
71
|
+
expect(subject.image).to receive(:execute).with("convert -resize 50% #{filename} png:-")
|
60
72
|
subject.render(size: 'pct:50', format: 'png')
|
61
73
|
end
|
74
|
+
it "should handle float percent sizes" do
|
75
|
+
expect(subject.image).to receive(:execute).with("convert -resize 12.5% #{filename} png:-")
|
76
|
+
subject.render(size: 'pct:12.5', format: 'png')
|
77
|
+
end
|
62
78
|
it "should handle w," do
|
63
|
-
expect(
|
79
|
+
expect(subject.image).to receive(:execute).with("convert -resize 50 #{filename} png:-")
|
64
80
|
subject.render(size: '50,', format: 'png')
|
65
81
|
end
|
66
82
|
it "should handle ,h" do
|
67
|
-
expect(
|
83
|
+
expect(subject.image).to receive(:execute).with("convert -resize x50 #{filename} png:-")
|
68
84
|
subject.render(size: ',50', format: 'png')
|
69
85
|
end
|
70
86
|
it "should handle w,h" do
|
71
|
-
expect(
|
87
|
+
expect(subject.image).to receive(:execute).with("convert -resize 150x75! #{filename} png:-")
|
72
88
|
subject.render(size: '150,75', format: 'png')
|
73
89
|
end
|
74
90
|
it "should handle bestfit (!w,h)" do
|
75
|
-
expect(
|
91
|
+
expect(subject.image).to receive(:execute).with("convert -resize 150x75 #{filename} png:-")
|
76
92
|
subject.render(size: '!150,75', format: 'png')
|
77
93
|
end
|
78
94
|
it "should raise an error for invalid size" do
|
@@ -81,15 +97,12 @@ describe Riiif::Image do
|
|
81
97
|
end
|
82
98
|
|
83
99
|
describe "rotate" do
|
84
|
-
let(:distorter) { double }
|
85
100
|
it "should return the original when specifing full size" do
|
86
|
-
expect(
|
101
|
+
expect(subject.image).to receive(:execute).with("convert #{filename} png:-")
|
87
102
|
subject.render(rotation: '0', format: 'png')
|
88
103
|
end
|
89
104
|
it "should handle floats" do
|
90
|
-
expect(
|
91
|
-
expect(combinator).to receive(:virtual_pixel).with('white')
|
92
|
-
expect(distorter).to receive(:+).with("srt", 22.5)
|
105
|
+
expect(subject.image).to receive(:execute).with("convert -virtual-pixel white +distort srt 22.5 #{filename} png:-")
|
93
106
|
subject.render(rotation: '22.5', format: 'png')
|
94
107
|
end
|
95
108
|
it "should raise an error for invalid angle" do
|
@@ -99,20 +112,19 @@ describe Riiif::Image do
|
|
99
112
|
|
100
113
|
describe "quality" do
|
101
114
|
it "should return the original when specifing native" do
|
102
|
-
expect(
|
115
|
+
expect(subject.image).to receive(:execute).with("convert #{filename} png:-")
|
103
116
|
subject.render(quality: 'native', format: 'png')
|
104
117
|
end
|
105
118
|
it "should return the original when specifing color" do
|
106
|
-
expect(
|
119
|
+
expect(subject.image).to receive(:execute).with("convert #{filename} png:-")
|
107
120
|
subject.render(quality: 'color', format: 'png')
|
108
121
|
end
|
109
122
|
it "should convert to grayscale" do
|
110
|
-
expect(
|
123
|
+
expect(subject.image).to receive(:execute).with("convert -colorspace Gray #{filename} png:-")
|
111
124
|
subject.render(quality: 'grey', format: 'png')
|
112
125
|
end
|
113
126
|
it "should convert to bitonal" do
|
114
|
-
expect(
|
115
|
-
expect(combinator).to receive(:type).with('Bilevel')
|
127
|
+
expect(subject.image).to receive(:execute).with("convert -colorspace Gray -type Bilevel #{filename} png:-")
|
116
128
|
subject.render(quality: 'bitonal', format: 'png')
|
117
129
|
end
|
118
130
|
it "should raise an error for invalid angle" do
|