assembly-image 1.7.7 → 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 +1 -1
- data/assembly-image.gemspec +2 -0
- data/lib/assembly-image/image.rb +11 -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 +248 -244
- data/spec/images_spec.rb +20 -22
- data/spec/spec_helper.rb +84 -0
- metadata +28 -8
- data/.travis.yml +0 -37
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,4 @@
|
|
1
|
-
[](https://circleci.com/gh/sul-dlss/assembly-image/tree/main)
|
2
2
|
[](https://codeclimate.com/github/sul-dlss/assembly-image/test_coverage)
|
3
3
|
[](https://codeclimate.com/github/sul-dlss/assembly-image/maintainability)
|
4
4
|
[](https://badge.fury.io/rb/assembly-image)
|
data/assembly-image.gemspec
CHANGED
@@ -11,6 +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
|
+
s.metadata['rubygems_mfa_required'] = 'true'
|
14
15
|
|
15
16
|
s.files = `git ls-files`.split("\n")
|
16
17
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -24,6 +25,7 @@ Gem::Specification.new do |s|
|
|
24
25
|
s.add_development_dependency 'rake'
|
25
26
|
s.add_development_dependency 'rspec', '~> 3.0'
|
26
27
|
s.add_development_dependency 'rubocop'
|
28
|
+
s.add_development_dependency 'rubocop-rspec'
|
27
29
|
s.add_development_dependency 'simplecov'
|
28
30
|
s.add_development_dependency 'yard'
|
29
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
|
#
|
@@ -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,7 +116,6 @@ 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')
|
@@ -130,64 +124,8 @@ module Assembly
|
|
130
124
|
# puts derivative_image.path # '/input/path_to_file.jp2'
|
131
125
|
# rubocop:disable Metrics/CyclomaticComplexity:
|
132
126
|
def create_jp2(params = {})
|
133
|
-
|
134
|
-
create_jp2_checks(output: output, overwrite: params[:overwrite])
|
135
|
-
|
136
|
-
# Using instance variable so that can check in tests.
|
137
|
-
@tmp_path = make_tmp_tiff(tmp_folder: params[:tmp_folder])
|
138
|
-
|
139
|
-
jp2_command = jp2_create_command(source_path: @tmp_path, output: output)
|
140
|
-
result = `#{jp2_command}`
|
141
|
-
raise "JP2 creation command failed: #{jp2_command} with result #{result}" unless $CHILD_STATUS.success?
|
142
|
-
|
143
|
-
File.delete(@tmp_path) unless @tmp_path.nil? || params[:preserve_tmp_source]
|
144
|
-
|
145
|
-
# create output response object, which is an Assembly::Image type object
|
146
|
-
Assembly::Image.new(output)
|
147
|
-
end
|
148
|
-
|
149
|
-
private
|
150
|
-
|
151
|
-
# def create_temp_tiff?
|
152
|
-
# mimetype != 'image/tiff' || compressed?
|
153
|
-
# end
|
154
|
-
|
155
|
-
def create_jp2_checks(output:, overwrite:)
|
156
|
-
check_for_file
|
157
|
-
raise 'input file is not a valid image, or is the wrong mimetype' unless jp2able?
|
158
|
-
|
159
|
-
raise SecurityError, "output #{output} exists, cannot overwrite" if !overwrite && File.exist?(output)
|
160
|
-
raise SecurityError, 'cannot recreate jp2 over itself' if overwrite && mimetype == 'image/jp2' && output == @path
|
161
|
-
end
|
162
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
163
|
-
|
164
|
-
def jp2_create_command(source_path:, output:)
|
165
|
-
kdu_bin = 'kdu_compress'
|
166
|
-
options = []
|
167
|
-
options << '-jp2_space sRGB' if samples_per_pixel == 3
|
168
|
-
options += kdu_compress_default_options
|
169
|
-
options << "Clayers=#{layers}"
|
170
|
-
"#{kdu_bin} #{options.join(' ')} -i '#{source_path}' -o '#{output}' 2>&1"
|
171
|
-
end
|
172
|
-
|
173
|
-
# rubocop:disable Metrics/MethodLength
|
174
|
-
def kdu_compress_default_options
|
175
|
-
[
|
176
|
-
'-num_threads 2', # forces Kakadu to only use 2 threads
|
177
|
-
'-precise', # forces the use of 32-bit representations
|
178
|
-
'-no_weights', # minimization of the MSE over all reconstructed colour components
|
179
|
-
'-quiet', # suppress informative messages.
|
180
|
-
'Creversible=no', # Disable reversible compression
|
181
|
-
'Cmodes=BYPASS', #
|
182
|
-
'Corder=RPCL', # R=resolution P=position C=component L=layer
|
183
|
-
'Cblk=\\{64,64\\}', # code-block dimensions; 64x64 happens to also be the default
|
184
|
-
'Cprecincts=\\{256,256\\},\\{256,256\\},\\{128,128\\}', # Precinct dimensions; 256x256 for the 2 highest resolution levels, defaults to 128x128 for the rest
|
185
|
-
'ORGgen_plt=yes', # Insert packet length information
|
186
|
-
'-rate 1.5', # Ratio of compressed bits to the image size
|
187
|
-
'Clevels=5' # Number of wavelet decomposition levels, or stages
|
188
|
-
]
|
127
|
+
Jp2Creator.create(self, params)
|
189
128
|
end
|
190
|
-
# rubocop:enable Metrics/MethodLength
|
191
129
|
|
192
130
|
def samples_per_pixel
|
193
131
|
if exif['samplesperpixel']
|
@@ -202,6 +140,14 @@ module Assembly
|
|
202
140
|
end
|
203
141
|
end
|
204
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
|
205
151
|
def bits_per_sample
|
206
152
|
if exif['bitspersample']
|
207
153
|
exif['bitspersample'].to_i
|
@@ -212,96 +158,5 @@ module Assembly
|
|
212
158
|
end
|
213
159
|
end
|
214
160
|
end
|
215
|
-
|
216
|
-
# Get size of image data in bytes
|
217
|
-
def image_data_size
|
218
|
-
(samples_per_pixel * height * width * bits_per_sample) / 8
|
219
|
-
end
|
220
|
-
|
221
|
-
# Bigtiff needs to be used if size of image exceeds 2^32 bytes.
|
222
|
-
def need_bigtiff?
|
223
|
-
image_data_size >= 2**32
|
224
|
-
end
|
225
|
-
|
226
|
-
# Get the number of JP2 layers to generate
|
227
|
-
def layers
|
228
|
-
pixdem = [width, height].max
|
229
|
-
((Math.log(pixdem) / Math.log(2)) - (Math.log(96) / Math.log(2))).ceil + 1
|
230
|
-
end
|
231
|
-
|
232
|
-
# rubocop:disable Metrics/MethodLength
|
233
|
-
# rubocop:disable Metrics/AbcSize
|
234
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
235
|
-
def profile_conversion_switch(profile, tmp_folder:)
|
236
|
-
path_to_profiles = File.join(Assembly::PATH_TO_IMAGE_GEM, 'profiles')
|
237
|
-
# eventually we may allow the user to specify the output_profile...when we do, you can just uncomment this code
|
238
|
-
# and update the tests that check for this
|
239
|
-
output_profile = 'sRGBIEC6196621' # params[:output_profile] || 'sRGBIEC6196621'
|
240
|
-
output_profile_file = File.join(path_to_profiles, "#{output_profile}.icc")
|
241
|
-
|
242
|
-
raise "output profile #{output_profile} invalid" unless File.exist?(output_profile_file)
|
243
|
-
|
244
|
-
return '' if profile.nil?
|
245
|
-
|
246
|
-
# if the input color profile exists, contract paths to the profile and setup the command
|
247
|
-
|
248
|
-
input_profile = profile.gsub(/[^[:alnum:]]/, '') # remove all non alpha-numeric characters, so we can get to a filename
|
249
|
-
|
250
|
-
# construct a path to the input profile, which might exist either in the gem itself or in the tmp folder
|
251
|
-
input_profile_file_gem = File.join(path_to_profiles, "#{input_profile}.icc")
|
252
|
-
input_profile_file_tmp = File.join(tmp_folder, "#{input_profile}.icc")
|
253
|
-
input_profile_file = File.exist?(input_profile_file_gem) ? input_profile_file_gem : input_profile_file_tmp
|
254
|
-
|
255
|
-
# if input profile was extracted and does not matches an existing known profile either in the gem or in the tmp folder,
|
256
|
-
# we'll issue an imagicmagick command to extract the profile to the tmp folder
|
257
|
-
unless File.exist?(input_profile_file)
|
258
|
-
input_profile_extract_command = "MAGICK_TEMPORARY_PATH=#{tmp_folder} convert '#{@path}'[0] #{input_profile_file}" # extract profile from input image
|
259
|
-
result = `#{input_profile_extract_command} 2>&1`
|
260
|
-
raise "input profile extraction command failed: #{input_profile_extract_command} with result #{result}" unless $CHILD_STATUS.success?
|
261
|
-
# if extraction failed or we cannot write the file, throw exception
|
262
|
-
raise 'input profile is not a known profile and could not be extracted from input file' unless File.exist?(input_profile_file)
|
263
|
-
end
|
264
|
-
|
265
|
-
"-profile #{input_profile_file} -profile #{output_profile_file}"
|
266
|
-
end
|
267
|
-
|
268
|
-
def make_tmp_tiff(tmp_folder: nil)
|
269
|
-
tmp_folder ||= Dir.tmpdir
|
270
|
-
raise "tmp_folder #{tmp_folder} does not exists" unless File.exist?(tmp_folder)
|
271
|
-
|
272
|
-
# make temp tiff filename
|
273
|
-
tmp_tiff_file = Tempfile.new(['assembly-image', '.tif'], tmp_folder)
|
274
|
-
tmp_path = tmp_tiff_file.path
|
275
|
-
|
276
|
-
options = []
|
277
|
-
|
278
|
-
# Limit the amount of memory ImageMagick is able to use.
|
279
|
-
options << '-limit memory 1GiB -limit map 1GiB'
|
280
|
-
|
281
|
-
case samples_per_pixel
|
282
|
-
when 3
|
283
|
-
options << '-type TrueColor'
|
284
|
-
when 1
|
285
|
-
options << '-depth 8' # force the production of a grayscale access derivative
|
286
|
-
options << '-type Grayscale'
|
287
|
-
end
|
288
|
-
|
289
|
-
options << profile_conversion_switch(profile, tmp_folder: tmp_folder)
|
290
|
-
|
291
|
-
# The output in the covnert command needs to be prefixed by the image type. By default ImageMagick
|
292
|
-
# will assume TIFF: when the file extension is .tif/.tiff. TIFF64: Needs to be forced when image will
|
293
|
-
# exceed 2^32 bytes in size
|
294
|
-
tiff_type = need_bigtiff? ? 'TIFF64:' : ''
|
295
|
-
|
296
|
-
tiff_command = "MAGICK_TEMPORARY_PATH=#{tmp_folder} convert -quiet -compress none #{options.join(' ')} '#{@path}[0]' #{tiff_type}'#{tmp_path}'"
|
297
|
-
result = `#{tiff_command} 2>&1`
|
298
|
-
raise "tiff convert command failed: #{tiff_command} with result #{result}" unless $CHILD_STATUS.success?
|
299
|
-
|
300
|
-
tmp_path
|
301
|
-
end
|
302
|
-
# rubocop:enable Metrics/MethodLength
|
303
|
-
# rubocop:enable Metrics/AbcSize
|
304
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
305
161
|
end
|
306
|
-
# rubocop:enable Metrics/ClassLength
|
307
162
|
end
|