assembly-image 1.7.5 → 1.7.8
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 +4 -4
- data/.circleci/config.yml +22 -0
- data/.github/pull_request_template.md +10 -0
- data/.gitignore +4 -1
- data/.rubocop.yml +150 -3
- data/.rubocop_todo.yml +68 -0
- data/README.md +5 -2
- data/assembly-image.gemspec +3 -2
- data/lib/assembly-image/image.rb +16 -156
- data/lib/assembly-image/jp2_creator.rb +182 -0
- data/lib/assembly-image/version.rb +2 -2
- data/spec/assembly/image/jp2_creator_spec.rb +58 -0
- data/spec/image_spec.rb +249 -227
- data/spec/images_spec.rb +20 -22
- data/spec/spec_helper.rb +95 -2
- metadata +42 -8
- data/.travis.yml +0 -28
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: efc5ecaed58333775573f14e2f2895ecc8279ff9b80fc13ca69e927abfd216ef
|
|
4
|
+
data.tar.gz: 3c9c28f4b3c1a1d170fafbccca2b4b0d518047d8cc6c634716c79efb859876d0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f48ce528fd60e5f9ceac51472811ed1bccaf34cd3d82348520dd75bc94af8c18b760e240fcc5355f452a4edee44fc5f664bdbae9bcd6bfd3ea2c46c1bc1fc6a3
|
|
7
|
+
data.tar.gz: e2c7963073b4c2975f6e59ee00d8011b04d7bb95f013291d5a48f992a7a801b913fbf8803952d1b133a5d1ac55eba280a9ecd7a38aac1881c53023614fd5582d
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
version: 2.1
|
|
2
|
+
orbs:
|
|
3
|
+
ruby-rails: sul-dlss/ruby-rails@3.0.1
|
|
4
|
+
workflows:
|
|
5
|
+
build:
|
|
6
|
+
jobs:
|
|
7
|
+
- ruby-rails/lint-gem:
|
|
8
|
+
name: lint
|
|
9
|
+
- ruby-rails/test-gem:
|
|
10
|
+
name: test
|
|
11
|
+
before-test:
|
|
12
|
+
- run:
|
|
13
|
+
name: Install exiftool
|
|
14
|
+
command: curl -L http://cpanmin.us | perl - --sudo Image::ExifTool
|
|
15
|
+
- setup_remote_docker
|
|
16
|
+
- run:
|
|
17
|
+
name: Install Kakadu
|
|
18
|
+
command: |
|
|
19
|
+
docker create --name kakadu josejuansanchez/kakadu:1.0
|
|
20
|
+
docker cp kakadu:/kakadu kakadu
|
|
21
|
+
sudo cp kakadu/*.so /usr/lib
|
|
22
|
+
sudo cp kakadu/* /usr/bin
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
## Why was this change made? 🤔
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
## How was this change tested? 🤨
|
|
6
|
+
|
|
7
|
+
⚡ ⚠ If this change has cross service impact, ***run [integration tests](https://github.com/sul-dlss/infrastructure-integration-test) that do IMAGE ACCESSIONING*** (e.g. create_preassembly_image_spec) and/or test in [stage|qa] environment, in addition to specs. ⚡
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
|
2
|
+
|
|
3
|
+
require: rubocop-rspec
|
|
4
|
+
|
|
5
|
+
AllCops:
|
|
6
|
+
TargetRubyVersion: 3.0
|
|
7
|
+
SuggestExtensions: false
|
|
8
|
+
|
|
1
9
|
# rspec expect{...} is conventional
|
|
2
10
|
Layout/SpaceBeforeBlockBraces:
|
|
3
11
|
Exclude:
|
|
@@ -7,15 +15,154 @@ Layout/EmptyLineBetweenDefs:
|
|
|
7
15
|
AllowAdjacentOneLineDefs: true
|
|
8
16
|
|
|
9
17
|
# Configuration parameters: AllowURI, URISchemes.
|
|
10
|
-
|
|
18
|
+
Layout/LineLength:
|
|
11
19
|
Max: 200
|
|
12
20
|
|
|
13
21
|
Naming/FileName:
|
|
14
22
|
Exclude:
|
|
15
23
|
- lib/assembly-image.rb
|
|
16
24
|
|
|
25
|
+
RSpec/ExampleLength:
|
|
26
|
+
Max: 12
|
|
27
|
+
|
|
17
28
|
Style/WordArray:
|
|
18
29
|
Enabled: false
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
|
|
31
|
+
Gemspec/DateAssignment: # new in 1.10
|
|
32
|
+
Enabled: true
|
|
33
|
+
Gemspec/RequireMFA: # new in 1.23
|
|
34
|
+
Enabled: true
|
|
35
|
+
Layout/LineEndStringConcatenationIndentation: # new in 1.18
|
|
36
|
+
Enabled: true
|
|
37
|
+
Layout/SpaceBeforeBrackets: # new in 1.7
|
|
38
|
+
Enabled: true
|
|
39
|
+
Lint/AmbiguousAssignment: # new in 1.7
|
|
40
|
+
Enabled: true
|
|
41
|
+
Lint/AmbiguousOperatorPrecedence: # new in 1.21
|
|
42
|
+
Enabled: true
|
|
43
|
+
Lint/AmbiguousRange: # new in 1.19
|
|
44
|
+
Enabled: true
|
|
45
|
+
Lint/DeprecatedConstants: # new in 1.8
|
|
46
|
+
Enabled: true
|
|
47
|
+
Lint/DuplicateBranch: # new in 1.3
|
|
48
|
+
Enabled: true
|
|
49
|
+
Lint/DuplicateRegexpCharacterClassElement: # new in 1.1
|
|
50
|
+
Enabled: true
|
|
51
|
+
Lint/EmptyBlock: # new in 1.1
|
|
52
|
+
Enabled: true
|
|
53
|
+
Lint/EmptyClass: # new in 1.3
|
|
54
|
+
Enabled: true
|
|
55
|
+
Lint/EmptyInPattern: # new in 1.16
|
|
56
|
+
Enabled: true
|
|
57
|
+
Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
|
|
58
|
+
Enabled: true
|
|
59
|
+
Lint/LambdaWithoutLiteralBlock: # new in 1.8
|
|
60
|
+
Enabled: true
|
|
61
|
+
Lint/NoReturnInBeginEndBlocks: # new in 1.2
|
|
62
|
+
Enabled: true
|
|
63
|
+
Lint/NumberedParameterAssignment: # new in 1.9
|
|
64
|
+
Enabled: true
|
|
65
|
+
Lint/OrAssignmentToConstant: # new in 1.9
|
|
66
|
+
Enabled: true
|
|
67
|
+
Lint/RedundantDirGlobSort: # new in 1.8
|
|
68
|
+
Enabled: true
|
|
69
|
+
Lint/RequireRelativeSelfPath: # new in 1.22
|
|
70
|
+
Enabled: true
|
|
71
|
+
Lint/SymbolConversion: # new in 1.9
|
|
72
|
+
Enabled: true
|
|
73
|
+
Lint/ToEnumArguments: # new in 1.1
|
|
74
|
+
Enabled: true
|
|
75
|
+
Lint/TripleQuotes: # new in 1.9
|
|
76
|
+
Enabled: true
|
|
77
|
+
Lint/UnexpectedBlockArity: # new in 1.5
|
|
78
|
+
Enabled: true
|
|
79
|
+
Lint/UnmodifiedReduceAccumulator: # new in 1.1
|
|
80
|
+
Enabled: true
|
|
81
|
+
Lint/UselessRuby2Keywords: # new in 1.23
|
|
82
|
+
Enabled: true
|
|
83
|
+
Naming/BlockForwarding: # new in 1.24
|
|
84
|
+
Enabled: true
|
|
85
|
+
Security/IoMethods: # new in 1.22
|
|
86
|
+
Enabled: true
|
|
87
|
+
Style/ArgumentsForwarding: # new in 1.1
|
|
88
|
+
Enabled: true
|
|
89
|
+
Style/CollectionCompact: # new in 1.2
|
|
90
|
+
Enabled: true
|
|
91
|
+
Style/DocumentDynamicEvalDefinition: # new in 1.1
|
|
92
|
+
Enabled: true
|
|
93
|
+
Style/EndlessMethod: # new in 1.8
|
|
94
|
+
Enabled: true
|
|
95
|
+
Style/FileRead: # new in 1.24
|
|
96
|
+
Enabled: true
|
|
97
|
+
Style/FileWrite: # new in 1.24
|
|
98
|
+
Enabled: true
|
|
99
|
+
Style/HashConversion: # new in 1.10
|
|
100
|
+
Enabled: true
|
|
101
|
+
Style/HashExcept: # new in 1.7
|
|
102
|
+
Enabled: true
|
|
103
|
+
Style/IfWithBooleanLiteralBranches: # new in 1.9
|
|
104
|
+
Enabled: true
|
|
105
|
+
Style/InPatternThen: # new in 1.16
|
|
106
|
+
Enabled: true
|
|
107
|
+
Style/MapToHash: # new in 1.24
|
|
108
|
+
Enabled: true
|
|
109
|
+
Style/MultilineInPatternThen: # new in 1.16
|
|
110
|
+
Enabled: true
|
|
111
|
+
Style/NegatedIfElseCondition: # new in 1.2
|
|
112
|
+
Enabled: true
|
|
113
|
+
Style/NilLambda: # new in 1.3
|
|
114
|
+
Enabled: true
|
|
115
|
+
Style/NumberedParameters: # new in 1.22
|
|
116
|
+
Enabled: true
|
|
117
|
+
Style/NumberedParametersLimit: # new in 1.22
|
|
118
|
+
Enabled: true
|
|
119
|
+
Style/OpenStructUse: # new in 1.23
|
|
120
|
+
Enabled: true
|
|
121
|
+
Style/QuotedSymbols: # new in 1.16
|
|
122
|
+
Enabled: true
|
|
123
|
+
Style/RedundantArgument: # new in 1.4
|
|
124
|
+
Enabled: true
|
|
125
|
+
Style/RedundantSelfAssignmentBranch: # new in 1.19
|
|
126
|
+
Enabled: true
|
|
127
|
+
Style/SelectByRegexp: # new in 1.22
|
|
128
|
+
Enabled: true
|
|
129
|
+
Style/StringChars: # new in 1.12
|
|
130
|
+
Enabled: true
|
|
131
|
+
Style/SwapValues: # new in 1.1
|
|
132
|
+
Enabled: true
|
|
133
|
+
|
|
134
|
+
RSpec/BeEq: # new in 2.9.0
|
|
135
|
+
Enabled: true
|
|
136
|
+
RSpec/BeNil: # new in 2.9.0
|
|
137
|
+
Enabled: true
|
|
138
|
+
RSpec/ExcessiveDocstringSpacing: # new in 2.5
|
|
139
|
+
Enabled: true
|
|
140
|
+
RSpec/IdenticalEqualityAssertion: # new in 2.4
|
|
141
|
+
Enabled: true
|
|
142
|
+
RSpec/SubjectDeclaration: # new in 2.5
|
|
143
|
+
Enabled: true
|
|
144
|
+
RSpec/FactoryBot/SyntaxMethods: # new in 2.7
|
|
145
|
+
Enabled: true
|
|
146
|
+
RSpec/Rails/AvoidSetupHook: # new in 2.4
|
|
147
|
+
Enabled: true
|
|
148
|
+
|
|
149
|
+
Lint/RefinementImportMethods: # new in 1.27
|
|
150
|
+
Enabled: true
|
|
151
|
+
Security/CompoundHash: # new in 1.28
|
|
152
|
+
Enabled: true
|
|
153
|
+
Style/EnvHome: # new in 1.29
|
|
154
|
+
Enabled: true
|
|
155
|
+
Style/FetchEnvVar: # new in 1.28
|
|
156
|
+
Enabled: true
|
|
157
|
+
Style/MapCompactWithConditionalBlock: # new in 1.30
|
|
158
|
+
Enabled: true
|
|
159
|
+
Style/NestedFileDirname: # new in 1.26
|
|
160
|
+
Enabled: true
|
|
161
|
+
Style/ObjectThen: # new in 1.28
|
|
162
|
+
Enabled: true
|
|
163
|
+
Style/RedundantInitialize: # new in 1.27
|
|
164
|
+
Enabled: true
|
|
165
|
+
RSpec/ChangeByZero: # new in 2.11.0
|
|
166
|
+
Enabled: true
|
|
167
|
+
RSpec/VerifiedDoubleReference: # new in 2.10.0
|
|
168
|
+
Enabled: true
|
data/.rubocop_todo.yml
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# This configuration was generated by
|
|
2
|
+
# `rubocop --auto-gen-config`
|
|
3
|
+
# on 2022-02-28 19:49:08 UTC using RuboCop version 1.25.1.
|
|
4
|
+
# The point is for the user to remove these configuration records
|
|
5
|
+
# one by one as the offenses are removed from the code base.
|
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
|
8
|
+
|
|
9
|
+
# Offense count: 1
|
|
10
|
+
# Configuration parameters: Include.
|
|
11
|
+
# Include: **/*.gemspec
|
|
12
|
+
Gemspec/RequiredRubyVersion:
|
|
13
|
+
Exclude:
|
|
14
|
+
- 'assembly-image.gemspec'
|
|
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
|
+
# Offense count: 2
|
|
24
|
+
# Configuration parameters: Include, CustomTransform, IgnoreMethods, SpecSuffixOnly.
|
|
25
|
+
# Include: **/*_spec*rb*, **/spec/**/*
|
|
26
|
+
RSpec/FilePath:
|
|
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'
|
|
51
|
+
|
|
52
|
+
# Offense count: 1
|
|
53
|
+
# Configuration parameters: AllowedMethods.
|
|
54
|
+
# AllowedMethods: respond_to_missing?
|
|
55
|
+
Style/OptionalBooleanParameter:
|
|
56
|
+
Exclude:
|
|
57
|
+
- 'lib/assembly-image/image.rb'
|
|
58
|
+
|
|
59
|
+
# Offense count: 8
|
|
60
|
+
# Cop supports --auto-correct-all.
|
|
61
|
+
# Configuration parameters: Mode.
|
|
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'
|
data/README.md
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
[](https://circleci.com/gh/sul-dlss/assembly-image/tree/main)
|
|
2
|
+
[](https://codeclimate.com/github/sul-dlss/assembly-image/test_coverage)
|
|
3
|
+
[](https://codeclimate.com/github/sul-dlss/assembly-image/maintainability)
|
|
4
|
+
[](https://badge.fury.io/rb/assembly-image)
|
|
2
5
|
|
|
3
6
|
# Assembly Image Gem
|
|
4
7
|
|
|
@@ -51,7 +54,7 @@ perform image operations necessary for accessioning of content.
|
|
|
51
54
|
* 1.6.7 release to github/rubygems
|
|
52
55
|
* 1.6.9 update mini_exiftool
|
|
53
56
|
* 1.7.1 for jp2, only transcode to tiff if not a tiff
|
|
54
|
-
* 1.7.3 for jp2, only transcode to tiff if not an uncompressed tiff
|
|
57
|
+
* 1.7.3 for jp2, only transcode to tiff if not an uncompressed tiff
|
|
55
58
|
|
|
56
59
|
## Notes
|
|
57
60
|
|
data/assembly-image.gemspec
CHANGED
|
@@ -11,8 +11,7 @@ Gem::Specification.new do |s|
|
|
|
11
11
|
s.homepage = ''
|
|
12
12
|
s.summary = 'Ruby immplementation of image services needed to prepare objects to be accessioned in SULAIR digital library'
|
|
13
13
|
s.description = 'Contains classes to create derivative image files and perform other image operations'
|
|
14
|
-
|
|
15
|
-
s.rubyforge_project = 'assembly-image'
|
|
14
|
+
s.metadata['rubygems_mfa_required'] = 'true'
|
|
16
15
|
|
|
17
16
|
s.files = `git ls-files`.split("\n")
|
|
18
17
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
@@ -26,5 +25,7 @@ Gem::Specification.new do |s|
|
|
|
26
25
|
s.add_development_dependency 'rake'
|
|
27
26
|
s.add_development_dependency 'rspec', '~> 3.0'
|
|
28
27
|
s.add_development_dependency 'rubocop'
|
|
28
|
+
s.add_development_dependency 'rubocop-rspec'
|
|
29
|
+
s.add_development_dependency 'simplecov'
|
|
29
30
|
s.add_development_dependency 'yard'
|
|
30
31
|
end
|
data/lib/assembly-image/image.rb
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'assembly-objectfile'
|
|
4
|
-
|
|
5
|
-
require 'English' # see https://github.com/rubocop-hq/rubocop/issues/1747 (not #MAGA related)
|
|
4
|
+
require_relative 'jp2_creator'
|
|
6
5
|
|
|
7
6
|
module Assembly
|
|
8
7
|
# The Image class contains methods to operate on an image.
|
|
9
|
-
# rubocop:disable Metrics/ClassLength
|
|
10
8
|
class Image
|
|
11
9
|
# include common behaviors from assembly-objectfile gem
|
|
12
10
|
include Assembly::ObjectFileable
|
|
13
11
|
|
|
14
|
-
# stores the path to the tmp file generated during the JP2 creation process
|
|
15
|
-
attr_accessor :tmp_path
|
|
16
|
-
|
|
17
12
|
# Examines the input image for validity. Used to determine if image is correct and if JP2 generation is likely to succeed.
|
|
18
13
|
# This method is automatically called before you create a jp2 but it can be called separately earlier as a sanity check.
|
|
19
14
|
#
|
|
@@ -62,9 +57,9 @@ module Assembly
|
|
|
62
57
|
# Example:
|
|
63
58
|
# source_img=Assembly::ObjectFile.new('/input/path_to_file.tif')
|
|
64
59
|
# puts source_img.compressed? # gives true
|
|
65
|
-
def compressed?
|
|
66
|
-
|
|
67
|
-
end
|
|
60
|
+
# def compressed?
|
|
61
|
+
# exif.compression != 'Uncompressed'
|
|
62
|
+
# end
|
|
68
63
|
|
|
69
64
|
# Add an exif color profile descriptions to the image.
|
|
70
65
|
# This is useful if your source TIFFs do not have color profile descriptions in the EXIF data, but you know what it should be.
|
|
@@ -99,7 +94,7 @@ module Assembly
|
|
|
99
94
|
# source_img=Assembly::Image.new('/input/path_to_file.tif')
|
|
100
95
|
# puts source_img.jp2_filename # gives /input/path_to_file.jp2
|
|
101
96
|
def jp2_filename
|
|
102
|
-
File.extname(
|
|
97
|
+
File.extname(path).empty? ? "#{path}.jp2" : path.gsub(File.extname(path), '.jp2')
|
|
103
98
|
end
|
|
104
99
|
|
|
105
100
|
# Returns the full DPG equivalent jp2 path and filename that would match with the given image
|
|
@@ -121,81 +116,16 @@ module Assembly
|
|
|
121
116
|
# * :output => path to the output JP2 file (default: mirrors the source file name and path, but with a .jp2 extension)
|
|
122
117
|
# * :overwrite => if set to false, an existing JP2 file with the same name won't be overwritten (default: false)
|
|
123
118
|
# * :tmp_folder => the temporary folder to use when creating the jp2 (default: '/tmp'); also used by imagemagick
|
|
124
|
-
# * :preserve_tmp_source => if set to true, preserve the temporary file generated during the creation process and store path in 'tmp_path' attribute (default: false)
|
|
125
119
|
#
|
|
126
120
|
# Example:
|
|
127
121
|
# source_img=Assembly::Image.new('/input/path_to_file.tif')
|
|
128
122
|
# derivative_img=source_img.create_jp2(:overwrite=>true)
|
|
129
123
|
# puts derivative_img.mimetype # 'image/jp2'
|
|
130
124
|
# puts derivative_image.path # '/input/path_to_file.jp2'
|
|
131
|
-
# rubocop:disable Metrics/AbcSize
|
|
132
|
-
# rubocop:disable Metrics/MethodLength
|
|
133
125
|
# rubocop:disable Metrics/CyclomaticComplexity:
|
|
134
126
|
def create_jp2(params = {})
|
|
135
|
-
|
|
136
|
-
create_jp2_checks(output: output, overwrite: params[:overwrite])
|
|
137
|
-
|
|
138
|
-
# Using instance variable so that can check in tests.
|
|
139
|
-
source_path = if create_temp_tiff?
|
|
140
|
-
@tmp_path = make_tmp_tiff(tmp_folder: params[:tmp_folder])
|
|
141
|
-
else
|
|
142
|
-
@path
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
jp2_command = jp2_create_command(source_path: source_path, output: output)
|
|
146
|
-
result = `#{jp2_command}`
|
|
147
|
-
raise "JP2 creation command failed: #{jp2_command} with result #{result}" unless $CHILD_STATUS.success?
|
|
148
|
-
|
|
149
|
-
File.delete(source_path) unless @tmp_path.nil? || params[:preserve_tmp_source]
|
|
150
|
-
|
|
151
|
-
# create output response object, which is an Assembly::Image type object
|
|
152
|
-
Assembly::Image.new(output)
|
|
153
|
-
end
|
|
154
|
-
# rubocop:enable Metrics/AbcSize
|
|
155
|
-
# rubocop:enable Metrics/MethodLength
|
|
156
|
-
|
|
157
|
-
private
|
|
158
|
-
|
|
159
|
-
def create_temp_tiff?
|
|
160
|
-
mimetype != 'image/tiff' || compressed?
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
def create_jp2_checks(output:, overwrite:)
|
|
164
|
-
check_for_file
|
|
165
|
-
raise 'input file is not a valid image, or is the wrong mimetype' unless jp2able?
|
|
166
|
-
|
|
167
|
-
raise SecurityError, "output #{output} exists, cannot overwrite" if !overwrite && File.exist?(output)
|
|
168
|
-
raise SecurityError, 'cannot recreate jp2 over itself' if overwrite && mimetype == 'image/jp2' && output == @path
|
|
169
|
-
end
|
|
170
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
171
|
-
|
|
172
|
-
def jp2_create_command(source_path:, output:)
|
|
173
|
-
kdu_bin = 'kdu_compress'
|
|
174
|
-
options = []
|
|
175
|
-
options << '-jp2_space sRGB' if samples_per_pixel == 3
|
|
176
|
-
options += kdu_compress_default_options
|
|
177
|
-
options << "Clayers=#{layers}"
|
|
178
|
-
"#{kdu_bin} #{options.join(' ')} -i '#{source_path}' -o '#{output}' 2>&1"
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
# rubocop:disable Metrics/MethodLength
|
|
182
|
-
def kdu_compress_default_options
|
|
183
|
-
[
|
|
184
|
-
'-num_threads 2', # forces Kakadu to only use 2 threads
|
|
185
|
-
'-precise', # forces the use of 32-bit representations
|
|
186
|
-
'-no_weights', # minimization of the MSE over all reconstructed colour components
|
|
187
|
-
'-quiet', # suppress informative messages.
|
|
188
|
-
'Creversible=no', # Disable reversible compression
|
|
189
|
-
'Cmodes=BYPASS', #
|
|
190
|
-
'Corder=RPCL', # R=resolution P=position C=component L=layer
|
|
191
|
-
'Cblk=\\{64,64\\}', # code-block dimensions; 64x64 happens to also be the default
|
|
192
|
-
'Cprecincts=\\{256,256\\},\\{256,256\\},\\{128,128\\}', # Precinct dimensions; 256x256 for the 2 highest resolution levels, defaults to 128x128 for the rest
|
|
193
|
-
'ORGgen_plt=yes', # Insert packet length information
|
|
194
|
-
'-rate 1.5', # Ratio of compressed bits to the image size
|
|
195
|
-
'Clevels=5' # Number of wavelet decomposition levels, or stages
|
|
196
|
-
]
|
|
127
|
+
Jp2Creator.create(self, params)
|
|
197
128
|
end
|
|
198
|
-
# rubocop:enable Metrics/MethodLength
|
|
199
129
|
|
|
200
130
|
def samples_per_pixel
|
|
201
131
|
if exif['samplesperpixel']
|
|
@@ -204,10 +134,20 @@ module Assembly
|
|
|
204
134
|
case mimetype
|
|
205
135
|
when 'image/tiff'
|
|
206
136
|
1
|
|
137
|
+
when 'image/jpeg'
|
|
138
|
+
3
|
|
207
139
|
end
|
|
208
140
|
end
|
|
209
141
|
end
|
|
210
142
|
|
|
143
|
+
# Get size of image data in bytes
|
|
144
|
+
def image_data_size
|
|
145
|
+
(samples_per_pixel * height * width * bits_per_sample) / 8
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private
|
|
149
|
+
|
|
150
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
211
151
|
def bits_per_sample
|
|
212
152
|
if exif['bitspersample']
|
|
213
153
|
exif['bitspersample'].to_i
|
|
@@ -218,85 +158,5 @@ module Assembly
|
|
|
218
158
|
end
|
|
219
159
|
end
|
|
220
160
|
end
|
|
221
|
-
|
|
222
|
-
# Get the number of JP2 layers to generate
|
|
223
|
-
def layers
|
|
224
|
-
pixdem = [width, height].max
|
|
225
|
-
((Math.log(pixdem) / Math.log(2)) - (Math.log(96) / Math.log(2))).ceil + 1
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
# rubocop:disable Metrics/MethodLength
|
|
229
|
-
# rubocop:disable Metrics/AbcSize
|
|
230
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
231
|
-
def profile_conversion_switch(profile, tmp_folder:)
|
|
232
|
-
path_to_profiles = File.join(Assembly::PATH_TO_IMAGE_GEM, 'profiles')
|
|
233
|
-
# eventually we may allow the user to specify the output_profile...when we do, you can just uncomment this code
|
|
234
|
-
# and update the tests that check for this
|
|
235
|
-
output_profile = 'sRGBIEC6196621' # params[:output_profile] || 'sRGBIEC6196621'
|
|
236
|
-
output_profile_file = File.join(path_to_profiles, "#{output_profile}.icc")
|
|
237
|
-
|
|
238
|
-
raise "output profile #{output_profile} invalid" unless File.exist?(output_profile_file)
|
|
239
|
-
|
|
240
|
-
return '' if profile.nil?
|
|
241
|
-
|
|
242
|
-
# if the input color profile exists, contract paths to the profile and setup the command
|
|
243
|
-
|
|
244
|
-
input_profile = profile.gsub(/[^[:alnum:]]/, '') # remove all non alpha-numeric characters, so we can get to a filename
|
|
245
|
-
|
|
246
|
-
# construct a path to the input profile, which might exist either in the gem itself or in the tmp folder
|
|
247
|
-
input_profile_file_gem = File.join(path_to_profiles, "#{input_profile}.icc")
|
|
248
|
-
input_profile_file_tmp = File.join(tmp_folder, "#{input_profile}.icc")
|
|
249
|
-
input_profile_file = File.exist?(input_profile_file_gem) ? input_profile_file_gem : input_profile_file_tmp
|
|
250
|
-
|
|
251
|
-
# if input profile was extracted and does not matches an existing known profile either in the gem or in the tmp folder,
|
|
252
|
-
# we'll issue an imagicmagick command to extract the profile to the tmp folder
|
|
253
|
-
unless File.exist?(input_profile_file)
|
|
254
|
-
input_profile_extract_command = "MAGICK_TEMPORARY_PATH=#{tmp_folder} convert '#{@path}'[0] #{input_profile_file}" # extract profile from input image
|
|
255
|
-
result = `#{input_profile_extract_command} 2>&1`
|
|
256
|
-
raise "input profile extraction command failed: #{input_profile_extract_command} with result #{result}" unless $CHILD_STATUS.success?
|
|
257
|
-
# if extraction failed or we cannot write the file, throw exception
|
|
258
|
-
raise 'input profile is not a known profile and could not be extracted from input file' unless File.exist?(input_profile_file)
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
"-profile #{input_profile_file} -profile #{output_profile_file}"
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def make_tmp_tiff(tmp_folder: nil)
|
|
265
|
-
tmp_folder ||= Dir.tmpdir
|
|
266
|
-
raise "tmp_folder #{tmp_folder} does not exists" unless File.exist?(tmp_folder)
|
|
267
|
-
|
|
268
|
-
# make temp tiff filename
|
|
269
|
-
tmp_tiff_file = Tempfile.new(['assembly-image', '.tif'], tmp_folder)
|
|
270
|
-
tmp_path = tmp_tiff_file.path
|
|
271
|
-
|
|
272
|
-
options = []
|
|
273
|
-
|
|
274
|
-
# Limit the amount of memory ImageMagick is able to use.
|
|
275
|
-
options << '-limit memory 1GiB -limit map 1GiB'
|
|
276
|
-
|
|
277
|
-
case samples_per_pixel
|
|
278
|
-
when 3
|
|
279
|
-
options << '-type TrueColor'
|
|
280
|
-
when 1
|
|
281
|
-
if bits_per_sample == 1
|
|
282
|
-
options << '-type Bilevel'
|
|
283
|
-
options << '-depth 8' # force the production of a grayscale access derivative
|
|
284
|
-
elsif bits_per_sample > 1
|
|
285
|
-
options << '-type Grayscale'
|
|
286
|
-
end
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
options << profile_conversion_switch(profile, tmp_folder: tmp_folder)
|
|
290
|
-
|
|
291
|
-
tiff_command = "MAGICK_TEMPORARY_PATH=#{tmp_folder} convert -quiet -compress none #{options.join(' ')} '#{@path}[0]' '#{tmp_path}'"
|
|
292
|
-
result = `#{tiff_command} 2>&1`
|
|
293
|
-
raise "tiff convert command failed: #{tiff_command} with result #{result}" unless $CHILD_STATUS.success?
|
|
294
|
-
|
|
295
|
-
tmp_path
|
|
296
|
-
end
|
|
297
|
-
# rubocop:enable Metrics/MethodLength
|
|
298
|
-
# rubocop:enable Metrics/AbcSize
|
|
299
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
300
161
|
end
|
|
301
|
-
# rubocop:enable Metrics/ClassLength
|
|
302
162
|
end
|