assembly-image 1.6.9 → 1.7.0
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/.travis.yml +1 -0
- data/assembly-image.gemspec +0 -1
- data/lib/assembly-image.rb +2 -2
- data/lib/assembly-image/image.rb +97 -59
- data/lib/assembly-image/version.rb +1 -1
- metadata +3 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 693f1de3f3da7705f8920609b33300286a2bee43
|
4
|
+
data.tar.gz: dd91d143c8cb63df32576df88e8faaf99f75ef6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7a36d09fa0326861718e9c99495ce0ffc79ee4cb08b5fe1d9ed4d9eebb5fbf4527b3a0905434dadc4683f6c674f828e85f0dd10dde5a5b486a8a58fdac8da0f
|
7
|
+
data.tar.gz: 11e5bcee0606f7696f0d984b09a8c4aad7a558e2db1aabf2f0d2fdbd55c204c06ebaafde06e72673f5f7668975d99803bb8382699faaa07b4778a50ee324ab67
|
data/.travis.yml
CHANGED
data/assembly-image.gemspec
CHANGED
@@ -18,7 +18,6 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
19
|
s.require_paths = ['lib']
|
20
20
|
|
21
|
-
s.add_dependency 'uuidtools'
|
22
21
|
s.add_dependency 'assembly-objectfile', '>= 1.6.4'
|
23
22
|
s.add_dependency 'mini_exiftool', '>= 1.6', '< 3'
|
24
23
|
|
data/lib/assembly-image.rb
CHANGED
data/lib/assembly-image/image.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'uuidtools'
|
2
1
|
require 'assembly-objectfile'
|
2
|
+
require 'tempfile'
|
3
3
|
|
4
4
|
module Assembly
|
5
5
|
|
@@ -131,86 +131,124 @@ module Assembly
|
|
131
131
|
|
132
132
|
raise SecurityError,'cannot recreate jp2 over itself' if overwrite && mimetype=='image/jp2' && output == @path
|
133
133
|
|
134
|
-
tmp_folder = params[:tmp_folder] ||
|
134
|
+
tmp_folder = params[:tmp_folder] || Dir.tmpdir
|
135
135
|
raise "tmp_folder #{tmp_folder} does not exists" unless File.exists?(tmp_folder)
|
136
136
|
|
137
|
-
output_profile = 'sRGBIEC6196621' # params[:output_profile] || 'sRGBIEC6196621' # eventually we may allow the user to specify the output_profile...when we do, you can just uncomment this code and update the tests that check for this
|
138
137
|
preserve_tmp_source = params[:preserve_tmp_source] || false
|
139
|
-
path_to_profiles = File.join(Assembly::PATH_TO_IMAGE_GEM,'profiles')
|
140
|
-
output_profile_file = File.join(path_to_profiles,"#{output_profile}.icc")
|
141
138
|
|
142
|
-
|
139
|
+
# make temp tiff filename
|
140
|
+
tmp_tiff_file = Tempfile.new(['assembly-image', '.tif'], tmp_folder)
|
141
|
+
@tmp_path = tmp_tiff_file.path
|
143
142
|
|
144
|
-
|
145
|
-
|
143
|
+
options = []
|
144
|
+
case samples_per_pixel
|
145
|
+
when 3
|
146
|
+
options << '-type TrueColor'
|
147
|
+
when 1
|
148
|
+
if bits_per_sample == 1
|
149
|
+
options << '-type Bilevel'
|
150
|
+
options << '-depth 8' # force the production of a grayscale access derivative
|
151
|
+
elsif bits_per_sample > 1
|
152
|
+
options << '-type Grayscale'
|
153
|
+
end
|
154
|
+
end
|
146
155
|
|
147
|
-
|
156
|
+
options << profile_conversion_switch(profile, tmp_folder: tmp_folder)
|
148
157
|
|
149
|
-
|
158
|
+
tiff_command = "MAGICK_TEMPORARY_PATH=#{tmp_folder} convert -quiet -compress none #{options.join(' ')} '#{@path}[0]' '#{@tmp_path}'"
|
159
|
+
result=`#{tiff_command} 2>&1`
|
160
|
+
raise "tiff convert command failed: #{tiff_command} with result #{result}" unless $?.success?
|
150
161
|
|
151
|
-
|
162
|
+
# jp2 creation command
|
163
|
+
kdu_bin = 'kdu_compress'
|
164
|
+
options = []
|
165
|
+
options << '-jp2_space sRGB' if samples_per_pixel == 3
|
166
|
+
options += kdu_compress_default_options
|
167
|
+
options << "Clayers=#{layers.to_s}"
|
168
|
+
jp2_command = "#{kdu_bin} #{options.join(' ')} -i '#{@tmp_path}' -o '#{output}'"
|
169
|
+
result=`#{jp2_command} 2>&1`
|
170
|
+
raise "JP2 creation command failed: #{jp2_command} with result #{result}" unless $?.success?
|
152
171
|
|
153
|
-
|
154
|
-
input_profile_file_gem = File.join(path_to_profiles,"#{input_profile}.icc")
|
155
|
-
input_profile_file_tmp = File.join(tmp_folder,"#{input_profile}.icc")
|
156
|
-
input_profile_file = File.exists?(input_profile_file_gem) ? input_profile_file_gem : input_profile_file_tmp
|
172
|
+
tmp_tiff_file.delete unless preserve_tmp_source
|
157
173
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
input_profile_extraction_command = "MAGICK_TEMPORARY_PATH=#{tmp_folder} convert '#{@path}'[0] #{input_profile_file}" # extract profile from input image
|
162
|
-
result=`#{input_profile_extraction_command} 2>&1`
|
163
|
-
raise "input profile extraction command failed: #{input_profile_extraction_command} with result #{result}" unless $?.success?
|
164
|
-
raise 'input profile is not a known profile and could not be extracted from input file' unless File.exists?(input_profile_file) # if extraction failed or we cannot write the file, throw exception
|
165
|
-
end
|
174
|
+
# create output response object, which is an Assembly::Image type object
|
175
|
+
Assembly::Image.new(output)
|
176
|
+
end
|
166
177
|
|
167
|
-
|
178
|
+
private
|
179
|
+
|
180
|
+
def kdu_compress_default_options
|
181
|
+
[
|
182
|
+
'-precise', # forces the use of 32-bit representations
|
183
|
+
'-no_weights', # minimization of the MSE over all reconstructed colour components
|
184
|
+
'-quiet', # suppress informative messages.
|
185
|
+
'Creversible=no', # Disable reversible compression
|
186
|
+
'Cmodes=BYPASS', #
|
187
|
+
'Corder=RPCL', # R=resolution P=position C=component L=layer
|
188
|
+
'Cblk=\\{64,64\\}', # code-block dimensions; 64x64 happens to also be the default
|
189
|
+
'Cprecincts=\\{256,256\\},\\{256,256\\},\\{128,128\\}', # Precinct dimensions; 256x256 for the 2 highest resolution levels, defaults to 128x128 for the rest
|
190
|
+
'ORGgen_plt=yes', # Insert packet length information
|
191
|
+
'-rate 1.5', # Ratio of compressed bits to the image size
|
192
|
+
'Clevels=5' # Number of wavelet decomposition levels, or stages
|
193
|
+
]
|
194
|
+
end
|
168
195
|
|
196
|
+
def samples_per_pixel
|
197
|
+
if exif['samplesperpixel']
|
198
|
+
exif['samplesperpixel'].to_i
|
169
199
|
else
|
200
|
+
case mimetype
|
201
|
+
when 'image/tiff'
|
202
|
+
1
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
170
206
|
|
171
|
-
|
172
|
-
|
207
|
+
def bits_per_sample
|
208
|
+
if exif['bitspersample']
|
209
|
+
exif['bitspersample'].to_i
|
210
|
+
else
|
211
|
+
case mimetype
|
212
|
+
when 'image/tiff'
|
213
|
+
1
|
214
|
+
end
|
173
215
|
end
|
216
|
+
end
|
174
217
|
|
175
|
-
|
176
|
-
|
218
|
+
# Get the number of JP2 layers to generate
|
219
|
+
def layers
|
220
|
+
pixdem = [width, height].max
|
221
|
+
(( Math.log(pixdem) / Math.log(2) ) - ( Math.log(96) / Math.log(2) )).ceil + 1
|
222
|
+
end
|
177
223
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
when '1'
|
183
|
-
if bits_per_sample.to_i == 1
|
184
|
-
options += '-type Bilevel'
|
185
|
-
elsif bits_per_sample.to_i > 1
|
186
|
-
options += '-type Grayscale'
|
187
|
-
end
|
188
|
-
end
|
189
|
-
tiff_command = "MAGICK_TEMPORARY_PATH=#{tmp_folder} convert -quiet -compress none #{profile_conversion_switch} #{options} '#{@path}[0]' '#{@tmp_path}'"
|
190
|
-
result=`#{tiff_command} 2>&1`
|
191
|
-
raise "tiff convert command failed: #{tiff_command} with result #{result}" unless $?.success?
|
224
|
+
def profile_conversion_switch(profile, tmp_folder:)
|
225
|
+
path_to_profiles = File.join(Assembly::PATH_TO_IMAGE_GEM,'profiles')
|
226
|
+
output_profile = 'sRGBIEC6196621' # params[:output_profile] || 'sRGBIEC6196621' # eventually we may allow the user to specify the output_profile...when we do, you can just uncomment this code and update the tests that check for this
|
227
|
+
output_profile_file = File.join(path_to_profiles,"#{output_profile}.icc")
|
192
228
|
|
193
|
-
|
194
|
-
layers = (( Math.log(pixdem) / Math.log(2) ) - ( Math.log(96) / Math.log(2) )).ceil + 1
|
229
|
+
raise "output profile #{output_profile} invalid" unless File.exists?(output_profile_file)
|
195
230
|
|
196
|
-
|
197
|
-
kdu_bin = 'kdu_compress '
|
198
|
-
options = ''
|
199
|
-
options += ' -jp2_space sRGB ' if samples_per_pixel == '3'
|
200
|
-
options += ' -precise -no_weights -quiet Creversible=no Cmodes=BYPASS Corder=RPCL ' +
|
201
|
-
'Cblk=\\{64,64\\} Cprecincts=\\{256,256\\},\\{256,256\\},\\{128,128\\} ' +
|
202
|
-
'ORGgen_plt=yes -rate 1.5 Clevels=5 '
|
203
|
-
jp2_command = "#{kdu_bin} #{options} Clayers=#{layers.to_s} -i '#{@tmp_path}' -o '#{output}'"
|
204
|
-
result=`#{jp2_command} 2>&1`
|
205
|
-
raise "JP2 creation command failed: #{jp2_command} with result #{result}" unless $?.success?
|
231
|
+
return '' if profile.nil?
|
206
232
|
|
207
|
-
|
233
|
+
# if the input color profile exists, contract paths to the profile and setup the command
|
208
234
|
|
209
|
-
#
|
210
|
-
Assembly::Image.new(output)
|
235
|
+
input_profile = profile.gsub(/[^[:alnum:]]/, '') # remove all non alpha-numeric characters, so we can get to a filename
|
211
236
|
|
212
|
-
|
237
|
+
# construct a path to the input profile, which might exist either in the gem itself or in the tmp folder
|
238
|
+
input_profile_file_gem = File.join(path_to_profiles,"#{input_profile}.icc")
|
239
|
+
input_profile_file_tmp = File.join(tmp_folder,"#{input_profile}.icc")
|
240
|
+
input_profile_file = File.exists?(input_profile_file_gem) ? input_profile_file_gem : input_profile_file_tmp
|
213
241
|
|
214
|
-
|
242
|
+
# if input profile was extracted and does not matches an existing known profile either in the gem or in the tmp folder,
|
243
|
+
# we'll issue an imagicmagick command to extract the profile to the tmp folder
|
244
|
+
unless File.exists?(input_profile_file)
|
245
|
+
input_profile_extraction_command = "MAGICK_TEMPORARY_PATH=#{tmp_folder} convert '#{@path}'[0] #{input_profile_file}" # extract profile from input image
|
246
|
+
result=`#{input_profile_extraction_command} 2>&1`
|
247
|
+
raise "input profile extraction command failed: #{input_profile_extraction_command} with result #{result}" unless $?.success?
|
248
|
+
raise 'input profile is not a known profile and could not be extracted from input file' unless File.exists?(input_profile_file) # if extraction failed or we cannot write the file, throw exception
|
249
|
+
end
|
215
250
|
|
251
|
+
"-profile #{input_profile_file} -profile #{output_profile_file}"
|
252
|
+
end
|
253
|
+
end
|
216
254
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: assembly-image
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Mangiafico
|
@@ -11,22 +11,8 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2018-03-19 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
17
|
-
name: uuidtools
|
18
|
-
requirement: !ruby/object:Gem::Requirement
|
19
|
-
requirements:
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '0'
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0'
|
30
16
|
- !ruby/object:Gem::Dependency
|
31
17
|
name: assembly-objectfile
|
32
18
|
requirement: !ruby/object:Gem::Requirement
|
@@ -156,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
142
|
version: '0'
|
157
143
|
requirements: []
|
158
144
|
rubyforge_project: assembly-image
|
159
|
-
rubygems_version: 2.6.
|
145
|
+
rubygems_version: 2.6.11
|
160
146
|
signing_key:
|
161
147
|
specification_version: 4
|
162
148
|
summary: Ruby immplementation of image services needed to prepare objects to be accessioned
|
@@ -167,4 +153,3 @@ test_files:
|
|
167
153
|
- spec/spec_helper.rb
|
168
154
|
- spec/test_data/input/.empty
|
169
155
|
- spec/test_data/output/.empty
|
170
|
-
has_rdoc:
|