assembly-image 1.8.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +4 -1
- data/.gitignore +2 -1
- data/.rubocop.yml +23 -5
- data/.rubocop_todo.yml +11 -51
- data/.rvmrc.example +1 -1
- data/Gemfile.lock +105 -0
- data/README.md +15 -58
- data/assembly-image.gemspec +4 -5
- data/bin/console +1 -1
- data/config/boot.rb +2 -2
- data/lib/assembly/image/jp2_creator.rb +127 -0
- data/lib/assembly/image.rb +58 -0
- data/lib/assembly-image.rb +5 -3
- data/profiles/cmyk.icc +0 -0
- data/spec/assembly/image/jp2_creator_spec.rb +327 -38
- data/spec/assembly/image_spec.rb +25 -0
- data/spec/spec_helper.rb +115 -29
- data/spec/test_data/color_rgb_srgb_rot90cw.tif +0 -0
- metadata +39 -38
- data/bin/run_all_tests +0 -3
- data/lib/assembly-image/image.rb +0 -162
- data/lib/assembly-image/images.rb +0 -107
- data/lib/assembly-image/jp2_creator.rb +0 -182
- data/lib/assembly-image/version.rb +0 -10
- data/spec/image_spec.rb +0 -279
- data/spec/images_spec.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '088a4b9c59b50f893f7b50c16898321770006b4ab22dc08a8ddd70cdba9a15da'
|
4
|
+
data.tar.gz: f22bf6d6acbd4d6885e2102526e7c5e0ac76b93af71eff0d2237d32334afd223
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91f0be3622982ad69823a45eca8111d05756e0442cd7d7aa16cb8099e71ee2e95c21f17c7f14b7ccab04c11724233c9a9739e24f8b8302f07f42b16738c6400e
|
7
|
+
data.tar.gz: d1ab206c475413496a6add9376cb246705df18a3142bdc32189b202e31af698b8cfded84464d00e94357fc08396ab142270043b3b862cc0d68cd57834863b649
|
data/.circleci/config.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
version: 2.1
|
2
2
|
orbs:
|
3
|
-
ruby-rails: sul-dlss/ruby-rails@3.
|
3
|
+
ruby-rails: sul-dlss/ruby-rails@3.1.2
|
4
4
|
workflows:
|
5
5
|
build:
|
6
6
|
jobs:
|
@@ -12,6 +12,9 @@ workflows:
|
|
12
12
|
- run:
|
13
13
|
name: Install exiftool
|
14
14
|
command: curl -L http://cpanmin.us | perl - --sudo Image::ExifTool
|
15
|
+
- run:
|
16
|
+
name: Install libvips
|
17
|
+
command: sudo apt-get update && sudo apt-get install -y libvips
|
15
18
|
- setup_remote_docker
|
16
19
|
- run:
|
17
20
|
name: Install Kakadu
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -22,14 +22,16 @@ Naming/FileName:
|
|
22
22
|
Exclude:
|
23
23
|
- lib/assembly-image.rb
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
Naming/PredicateName:
|
26
|
+
ForbiddenPrefixes:
|
27
|
+
- is_
|
28
|
+
|
29
|
+
RSpec/MultipleMemoizedHelpers:
|
30
|
+
Enabled: false
|
27
31
|
|
28
32
|
Style/WordArray:
|
29
33
|
Enabled: false
|
30
34
|
|
31
|
-
Gemspec/DateAssignment: # new in 1.10
|
32
|
-
Enabled: true
|
33
35
|
Gemspec/RequireMFA: # new in 1.23
|
34
36
|
Enabled: true
|
35
37
|
Layout/LineEndStringConcatenationIndentation: # new in 1.18
|
@@ -144,7 +146,7 @@ RSpec/SubjectDeclaration: # new in 2.5
|
|
144
146
|
RSpec/FactoryBot/SyntaxMethods: # new in 2.7
|
145
147
|
Enabled: true
|
146
148
|
RSpec/Rails/AvoidSetupHook: # new in 2.4
|
147
|
-
Enabled:
|
149
|
+
Enabled: false
|
148
150
|
|
149
151
|
Lint/RefinementImportMethods: # new in 1.27
|
150
152
|
Enabled: true
|
@@ -166,3 +168,19 @@ RSpec/ChangeByZero: # new in 2.11.0
|
|
166
168
|
Enabled: true
|
167
169
|
RSpec/VerifiedDoubleReference: # new in 2.10.0
|
168
170
|
Enabled: true
|
171
|
+
|
172
|
+
Gemspec/DeprecatedAttributeAssignment: # new in 1.30
|
173
|
+
Enabled: true
|
174
|
+
Layout/LineContinuationLeadingSpace: # new in 1.31
|
175
|
+
Enabled: true
|
176
|
+
Layout/LineContinuationSpacing: # new in 1.31
|
177
|
+
Enabled: true
|
178
|
+
Lint/ConstantOverwrittenInRescue: # new in 1.31
|
179
|
+
Enabled: true
|
180
|
+
Lint/NonAtomicFileOperation: # new in 1.31
|
181
|
+
Enabled: true
|
182
|
+
|
183
|
+
RSpec/Capybara/SpecificMatcher: # new in 2.12
|
184
|
+
Enabled: true
|
185
|
+
RSpec/Rails/HaveHttpStatus: # new in 2.12
|
186
|
+
Enabled: false
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2022-
|
3
|
+
# on 2022-07-19 17:18:47 UTC using RuboCop version 1.31.2.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
@@ -13,56 +13,16 @@ Gemspec/RequiredRubyVersion:
|
|
13
13
|
Exclude:
|
14
14
|
- 'assembly-image.gemspec'
|
15
15
|
|
16
|
-
# Offense count: 3
|
17
|
-
# Cop supports --auto-correct.
|
18
|
-
Lint/RedundantCopDisableDirective:
|
19
|
-
Exclude:
|
20
|
-
- 'lib/assembly-image/image.rb'
|
21
|
-
- 'lib/assembly-image/images.rb'
|
22
|
-
|
23
16
|
# Offense count: 2
|
24
|
-
# Configuration parameters:
|
25
|
-
|
26
|
-
|
27
|
-
Exclude:
|
28
|
-
- 'spec/image_spec.rb'
|
29
|
-
- 'spec/images_spec.rb'
|
30
|
-
|
31
|
-
# Offense count: 21
|
32
|
-
RSpec/MultipleExpectations:
|
33
|
-
Max: 10
|
34
|
-
|
35
|
-
# Offense count: 5
|
36
|
-
RSpec/UnspecifiedException:
|
37
|
-
Exclude:
|
38
|
-
- 'spec/image_spec.rb'
|
39
|
-
- 'spec/images_spec.rb'
|
40
|
-
|
41
|
-
# Offense count: 3
|
42
|
-
Style/CombinableLoops:
|
43
|
-
Exclude:
|
44
|
-
- 'spec/images_spec.rb'
|
45
|
-
|
46
|
-
# Offense count: 1
|
47
|
-
# Cop supports --auto-correct.
|
48
|
-
Style/GlobalStdStream:
|
49
|
-
Exclude:
|
50
|
-
- 'lib/assembly-image/images.rb'
|
17
|
+
# Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
|
18
|
+
Metrics/AbcSize:
|
19
|
+
Max: 20
|
51
20
|
|
52
|
-
# Offense count:
|
53
|
-
# Configuration parameters:
|
54
|
-
|
55
|
-
|
56
|
-
Exclude:
|
57
|
-
- 'lib/assembly-image/image.rb'
|
21
|
+
# Offense count: 11
|
22
|
+
# Configuration parameters: CountAsOne.
|
23
|
+
RSpec/ExampleLength:
|
24
|
+
Max: 13
|
58
25
|
|
59
|
-
# Offense count:
|
60
|
-
|
61
|
-
|
62
|
-
Style/StringConcatenation:
|
63
|
-
Exclude:
|
64
|
-
- 'bin/console'
|
65
|
-
- 'config/boot.rb'
|
66
|
-
- 'lib/assembly-image.rb'
|
67
|
-
- 'lib/assembly-image/images.rb'
|
68
|
-
- 'spec/spec_helper.rb'
|
26
|
+
# Offense count: 15
|
27
|
+
RSpec/MultipleExpectations:
|
28
|
+
Max: 11
|
data/.rvmrc.example
CHANGED
@@ -1 +1 @@
|
|
1
|
-
rvm use 1.
|
1
|
+
rvm use 3.1.0@assembly-image --create
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
assembly-image (2.1.0)
|
5
|
+
activesupport (> 6.1)
|
6
|
+
assembly-objectfile (>= 1.6.4)
|
7
|
+
ruby-vips (>= 2.0)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activesupport (7.0.3.1)
|
13
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
14
|
+
i18n (>= 1.6, < 2)
|
15
|
+
minitest (>= 5.1)
|
16
|
+
tzinfo (~> 2.0)
|
17
|
+
assembly-objectfile (2.1.0)
|
18
|
+
activesupport (>= 5.2.0)
|
19
|
+
mime-types (> 3)
|
20
|
+
mini_exiftool
|
21
|
+
ast (2.4.2)
|
22
|
+
byebug (11.1.3)
|
23
|
+
coderay (1.1.3)
|
24
|
+
concurrent-ruby (1.1.10)
|
25
|
+
diff-lcs (1.5.0)
|
26
|
+
docile (1.4.0)
|
27
|
+
ffi (1.15.5)
|
28
|
+
i18n (1.12.0)
|
29
|
+
concurrent-ruby (~> 1.0)
|
30
|
+
json (2.6.2)
|
31
|
+
method_source (1.0.0)
|
32
|
+
mime-types (3.4.1)
|
33
|
+
mime-types-data (~> 3.2015)
|
34
|
+
mime-types-data (3.2022.0105)
|
35
|
+
mini_exiftool (2.10.2)
|
36
|
+
minitest (5.16.2)
|
37
|
+
parallel (1.22.1)
|
38
|
+
parser (3.1.2.0)
|
39
|
+
ast (~> 2.4.1)
|
40
|
+
pry (0.13.1)
|
41
|
+
coderay (~> 1.1)
|
42
|
+
method_source (~> 1.0)
|
43
|
+
pry-byebug (3.9.0)
|
44
|
+
byebug (~> 11.0)
|
45
|
+
pry (~> 0.13.0)
|
46
|
+
rainbow (3.1.1)
|
47
|
+
rake (13.0.6)
|
48
|
+
regexp_parser (2.5.0)
|
49
|
+
rexml (3.2.5)
|
50
|
+
rspec (3.11.0)
|
51
|
+
rspec-core (~> 3.11.0)
|
52
|
+
rspec-expectations (~> 3.11.0)
|
53
|
+
rspec-mocks (~> 3.11.0)
|
54
|
+
rspec-core (3.11.0)
|
55
|
+
rspec-support (~> 3.11.0)
|
56
|
+
rspec-expectations (3.11.0)
|
57
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
58
|
+
rspec-support (~> 3.11.0)
|
59
|
+
rspec-mocks (3.11.1)
|
60
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
61
|
+
rspec-support (~> 3.11.0)
|
62
|
+
rspec-support (3.11.0)
|
63
|
+
rubocop (1.31.2)
|
64
|
+
json (~> 2.3)
|
65
|
+
parallel (~> 1.10)
|
66
|
+
parser (>= 3.1.0.0)
|
67
|
+
rainbow (>= 2.2.2, < 4.0)
|
68
|
+
regexp_parser (>= 1.8, < 3.0)
|
69
|
+
rexml (>= 3.2.5, < 4.0)
|
70
|
+
rubocop-ast (>= 1.18.0, < 2.0)
|
71
|
+
ruby-progressbar (~> 1.7)
|
72
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
73
|
+
rubocop-ast (1.19.1)
|
74
|
+
parser (>= 3.1.1.0)
|
75
|
+
rubocop-rspec (2.12.1)
|
76
|
+
rubocop (~> 1.31)
|
77
|
+
ruby-progressbar (1.11.0)
|
78
|
+
ruby-vips (2.1.4)
|
79
|
+
ffi (~> 1.12)
|
80
|
+
simplecov (0.21.2)
|
81
|
+
docile (~> 1.1)
|
82
|
+
simplecov-html (~> 0.11)
|
83
|
+
simplecov_json_formatter (~> 0.1)
|
84
|
+
simplecov-html (0.12.3)
|
85
|
+
simplecov_json_formatter (0.1.4)
|
86
|
+
tzinfo (2.0.5)
|
87
|
+
concurrent-ruby (~> 1.0)
|
88
|
+
unicode-display_width (2.2.0)
|
89
|
+
|
90
|
+
PLATFORMS
|
91
|
+
x86_64-darwin-19
|
92
|
+
x86_64-darwin-21
|
93
|
+
x86_64-linux
|
94
|
+
|
95
|
+
DEPENDENCIES
|
96
|
+
assembly-image!
|
97
|
+
pry-byebug
|
98
|
+
rake
|
99
|
+
rspec (~> 3.0)
|
100
|
+
rubocop
|
101
|
+
rubocop-rspec
|
102
|
+
simplecov
|
103
|
+
|
104
|
+
BUNDLED WITH
|
105
|
+
2.3.17
|
data/README.md
CHANGED
@@ -6,22 +6,16 @@
|
|
6
6
|
# Assembly Image Gem
|
7
7
|
|
8
8
|
## Overview
|
9
|
-
This gem contains classes used by the Stanford University Digital Library to
|
10
|
-
|
9
|
+
This gem contains classes used by the Stanford University Digital Library to create JP2 image derivatives.
|
10
|
+
|
11
|
+
Requires image processing software - see [prerequisites section](#prerequisites) below.
|
11
12
|
|
12
13
|
## Notes
|
13
14
|
|
14
15
|
1. The gem assumes that the user context in which it is executed has write access to the 'tmp' folder.
|
15
|
-
This is
|
16
|
-
|
17
|
-
is
|
18
|
-
If you know there are color profiles which are commonly used, it is better to
|
19
|
-
capture them in the gem itself in the profile folder so they can be re-used
|
20
|
-
and do not need to be extracted.
|
21
|
-
1. If any errors occur during JP2 generation for any reason, a runtime exception will be thrown with a description of the error.
|
22
|
-
2. If an image is passed in with a color profile that cannot be determined by examining the exif header data, an exception will be thrown.
|
23
|
-
|
24
|
-
This can commonly occur in basic test TIFs that are black/white and have no profile, so beware during testing.
|
16
|
+
This is to create the temporary tiffs used; we need temporary tiffs to reliably compress the image using KDUcompress, which doesn’t support arbitrary image types
|
17
|
+
2. If any errors occur during JP2 generation for any reason, a runtime exception will be thrown with a description of the error.
|
18
|
+
3. If an image is passed in with a color profile that cannot be determined, an exception will be thrown. This can commonly occur in basic test TIFs that are black/white and have no profile, so beware during testing.
|
25
19
|
|
26
20
|
## Usage
|
27
21
|
|
@@ -29,76 +23,39 @@ To use the JP2 creation method, you first instantiate the image object with an i
|
|
29
23
|
|
30
24
|
```ruby
|
31
25
|
require 'assembly-image'
|
32
|
-
|
33
|
-
|
34
|
-
output = input.create_jp2(:output=>'/full/path/to/output.jp2') # generate a new JP2 in the specified location
|
35
|
-
puts output.exif # show exif header information for the JP2
|
26
|
+
input_image = Assembly::Image.new('/full/path/to/file.tif')
|
27
|
+
output = input_image.create_jp2(output: '/full/path/to/output.jp2') # generate a new JP2 in the specified location
|
36
28
|
```
|
37
29
|
|
38
30
|
## Running tests
|
39
31
|
|
40
32
|
```bash
|
41
|
-
bundle exec
|
42
|
-
```
|
43
|
-
|
44
|
-
## Generate documentation
|
45
|
-
To generate documentation into the "doc" folder:
|
46
|
-
|
47
|
-
```bash
|
48
|
-
yard
|
49
|
-
```
|
50
|
-
|
51
|
-
To keep a local server running with up to date code documentation that you can view in your browser:
|
52
|
-
|
53
|
-
```bash
|
54
|
-
yard server --reload
|
33
|
+
bundle exec rspec
|
55
34
|
```
|
56
35
|
|
57
36
|
## Prerequisites
|
58
37
|
|
59
38
|
1. Kakadu Proprietary Software Binaries - for JP2 generation
|
60
|
-
1.
|
61
|
-
1. Exiftool
|
39
|
+
1. Libvips
|
40
|
+
1. Exiftool - upstream dependency of assembly-objectfile (used by specs to check mimetype of produced jp2, and because there is no libvips package available for circleci that speaks jp2)
|
62
41
|
|
63
42
|
### Kakadu
|
64
43
|
|
65
44
|
Download and install demonstration binaries from Kakadu:
|
66
45
|
http://kakadusoftware.com/downloads/
|
67
46
|
|
68
|
-
|
69
|
-
|
70
|
-
### Imagemagick
|
71
|
-
|
72
|
-
#### RHEL 6
|
73
|
-
|
74
|
-
The version of ImageMagick included with RHEL 6 has all of the dependency libraries included:
|
75
|
-
|
76
|
-
```bash
|
77
|
-
yum install ImageMagick
|
78
|
-
```
|
79
|
-
#### RHEL 5
|
80
|
-
|
81
|
-
The version of ImageMagick included with RHEL 5 is too old and does not have all the proper binaries included/built:
|
82
|
-
|
83
|
-
```bash
|
84
|
-
yum install lcms lcms-devel libjpeg libjpeg-devel libpng libpng-devel
|
85
|
-
```
|
86
|
-
Required libraries from source:
|
87
|
-
* libtiff (version 3.9.4 or higher)
|
88
|
-
|
89
|
-
Build Imagemagick from source:
|
90
|
-
http://www.imagemagick.org/download/ImageMagick.tar.gz
|
47
|
+
### Libvips
|
48
|
+
Note: libvips may require a significant amount of space for temporary files. The location for this can be controlled by the TMPDIR environment variable.
|
91
49
|
|
92
50
|
#### Mac
|
93
51
|
|
94
52
|
```bash
|
95
|
-
brew install
|
96
|
-
brew install imagemagick --use-tiff --use-jpeg2000
|
53
|
+
brew install libvips
|
97
54
|
```
|
98
55
|
|
99
56
|
### Exiftool
|
100
57
|
|
101
|
-
####
|
58
|
+
#### Linux
|
102
59
|
Download latest version from: http://www.sno.phy.queensu.ca/~phil/exiftool
|
103
60
|
|
104
61
|
```bash
|
data/assembly-image.gemspec
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
4
|
-
require 'assembly-image/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |s|
|
7
6
|
s.name = 'assembly-image'
|
8
|
-
s.version =
|
7
|
+
s.version = '2.1.0'
|
9
8
|
s.authors = ['Peter Mangiafico', 'Renzo Sanchez-Silva', 'Monty Hindman', 'Tony Calavano']
|
10
9
|
s.email = ['pmangiafico@stanford.edu']
|
11
10
|
s.homepage = ''
|
@@ -14,18 +13,18 @@ Gem::Specification.new do |s|
|
|
14
13
|
s.metadata['rubygems_mfa_required'] = 'true'
|
15
14
|
|
16
15
|
s.files = `git ls-files`.split("\n")
|
17
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
16
|
s.bindir = 'exe'
|
19
17
|
s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
18
|
s.require_paths = ['lib']
|
21
19
|
|
20
|
+
s.add_dependency 'activesupport', '> 6.1'
|
22
21
|
s.add_dependency 'assembly-objectfile', '>= 1.6.4'
|
23
|
-
s.add_dependency '
|
22
|
+
s.add_dependency 'ruby-vips', '>= 2.0'
|
24
23
|
|
24
|
+
s.add_development_dependency 'pry-byebug'
|
25
25
|
s.add_development_dependency 'rake'
|
26
26
|
s.add_development_dependency 'rspec', '~> 3.0'
|
27
27
|
s.add_development_dependency 'rubocop'
|
28
28
|
s.add_development_dependency 'rubocop-rspec'
|
29
29
|
s.add_development_dependency 'simplecov'
|
30
|
-
s.add_development_dependency 'yard'
|
31
30
|
end
|
data/bin/console
CHANGED
data/config/boot.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
|
5
|
-
project_root = File.expand_path(File.dirname(__FILE__)
|
5
|
+
project_root = File.expand_path("#{File.dirname(__FILE__)}/..")
|
6
6
|
|
7
7
|
# Load config for current environment.
|
8
|
-
$LOAD_PATH.unshift(project_root
|
8
|
+
$LOAD_PATH.unshift("#{project_root}/lib")
|
9
9
|
|
10
10
|
require 'assembly-image'
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'assembly-objectfile'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'English' # see https://github.com/rubocop-hq/rubocop/issues/1747 (not #MAGA related)
|
6
|
+
require 'active_support/core_ext/module/delegation'
|
7
|
+
|
8
|
+
module Assembly
|
9
|
+
class Image < Assembly::ObjectFile
|
10
|
+
# Creates jp2 derivatives
|
11
|
+
class Jp2Creator
|
12
|
+
# Create a JP2 file for the current image.
|
13
|
+
# Important note: this will not work for multipage TIFFs.
|
14
|
+
#
|
15
|
+
# @return [Assembly::Image] object containing the generated JP2 file
|
16
|
+
#
|
17
|
+
# @param [Assembly::Image] the image file
|
18
|
+
# @param [String] output path to the output JP2 file (default: mirrors the source file name and path, but with a .jp2 extension)
|
19
|
+
# @param [Boolean] overwrite if set to false, an existing JP2 file with the same name won't be overwritten (default: false)
|
20
|
+
# @param [Dir] tmp_folder the temporary folder to use when creating the jp2 (default: '/tmp'); also used by imagemagick
|
21
|
+
#
|
22
|
+
# Example:
|
23
|
+
# source_img = Assembly::Image.new('/input/path_to_file.tif')
|
24
|
+
# derivative_img = source_img.create_jp2(overwrite: true)
|
25
|
+
# puts derivative_img.mimetype # 'image/jp2'
|
26
|
+
# puts derivative_image.path # '/input/path_to_file.jp2'
|
27
|
+
def self.create(image, **args)
|
28
|
+
new(image, **args).create
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(image, overwrite: false, output: image.jp2_filename, tmp_folder: Dir.tmpdir)
|
32
|
+
@image = image
|
33
|
+
@output_path = output
|
34
|
+
@tmp_folder = tmp_folder
|
35
|
+
@overwrite = overwrite
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_reader :image, :output_path, :tmp_folder, :tmp_tiff_path
|
39
|
+
|
40
|
+
delegate :vips_image, to: :image
|
41
|
+
|
42
|
+
# @return [Assembly::Image] object containing the generated JP2 file
|
43
|
+
def create
|
44
|
+
create_jp2_checks
|
45
|
+
|
46
|
+
# KDUcompress doesn’t support arbitrary image types, so we make a temporary tiff
|
47
|
+
@tmp_tiff_path = make_tmp_tiff
|
48
|
+
|
49
|
+
jp2_command = jp2_create_command(source_path: tmp_tiff_path, output: output_path)
|
50
|
+
result = `#{jp2_command}`
|
51
|
+
unless $CHILD_STATUS.success?
|
52
|
+
# Clean up any partial result
|
53
|
+
FileUtils.rm_rf(output_path)
|
54
|
+
raise "JP2 creation command failed: #{jp2_command} with result #{result}"
|
55
|
+
end
|
56
|
+
|
57
|
+
File.delete(tmp_tiff_path) unless tmp_tiff_path.nil?
|
58
|
+
|
59
|
+
# create output response object, which is an Assembly::Image type object
|
60
|
+
Image.new(output_path)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def overwrite?
|
66
|
+
@overwrite
|
67
|
+
end
|
68
|
+
|
69
|
+
def jp2_create_command(source_path:, output:)
|
70
|
+
options = []
|
71
|
+
# CMYK becomes sRGB in make_tmp_tiff, so jp2_space option will be set for sRGB and CMYK
|
72
|
+
# TODO: we're not sure at this time what happens for grayscale (or what Tony C. wants for grayscale)
|
73
|
+
# see https://github.com/sul-dlss/assembly-image/issues/98
|
74
|
+
options << '-jp2_space sRGB' if image.srgb?
|
75
|
+
options += KDU_COMPRESS_DEFAULT_OPTIONS
|
76
|
+
options << "Clayers=#{layers}"
|
77
|
+
"kdu_compress #{options.join(' ')} -i '#{source_path}' -o '#{output}' 2>&1"
|
78
|
+
end
|
79
|
+
|
80
|
+
# Get the number of JP2 layers to generate
|
81
|
+
def layers
|
82
|
+
pixdem = [image.width, image.height].max
|
83
|
+
((Math.log(pixdem) / Math.log(2)) - (Math.log(96) / Math.log(2))).ceil + 1
|
84
|
+
end
|
85
|
+
|
86
|
+
KDU_COMPRESS_DEFAULT_OPTIONS = [
|
87
|
+
'-num_threads 2', # forces Kakadu to only use 2 threads
|
88
|
+
'-quiet', # suppress informative messages.
|
89
|
+
'Creversible=no', # Disable reversible compression
|
90
|
+
'Corder=RPCL', # R=resolution P=position C=component L=layer
|
91
|
+
'Cblk=\\{64,64\\}', # code-block dimensions; 64x64 happens to also be the default
|
92
|
+
'Cprecincts=\\{256,256\\},\\{256,256\\},\\{128,128\\}', # Precinct dimensions; 256x256 for the 2 highest resolution levels, defaults to 128x128 for the rest
|
93
|
+
'-rate -', # Ratio of compressed bits to the image size
|
94
|
+
'Clevels=5' # Number of wavelet decomposition levels, or stages
|
95
|
+
].freeze
|
96
|
+
|
97
|
+
def create_jp2_checks
|
98
|
+
image.send(:check_for_file)
|
99
|
+
raise 'input file is not a valid image, or is the wrong mimetype' unless image.jp2able?
|
100
|
+
|
101
|
+
raise SecurityError, "output #{output_path} exists, cannot overwrite" if !overwrite? && File.exist?(output_path)
|
102
|
+
raise SecurityError, 'cannot recreate jp2 over itself' if overwrite? && image.mimetype == 'image/jp2' && output_path == image.path
|
103
|
+
end
|
104
|
+
|
105
|
+
# We do this because we need to reliably compress the tiff and KDUcompress doesn’t support arbitrary image types
|
106
|
+
# rubocop:disable Metrics/MethodLength
|
107
|
+
def make_tmp_tiff
|
108
|
+
raise "tmp_folder #{tmp_folder} does not exist" unless File.exist?(tmp_folder)
|
109
|
+
|
110
|
+
# make temp tiff filename
|
111
|
+
tmp_tiff_file = Tempfile.new(['assembly-image', '.tif'], tmp_folder)
|
112
|
+
result_path = tmp_tiff_file.path
|
113
|
+
tmp_tiff_image = if vips_image.interpretation.eql?(:cmyk)
|
114
|
+
vips_image.icc_transform(SRGB_ICC, input_profile: CMYK_ICC)
|
115
|
+
elsif image.has_profile?
|
116
|
+
vips_image.icc_transform(SRGB_ICC, embedded: true)
|
117
|
+
else
|
118
|
+
vips_image
|
119
|
+
end
|
120
|
+
|
121
|
+
tmp_tiff_image.tiffsave(result_path, bigtiff: true) # Use bigtiff so we can support images > 4GB
|
122
|
+
result_path
|
123
|
+
end
|
124
|
+
# rubocop:enable Metrics/MethodLength
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'vips'
|
4
|
+
require 'assembly-objectfile'
|
5
|
+
require_relative 'image/jp2_creator'
|
6
|
+
|
7
|
+
module Assembly
|
8
|
+
# The Image class contains methods to operate on an image.
|
9
|
+
class Image < Assembly::ObjectFile
|
10
|
+
# @return [integer] image height in pixels
|
11
|
+
def height
|
12
|
+
vips_image.height
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [integer] image width in pixels
|
16
|
+
def width
|
17
|
+
vips_image.width
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [string] full default jp2 path and filename that will be created from the given image
|
21
|
+
# Example: given original file of '/dir/path_to_file.tif', gives '/dir/path_to_file.jp2'
|
22
|
+
def jp2_filename
|
23
|
+
# path is a property on Assembly::ObjectFile
|
24
|
+
File.extname(path).empty? ? "#{path}.jp2" : path.gsub(File.extname(path), '.jp2')
|
25
|
+
end
|
26
|
+
|
27
|
+
# Create a JP2 file for the current image.
|
28
|
+
# Important note: this will not work for multipage TIFFs.
|
29
|
+
#
|
30
|
+
# @param [String] output path to the output JP2 file (default: mirrors the source file name and path, but with a .jp2 extension)
|
31
|
+
# @param [Boolean] overwrite if set to false, an existing JP2 file with the same name won't be overwritten (default: false)
|
32
|
+
# @param [Dir] tmp_folder the temporary folder to use when creating the jp2 (default: '/tmp'); also used by imagemagick
|
33
|
+
# @return [Assembly::Image] object containing the generated JP2 file
|
34
|
+
#
|
35
|
+
# Example:
|
36
|
+
# source_img = Assembly::Image.new('/dir/path_to_file.tif')
|
37
|
+
# jp2_img = source_img.create_jp2(overwrite: true)
|
38
|
+
# jp2_img.mimetype # 'image/jp2'
|
39
|
+
# jp2_img.path # '/dir/path_to_file.jp2'
|
40
|
+
def create_jp2(**params)
|
41
|
+
Jp2Creator.create(self, **params)
|
42
|
+
end
|
43
|
+
|
44
|
+
def vips_image
|
45
|
+
# autorot will only affect images that need rotation: https://www.libvips.org/API/current/libvips-conversion.html#vips-autorot
|
46
|
+
@vips_image ||= Vips::Image.new_from_file(path).autorot
|
47
|
+
end
|
48
|
+
|
49
|
+
def srgb?
|
50
|
+
vips_image.interpretation == :srgb
|
51
|
+
end
|
52
|
+
|
53
|
+
# Does the image include an ICC profile?
|
54
|
+
def has_profile?
|
55
|
+
vips_image.get_fields.include?('icc-profile-data')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/assembly-image.rb
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
|
3
3
|
module Assembly
|
4
4
|
# the path to the gem, used to access profiles stored with the gem
|
5
|
-
PATH_TO_IMAGE_GEM = File.expand_path(File.dirname(__FILE__)
|
5
|
+
PATH_TO_IMAGE_GEM = File.expand_path("#{File.dirname(__FILE__)}/..")
|
6
|
+
PATH_TO_PROFILES = File.join(Assembly::PATH_TO_IMAGE_GEM, 'profiles')
|
7
|
+
SRGB_ICC = File.join(PATH_TO_PROFILES, 'sRGBIEC6196621.icc')
|
8
|
+
CMYK_ICC = File.join(PATH_TO_PROFILES, 'cmyk.icc')
|
6
9
|
end
|
7
10
|
|
8
|
-
require 'assembly
|
9
|
-
require 'assembly-image/images'
|
11
|
+
require 'assembly/image'
|
data/profiles/cmyk.icc
ADDED
Binary file
|