assembly-image 1.7.0 → 1.7.1
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 +5 -5
- data/.rubocop.yml +12 -4
- data/.travis.yml +1 -0
- data/Gemfile +2 -0
- data/README.md +4 -4
- data/Rakefile +14 -3
- data/assembly-image.gemspec +8 -6
- data/bin/console +1 -0
- data/config/boot.rb +2 -1
- data/lib/assembly-image/image.rb +101 -75
- data/lib/assembly-image/images.rb +42 -32
- data/lib/assembly-image/version.rb +3 -1
- data/lib/assembly-image.rb +2 -2
- data/spec/image_spec.rb +75 -54
- data/spec/images_spec.rb +21 -20
- data/spec/spec_helper.rb +25 -19
- metadata +19 -6
- data/.rubocop_todo.yml +0 -263
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 37d19061d4cdbcf04b0a9dfa0702d9ae68eda22a248daba5284327d4a0a6586b
|
4
|
+
data.tar.gz: 77961e8b421063939c636e20d32ccfc74e7fa334e2229903d3a9da2a37dfcfa2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e129b0e5549da1e7c3925cded0ad977bd537a4da8492be152738b26fecd18445c3c29e72a5040865cdabca5ce8fe1e3951805abbc2734b2bc38a1d52831ad75
|
7
|
+
data.tar.gz: 848bdfc0b96d1257371fd8b51589eef953020b5dae43c98068206c96b22472ae27bab0b72fcb51e89a2786f5cbd3cec831ebcf2571a0da737cdad10b8b5cbd78
|
data/.rubocop.yml
CHANGED
@@ -1,13 +1,21 @@
|
|
1
|
-
inherit_from: .rubocop_todo.yml
|
2
|
-
|
3
1
|
# rspec expect{...} is conventional
|
4
|
-
|
2
|
+
Layout/SpaceBeforeBlockBraces:
|
5
3
|
Exclude:
|
6
4
|
- 'spec/**/*_spec.rb'
|
7
5
|
|
8
|
-
|
6
|
+
Layout/EmptyLineBetweenDefs:
|
9
7
|
AllowAdjacentOneLineDefs: true
|
10
8
|
|
11
9
|
# Configuration parameters: AllowURI, URISchemes.
|
12
10
|
Metrics/LineLength:
|
13
11
|
Max: 200
|
12
|
+
|
13
|
+
Naming/FileName:
|
14
|
+
Exclude:
|
15
|
+
- lib/assembly-image.rb
|
16
|
+
|
17
|
+
Style/WordArray:
|
18
|
+
Enabled: false
|
19
|
+
|
20
|
+
AllCops:
|
21
|
+
TargetRubyVersion: 2.5.3
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -50,6 +50,7 @@ perform image operations necessary for accessioning of content.
|
|
50
50
|
* 1.6.5 fix problem with lack of extension in incoming tif causing a problem when creating jp2
|
51
51
|
* 1.6.7 release to github/rubygems
|
52
52
|
* 1.6.9 update mini_exiftool
|
53
|
+
* 1.7.1 for jp2, only transcode to tiff if not a tiff
|
53
54
|
|
54
55
|
## Notes
|
55
56
|
|
@@ -98,10 +99,9 @@ yard server --reload
|
|
98
99
|
|
99
100
|
## Prerequisites
|
100
101
|
|
101
|
-
1.
|
102
|
-
|
103
|
-
|
104
|
-
4. Exiftool
|
102
|
+
1. Kakadu Proprietary Software Binaries - for JP2 generation
|
103
|
+
1. ImageMagick 6.5.4 or higher
|
104
|
+
1. Exiftool
|
105
105
|
|
106
106
|
### Kakadu
|
107
107
|
|
data/Rakefile
CHANGED
@@ -1,8 +1,19 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'bundler/setup' # Set up gems listed in the Gemfile.
|
3
4
|
require 'rspec/core/rake_task'
|
5
|
+
require 'rubocop/rake_task'
|
6
|
+
require 'bundler/gem_tasks'
|
7
|
+
|
8
|
+
desc 'Run style checker'
|
9
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
10
|
+
task.fail_on_error = true
|
11
|
+
end
|
4
12
|
|
5
|
-
desc 'Run specs'
|
6
13
|
RSpec::Core::RakeTask.new(:spec)
|
7
14
|
|
8
|
-
task :
|
15
|
+
task ci: [:rubocop] do
|
16
|
+
Rake::Task['spec'].invoke
|
17
|
+
end
|
18
|
+
|
19
|
+
task default: :ci
|
data/assembly-image.gemspec
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
2
4
|
require 'assembly-image/version'
|
3
5
|
|
4
6
|
Gem::Specification.new do |s|
|
5
7
|
s.name = 'assembly-image'
|
6
8
|
s.version = Assembly::Image::VERSION
|
7
|
-
s.authors = ['Peter Mangiafico', 'Renzo Sanchez-Silva','Monty Hindman','Tony Calavano']
|
9
|
+
s.authors = ['Peter Mangiafico', 'Renzo Sanchez-Silva', 'Monty Hindman', 'Tony Calavano']
|
8
10
|
s.email = ['pmangiafico@stanford.edu']
|
9
11
|
s.homepage = ''
|
10
|
-
s.summary =
|
11
|
-
s.description =
|
12
|
+
s.summary = 'Ruby immplementation of image services needed to prepare objects to be accessioned in SULAIR digital library'
|
13
|
+
s.description = 'Contains classes to create derivative image files and perform other image operations'
|
12
14
|
|
13
15
|
s.rubyforge_project = 'assembly-image'
|
14
16
|
|
@@ -21,8 +23,8 @@ Gem::Specification.new do |s|
|
|
21
23
|
s.add_dependency 'assembly-objectfile', '>= 1.6.4'
|
22
24
|
s.add_dependency 'mini_exiftool', '>= 1.6', '< 3'
|
23
25
|
|
26
|
+
s.add_development_dependency 'rake'
|
24
27
|
s.add_development_dependency 'rspec', '~> 3.0'
|
28
|
+
s.add_development_dependency 'rubocop'
|
25
29
|
s.add_development_dependency 'yard'
|
26
|
-
s.add_development_dependency 'rake'
|
27
|
-
|
28
30
|
end
|
data/bin/console
CHANGED
data/config/boot.rb
CHANGED
data/lib/assembly-image/image.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'assembly-objectfile'
|
2
4
|
require 'tempfile'
|
3
5
|
|
4
6
|
module Assembly
|
5
|
-
|
6
7
|
# The Image class contains methods to operate on an image.
|
8
|
+
# rubocop:disable Metrics/ClassLength
|
7
9
|
class Image
|
8
|
-
|
9
10
|
# include common behaviors from assembly-objectfile gem
|
10
11
|
include Assembly::ObjectFileable
|
11
12
|
|
@@ -45,7 +46,6 @@ module Assembly
|
|
45
46
|
end
|
46
47
|
|
47
48
|
# Get the image width from exif data
|
48
|
-
#
|
49
49
|
# @return [integer] image height in pixels
|
50
50
|
# Example:
|
51
51
|
# source_img=Assembly::Image.new('/input/path_to_file.tif')
|
@@ -67,19 +67,17 @@ module Assembly
|
|
67
67
|
# Example:
|
68
68
|
# source_img=Assembly::Image.new('/input/path_to_file.tif')
|
69
69
|
# source_img.add_exif_profile_description('Adobe RGB 1998')
|
70
|
-
def add_exif_profile_description(profile_name,force=false)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
raise "profile addition command failed: #{command} with result #{result}" unless $?.success?
|
79
|
-
end
|
80
|
-
rescue Exception => e
|
81
|
-
puts "** Error for #{filename}: #{e.message}"
|
70
|
+
def add_exif_profile_description(profile_name, force = false)
|
71
|
+
if profile.nil? || force
|
72
|
+
input_profile = profile_name.gsub(/[^[:alnum:]]/, '') # remove all non alpha-numeric characters, so we can get to a filename
|
73
|
+
path_to_profiles = File.join(Assembly::PATH_TO_IMAGE_GEM, 'profiles')
|
74
|
+
input_profile_file = File.join(path_to_profiles, "#{input_profile}.icc")
|
75
|
+
command = "exiftool '-icc_profile<=#{input_profile_file}' #{path}"
|
76
|
+
result = `#{command} 2>&1`
|
77
|
+
raise "profile addition command failed: #{command} with result #{result}" unless $CHILD_STATUS.success?
|
82
78
|
end
|
79
|
+
rescue StandardError => e
|
80
|
+
puts "** Error for #{filename}: #{e.message}"
|
83
81
|
end
|
84
82
|
|
85
83
|
# Returns the full default jp2 path and filename that will be created from the given image
|
@@ -89,7 +87,7 @@ module Assembly
|
|
89
87
|
# source_img=Assembly::Image.new('/input/path_to_file.tif')
|
90
88
|
# puts source_img.jp2_filename # gives /input/path_to_file.jp2
|
91
89
|
def jp2_filename
|
92
|
-
File.extname(@path).empty? ? "#{@path}.jp2" : @path.gsub(File.extname(@path),'.jp2')
|
90
|
+
File.extname(@path).empty? ? "#{@path}.jp2" : @path.gsub(File.extname(@path), '.jp2')
|
93
91
|
end
|
94
92
|
|
95
93
|
# Returns the full DPG equivalent jp2 path and filename that would match with the given image
|
@@ -99,7 +97,7 @@ module Assembly
|
|
99
97
|
# source_img=Assembly::Image.new('/input/path_to_file.tif')
|
100
98
|
# puts source_img.jp2_filename # gives /input/path_to_file.jp2
|
101
99
|
def dpg_jp2_filename
|
102
|
-
jp2_filename.gsub('_00_','_05_')
|
100
|
+
jp2_filename.gsub('_00_', '_05_')
|
103
101
|
end
|
104
102
|
|
105
103
|
# Create a JP2 file for the current image.
|
@@ -118,65 +116,52 @@ module Assembly
|
|
118
116
|
# derivative_img=source_img.create_jp2(:overwrite=>true)
|
119
117
|
# puts derivative_img.mimetype # 'image/jp2'
|
120
118
|
# puts derivative_image.path # '/input/path_to_file.jp2'
|
119
|
+
# rubocop:disable Metrics/AbcSize
|
120
|
+
# rubocop:disable Metrics/MethodLength
|
121
121
|
def create_jp2(params = {})
|
122
|
+
output = params[:output] || jp2_filename
|
123
|
+
create_jp2_checks(output: output, overwrite: params[:overwrite])
|
122
124
|
|
123
|
-
|
125
|
+
# Using instance variable so that can check in tests.
|
126
|
+
source_path = if mimetype != 'image/tiff'
|
127
|
+
@tmp_path = make_tmp_tiff(tmp_folder: params[:tmp_folder])
|
128
|
+
else
|
129
|
+
@path
|
130
|
+
end
|
124
131
|
|
125
|
-
|
132
|
+
result = `#{jp2_create_command(source_path: source_path, output: output)}`
|
133
|
+
raise "JP2 creation command failed: #{jp2_command} with result #{result}" unless $CHILD_STATUS.success?
|
126
134
|
|
127
|
-
|
128
|
-
overwrite = params[:overwrite] || false
|
135
|
+
File.delete(source_path) unless @tmp_path.nil? || params[:preserve_tmp_source]
|
129
136
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
raise "tmp_folder #{tmp_folder} does not exists" unless File.exists?(tmp_folder)
|
136
|
-
|
137
|
-
preserve_tmp_source = params[:preserve_tmp_source] || false
|
138
|
-
|
139
|
-
# make temp tiff filename
|
140
|
-
tmp_tiff_file = Tempfile.new(['assembly-image', '.tif'], tmp_folder)
|
141
|
-
@tmp_path = tmp_tiff_file.path
|
137
|
+
# create output response object, which is an Assembly::Image type object
|
138
|
+
Assembly::Image.new(output)
|
139
|
+
end
|
140
|
+
# rubocop:enable Metrics/AbcSize
|
141
|
+
# rubocop:enable Metrics/MethodLength
|
142
142
|
|
143
|
-
|
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
|
143
|
+
private
|
155
144
|
|
156
|
-
|
145
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
146
|
+
def create_jp2_checks(output:, overwrite:)
|
147
|
+
check_for_file
|
148
|
+
raise 'input file is not a valid image, or is the wrong mimetype' unless jp2able?
|
157
149
|
|
158
|
-
|
159
|
-
|
160
|
-
|
150
|
+
raise SecurityError, "output #{output} exists, cannot overwrite" if !overwrite && File.exist?(output)
|
151
|
+
raise SecurityError, 'cannot recreate jp2 over itself' if overwrite && mimetype == 'image/jp2' && output == @path
|
152
|
+
end
|
153
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
161
154
|
|
162
|
-
|
155
|
+
def jp2_create_command(source_path:, output:)
|
163
156
|
kdu_bin = 'kdu_compress'
|
164
157
|
options = []
|
165
158
|
options << '-jp2_space sRGB' if samples_per_pixel == 3
|
166
159
|
options += kdu_compress_default_options
|
167
|
-
options << "Clayers=#{layers
|
168
|
-
|
169
|
-
result=`#{jp2_command} 2>&1`
|
170
|
-
raise "JP2 creation command failed: #{jp2_command} with result #{result}" unless $?.success?
|
171
|
-
|
172
|
-
tmp_tiff_file.delete unless preserve_tmp_source
|
173
|
-
|
174
|
-
# create output response object, which is an Assembly::Image type object
|
175
|
-
Assembly::Image.new(output)
|
160
|
+
options << "Clayers=#{layers}"
|
161
|
+
"#{kdu_bin} #{options.join(' ')} -i '#{source_path}' -o '#{output}' 2>&1"
|
176
162
|
end
|
177
163
|
|
178
|
-
|
179
|
-
|
164
|
+
# rubocop:disable Metrics/MethodLength
|
180
165
|
def kdu_compress_default_options
|
181
166
|
[
|
182
167
|
'-precise', # forces the use of 32-bit representations
|
@@ -192,6 +177,7 @@ module Assembly
|
|
192
177
|
'Clevels=5' # Number of wavelet decomposition levels, or stages
|
193
178
|
]
|
194
179
|
end
|
180
|
+
# rubocop:enable Metrics/MethodLength
|
195
181
|
|
196
182
|
def samples_per_pixel
|
197
183
|
if exif['samplesperpixel']
|
@@ -218,37 +204,77 @@ module Assembly
|
|
218
204
|
# Get the number of JP2 layers to generate
|
219
205
|
def layers
|
220
206
|
pixdem = [width, height].max
|
221
|
-
((
|
207
|
+
((Math.log(pixdem) / Math.log(2)) - (Math.log(96) / Math.log(2))).ceil + 1
|
222
208
|
end
|
223
209
|
|
210
|
+
# rubocop:disable Metrics/MethodLength
|
211
|
+
# rubocop:disable Metrics/AbcSize
|
212
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
224
213
|
def profile_conversion_switch(profile, tmp_folder:)
|
225
|
-
path_to_profiles
|
226
|
-
|
227
|
-
|
214
|
+
path_to_profiles = File.join(Assembly::PATH_TO_IMAGE_GEM, 'profiles')
|
215
|
+
# eventually we may allow the user to specify the output_profile...when we do, you can just uncomment this code
|
216
|
+
# and update the tests that check for this
|
217
|
+
output_profile = 'sRGBIEC6196621' # params[:output_profile] || 'sRGBIEC6196621'
|
218
|
+
output_profile_file = File.join(path_to_profiles, "#{output_profile}.icc")
|
228
219
|
|
229
|
-
raise "output profile #{output_profile} invalid" unless File.
|
220
|
+
raise "output profile #{output_profile} invalid" unless File.exist?(output_profile_file)
|
230
221
|
|
231
222
|
return '' if profile.nil?
|
232
223
|
|
233
224
|
# if the input color profile exists, contract paths to the profile and setup the command
|
234
225
|
|
235
|
-
input_profile = profile.gsub(/[^[:alnum:]]/, '')
|
226
|
+
input_profile = profile.gsub(/[^[:alnum:]]/, '') # remove all non alpha-numeric characters, so we can get to a filename
|
236
227
|
|
237
228
|
# 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.
|
229
|
+
input_profile_file_gem = File.join(path_to_profiles, "#{input_profile}.icc")
|
230
|
+
input_profile_file_tmp = File.join(tmp_folder, "#{input_profile}.icc")
|
231
|
+
input_profile_file = File.exist?(input_profile_file_gem) ? input_profile_file_gem : input_profile_file_tmp
|
241
232
|
|
242
233
|
# if input profile was extracted and does not matches an existing known profile either in the gem or in the tmp folder,
|
243
234
|
# we'll issue an imagicmagick command to extract the profile to the tmp folder
|
244
|
-
unless File.
|
245
|
-
|
246
|
-
result
|
247
|
-
raise "input profile extraction command failed: #{
|
248
|
-
|
235
|
+
unless File.exist?(input_profile_file)
|
236
|
+
input_profile_extract_command = "MAGICK_TEMPORARY_PATH=#{tmp_folder} convert '#{@path}'[0] #{input_profile_file}" # extract profile from input image
|
237
|
+
result = `#{input_profile_extract_command} 2>&1`
|
238
|
+
raise "input profile extraction command failed: #{input_profile_extract_command} with result #{result}" unless $CHILD_STATUS.success?
|
239
|
+
# if extraction failed or we cannot write the file, throw exception
|
240
|
+
raise 'input profile is not a known profile and could not be extracted from input file' unless File.exist?(input_profile_file)
|
249
241
|
end
|
250
242
|
|
251
243
|
"-profile #{input_profile_file} -profile #{output_profile_file}"
|
252
244
|
end
|
245
|
+
|
246
|
+
def make_tmp_tiff(tmp_folder: nil)
|
247
|
+
tmp_folder ||= Dir.tmpdir
|
248
|
+
raise "tmp_folder #{tmp_folder} does not exists" unless File.exist?(tmp_folder)
|
249
|
+
|
250
|
+
# make temp tiff filename
|
251
|
+
tmp_tiff_file = Tempfile.new(['assembly-image', '.tif'], tmp_folder)
|
252
|
+
tmp_path = tmp_tiff_file.path
|
253
|
+
|
254
|
+
options = []
|
255
|
+
case samples_per_pixel
|
256
|
+
when 3
|
257
|
+
options << '-type TrueColor'
|
258
|
+
when 1
|
259
|
+
if bits_per_sample == 1
|
260
|
+
options << '-type Bilevel'
|
261
|
+
options << '-depth 8' # force the production of a grayscale access derivative
|
262
|
+
elsif bits_per_sample > 1
|
263
|
+
options << '-type Grayscale'
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
options << profile_conversion_switch(profile, tmp_folder: tmp_folder)
|
268
|
+
|
269
|
+
tiff_command = "MAGICK_TEMPORARY_PATH=#{tmp_folder} convert -quiet -compress none #{options.join(' ')} '#{@path}[0]' '#{tmp_path}'"
|
270
|
+
result = `#{tiff_command} 2>&1`
|
271
|
+
raise "tiff convert command failed: #{tiff_command} with result #{result}" unless $CHILD_STATUS.success?
|
272
|
+
|
273
|
+
tmp_path
|
274
|
+
end
|
275
|
+
# rubocop:enable Metrics/MethodLength
|
276
|
+
# rubocop:enable Metrics/AbcSize
|
277
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
253
278
|
end
|
279
|
+
# rubocop:enable Metrics/ClassLength
|
254
280
|
end
|
@@ -1,15 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'logger'
|
2
4
|
module Assembly
|
3
|
-
|
4
5
|
# The Images class contains methods to operate on multiple images in batch.
|
5
6
|
class Images
|
6
|
-
|
7
7
|
def self.logger
|
8
8
|
@logger ||= Logger.new(STDERR)
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
class << self
|
12
|
+
attr_writer :logger
|
13
13
|
end
|
14
14
|
|
15
15
|
# Pass in a source path and have exif color profile descriptions added to all images contained.
|
@@ -28,8 +28,9 @@ module Assembly
|
|
28
28
|
#
|
29
29
|
# Example:
|
30
30
|
# Assembly::Images.batch_add_exif_profile_description('/full_path_to_tifs','Adobe RGB 1998')
|
31
|
-
|
32
|
-
|
31
|
+
# rubocop:disable Metrics/MethodLength
|
32
|
+
# rubocop:disable Metrics/AbcSize
|
33
|
+
def self.batch_add_exif_profile_descr(source, profile_name, params = {})
|
33
34
|
extension = params[:extension] || 'tif'
|
34
35
|
recursive = params[:recursive] || false
|
35
36
|
force = params[:force] || false
|
@@ -40,13 +41,15 @@ module Assembly
|
|
40
41
|
|
41
42
|
# iterate over input directory looking for tifs
|
42
43
|
pattern = recursive ? "**/*.#{extension}" : "*.#{extension}*"
|
43
|
-
Dir.glob(File.join(source,pattern)).each do |file|
|
44
|
-
img=Assembly::Image.new(file)
|
44
|
+
Dir.glob(File.join(source, pattern)).each do |file|
|
45
|
+
img = Assembly::Image.new(file)
|
45
46
|
logger.debug "Processing #{file}"
|
46
|
-
img.add_exif_profile_description(profile_name,force)
|
47
|
+
img.add_exif_profile_description(profile_name, force)
|
47
48
|
end
|
48
49
|
'Complete'
|
49
50
|
end
|
51
|
+
# rubocop:enable Metrics/MethodLength
|
52
|
+
# rubocop:enable Metrics/AbcSize
|
50
53
|
|
51
54
|
# Pass in a source path and get JP2s generate for each tiff that is in the source path
|
52
55
|
#
|
@@ -63,35 +66,42 @@ module Assembly
|
|
63
66
|
#
|
64
67
|
# Example:
|
65
68
|
# Assembly::Images.batch_generate_jp2('/full_path_to_tifs')
|
66
|
-
|
69
|
+
# rubocop:disable Metrics/MethodLength
|
70
|
+
# rubocop:disable Metrics/AbcSize
|
71
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
72
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
73
|
+
def self.batch_generate_jp2(source, params = {})
|
74
|
+
raise 'Input path does not exist' unless File.directory?(source)
|
67
75
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
recursive = params[:recursive] || false
|
76
|
+
output = params[:output] || File.join(source, 'jp2') # default output directgory is jp2 sub-directory from source
|
77
|
+
extension = params[:extension] || 'tif'
|
78
|
+
overwrite = params[:overwrite] || false
|
79
|
+
recursive = params[:recursive] || false
|
73
80
|
|
74
|
-
|
75
|
-
|
81
|
+
Dir.mkdir(output) unless File.directory?(output) # attemp to make output directory
|
82
|
+
raise 'Output path does not exist or could not be created' unless File.directory?(output)
|
76
83
|
|
77
|
-
|
78
|
-
|
84
|
+
logger.debug "Source: #{source}"
|
85
|
+
logger.debug "Destination: #{output}"
|
79
86
|
|
80
|
-
|
87
|
+
pattern = recursive ? "**/*.#{extension}" : "*.#{extension}*"
|
81
88
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
89
|
+
# iterate over input directory looking for tifs
|
90
|
+
Dir.glob(File.join(source, pattern)).each do |file|
|
91
|
+
source_img = Assembly::Image.new(file)
|
92
|
+
output_img = File.join(output, File.basename(file, File.extname(file)) + '.jp2') # output image gets same file name as source, but with a jp2 extension and in the correct output directory
|
93
|
+
begin
|
94
|
+
source_img.create_jp2(overwrite: overwrite, output: output_img)
|
95
|
+
logger.debug "Generated jp2 for #{File.basename(file)}"
|
96
|
+
rescue StandardError => e
|
97
|
+
logger.debug "** Error for #{File.basename(file)}: #{e.message}"
|
92
98
|
end
|
93
|
-
|
94
|
-
|
99
|
+
end
|
100
|
+
'Complete'
|
95
101
|
end
|
102
|
+
# rubocop:enable Metrics/MethodLength
|
103
|
+
# rubocop:enable Metrics/AbcSize
|
104
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
105
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
96
106
|
end
|
97
107
|
end
|
data/lib/assembly-image.rb
CHANGED
data/spec/image_spec.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
5
|
+
# rubocop:disable Metrics/BlockLength
|
3
6
|
describe Assembly::Image do
|
4
|
-
|
5
7
|
it 'should not run if no input file is passed in' do
|
6
|
-
@ai=Assembly::Image.new('')
|
7
|
-
expect{@ai.create_jp2}.to raise_error
|
8
|
+
@ai = Assembly::Image.new('')
|
9
|
+
expect{ @ai.create_jp2 }.to raise_error
|
8
10
|
end
|
9
11
|
|
10
12
|
it 'should indicate the default jp2 filename' do
|
11
13
|
@ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
|
12
|
-
expect(@ai.jp2_filename).to eq TEST_TIF_INPUT_FILE.gsub('.tif','.jp2')
|
14
|
+
expect(@ai.jp2_filename).to eq TEST_TIF_INPUT_FILE.gsub('.tif', '.jp2')
|
13
15
|
end
|
14
16
|
|
15
17
|
it 'should indicate the default jp2 filename' do
|
@@ -19,7 +21,7 @@ describe Assembly::Image do
|
|
19
21
|
|
20
22
|
it 'should indicate the default DPG jp2 filename' do
|
21
23
|
@ai = Assembly::Image.new(TEST_DPG_TIF_INPUT_FILE)
|
22
|
-
expect(@ai.dpg_jp2_filename).to eq TEST_DPG_TIF_INPUT_FILE.gsub('.tif','.jp2').gsub('_00_','_05_')
|
24
|
+
expect(@ai.dpg_jp2_filename).to eq TEST_DPG_TIF_INPUT_FILE.gsub('.tif', '.jp2').gsub('_00_', '_05_')
|
23
25
|
end
|
24
26
|
|
25
27
|
it 'should indicate the default jp2 filename' do
|
@@ -32,77 +34,92 @@ describe Assembly::Image do
|
|
32
34
|
expect(File).to exist TEST_TIF_INPUT_FILE
|
33
35
|
expect(File).to_not exist TEST_JP2_OUTPUT_FILE
|
34
36
|
@ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
|
35
|
-
result
|
37
|
+
result = @ai.create_jp2(output: TEST_JP2_OUTPUT_FILE)
|
38
|
+
# Indicates a temp tiff was not created.
|
39
|
+
expect(@ai.tmp_path).to be_nil
|
36
40
|
expect(result).to be_a_kind_of Assembly::Image
|
37
41
|
expect(result.path).to eq TEST_JP2_OUTPUT_FILE
|
38
42
|
expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
|
39
43
|
expect(result.exif.colorspace).to eq 'sRGB'
|
40
|
-
@jp2=Assembly::Image.new(TEST_JP2_OUTPUT_FILE)
|
44
|
+
@jp2 = Assembly::Image.new(TEST_JP2_OUTPUT_FILE)
|
41
45
|
expect(@jp2.height).to eq 100
|
42
46
|
expect(@jp2.width).to eq 100
|
43
47
|
end
|
44
48
|
|
45
49
|
it 'should create grayscale jp2 when given a bitonal tif' do
|
46
50
|
skip 'The latest version of Kakadu may require some changes for this work correctly'
|
47
|
-
# error message is
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
# error message is
|
52
|
+
# JP2 creation command failed: kdu_compress -precise -no_weights -quiet Creversible=no Cmodes=BYPASS
|
53
|
+
# Corder=RPCL Cblk=\{64,64\} Cprecincts=\{256,256\},\{256,256\},\{128,128\} ORGgen_plt=yes -rate 1.5 Clevels=5
|
54
|
+
# Clayers=2 -i '/tmp/408d3740-e25f-4c1b-889f-3f138d088fe4.tif' -o '/home/travis/build/sul-dlss/assembly-image/spec/test_data/output/test.jp2'
|
55
|
+
# with result Kakadu Error:
|
56
|
+
# The number of colours associated with the colour space identified by the source
|
57
|
+
# file (possible from an embedded ICC profile) is not consistent with the number
|
58
|
+
# of supplied image components and/or colour palette. You can address this
|
59
|
+
# problem by supplying a `-jp2_space' or `-jpx_space' argument to explicitly
|
60
|
+
# identify a colour space that has anywhere from 1 to 1 colour components.
|
61
|
+
generate_test_image(TEST_TIF_INPUT_FILE, color: 'white', image_type: 'Bilevel')
|
55
62
|
expect(File).to exist TEST_TIF_INPUT_FILE
|
56
63
|
expect(File).to_not exist TEST_JP2_OUTPUT_FILE
|
57
64
|
@ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
|
58
65
|
expect(@ai).to have_color_profile
|
59
|
-
result
|
66
|
+
result = @ai.create_jp2(output: TEST_JP2_OUTPUT_FILE)
|
67
|
+
# Indicates a temp tiff was not created.
|
68
|
+
expect(@ai.tmp_path).to be_nil
|
60
69
|
expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
|
61
70
|
expect(result.exif.colorspace).to eq 'Grayscale'
|
62
71
|
end
|
63
72
|
|
64
73
|
it 'should create color jp2 when given a color tif but bitonal image data (1 channels and 1 bits per pixel)' do
|
65
|
-
generate_test_image(TEST_TIF_INPUT_FILE
|
74
|
+
generate_test_image(TEST_TIF_INPUT_FILE, color: 'white', image_type: 'TrueColor', profile: '')
|
66
75
|
expect(File).to exist TEST_TIF_INPUT_FILE
|
67
76
|
expect(File).to_not exist TEST_JP2_OUTPUT_FILE
|
68
77
|
@ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
|
69
78
|
expect(@ai).to_not have_color_profile
|
70
|
-
result
|
79
|
+
result = @ai.create_jp2(output: TEST_JP2_OUTPUT_FILE)
|
80
|
+
# Indicates a temp tiff was not created.
|
81
|
+
expect(@ai.tmp_path).to be_nil
|
71
82
|
expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
|
72
83
|
expect(result.exif.colorspace).to eq 'sRGB'
|
73
84
|
end
|
74
85
|
|
75
86
|
it 'should create grayscale jp2 when given a graycale tif but with bitonal image data (1 channel and 1 bits per pixel)' do
|
76
|
-
generate_test_image(TEST_TIF_INPUT_FILE
|
87
|
+
generate_test_image(TEST_TIF_INPUT_FILE, color: 'white', image_type: 'Grayscale', profile: '')
|
77
88
|
expect(File).to exist TEST_TIF_INPUT_FILE
|
78
89
|
expect(File).to_not exist TEST_JP2_OUTPUT_FILE
|
79
90
|
@ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
|
91
|
+
# Indicates a temp tiff was not created.
|
92
|
+
expect(@ai.tmp_path).to be_nil
|
80
93
|
expect(@ai).to_not have_color_profile
|
81
|
-
result
|
94
|
+
result = @ai.create_jp2(output: TEST_JP2_OUTPUT_FILE)
|
82
95
|
expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
|
83
96
|
expect(result.exif.colorspace).to eq 'Grayscale'
|
84
97
|
end
|
85
98
|
|
86
99
|
it 'should create color jp2 when given a color tif but with greyscale image data (1 channel and 8 bits per pixel)' do
|
87
|
-
generate_test_image(TEST_TIF_INPUT_FILE
|
100
|
+
generate_test_image(TEST_TIF_INPUT_FILE, color: 'gray', image_type: 'TrueColor', profile: '')
|
88
101
|
expect(File).to exist TEST_TIF_INPUT_FILE
|
89
102
|
expect(File).to_not exist TEST_JP2_OUTPUT_FILE
|
90
103
|
@ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
|
104
|
+
# Indicates a temp tiff was not created.
|
105
|
+
expect(@ai.tmp_path).to be_nil
|
91
106
|
expect(@ai).to_not have_color_profile
|
92
|
-
result
|
107
|
+
result = @ai.create_jp2(output: TEST_JP2_OUTPUT_FILE)
|
93
108
|
expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
|
94
109
|
expect(result.exif.colorspace).to eq 'sRGB'
|
95
110
|
end
|
96
111
|
|
97
112
|
it 'should create a jp2 when the source image has no profile' do
|
98
|
-
generate_test_image(TEST_TIF_INPUT_FILE
|
113
|
+
generate_test_image(TEST_TIF_INPUT_FILE, profile: '') # generate a test input with no profile
|
99
114
|
expect(File).to exist TEST_TIF_INPUT_FILE
|
100
115
|
expect(File).to_not exist TEST_JP2_OUTPUT_FILE
|
101
116
|
@ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
|
117
|
+
# Indicates a temp tiff was not created.
|
118
|
+
expect(@ai.tmp_path).to be_nil
|
102
119
|
expect(@ai).to_not have_color_profile
|
103
120
|
expect(@ai).to be_a_valid_image
|
104
121
|
expect(@ai).to be_jp2able
|
105
|
-
@ai.create_jp2(:
|
122
|
+
@ai.create_jp2(output: TEST_JP2_OUTPUT_FILE)
|
106
123
|
expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
|
107
124
|
end
|
108
125
|
|
@@ -112,7 +129,7 @@ describe Assembly::Image do
|
|
112
129
|
expect(File).to exist TEST_TIF_INPUT_FILE
|
113
130
|
expect(File).to exist TEST_JP2_OUTPUT_FILE
|
114
131
|
@ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
|
115
|
-
expect{@ai.create_jp2(:
|
132
|
+
expect{ @ai.create_jp2(output: TEST_JP2_OUTPUT_FILE) }.to raise_error(SecurityError)
|
116
133
|
end
|
117
134
|
|
118
135
|
it 'should get the correct image height and width' do
|
@@ -135,57 +152,61 @@ describe Assembly::Image do
|
|
135
152
|
generate_test_image(TEST_TIF_INPUT_FILE)
|
136
153
|
expect(File).to exist TEST_TIF_INPUT_FILE
|
137
154
|
@ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
|
138
|
-
result
|
155
|
+
result = @ai.create_jp2(output_profile: 'bogusness')
|
139
156
|
expect(result).to be_a_kind_of Assembly::Image
|
140
157
|
expect(result.path).to eq TEST_JP2_INPUT_FILE
|
141
158
|
expect(TEST_JP2_INPUT_FILE).to be_a_jp2
|
142
159
|
expect(result.exif.colorspace).to eq 'sRGB'
|
143
160
|
end
|
144
161
|
|
162
|
+
it 'should create jp2 when given a JPEG' do
|
163
|
+
generate_test_image(TEST_JPEG_INPUT_FILE)
|
164
|
+
expect(File).to exist TEST_JPEG_INPUT_FILE
|
165
|
+
expect(File).to_not exist TEST_JP2_OUTPUT_FILE
|
166
|
+
@ai = Assembly::Image.new(TEST_JPEG_INPUT_FILE)
|
167
|
+
result = @ai.create_jp2(output: TEST_JP2_OUTPUT_FILE)
|
168
|
+
# Indicates a temp tiff was created.
|
169
|
+
expect(@ai.tmp_path).not_to be_nil
|
170
|
+
expect(File).not_to exist @ai.tmp_path
|
171
|
+
expect(result).to be_a_kind_of Assembly::Image
|
172
|
+
expect(result.path).to eq TEST_JP2_OUTPUT_FILE
|
173
|
+
expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
|
174
|
+
end
|
175
|
+
|
145
176
|
it 'should not run if you specify a bogus tmp folder' do
|
146
|
-
generate_test_image(
|
147
|
-
bogus_folder='/crapsticks'
|
148
|
-
expect(File).to exist
|
177
|
+
generate_test_image(TEST_JPEG_INPUT_FILE)
|
178
|
+
bogus_folder = '/crapsticks'
|
179
|
+
expect(File).to exist TEST_JPEG_INPUT_FILE
|
149
180
|
expect(File).to_not exist bogus_folder
|
150
|
-
@ai = Assembly::Image.new(
|
151
|
-
expect { @ai.create_jp2(:
|
181
|
+
@ai = Assembly::Image.new(TEST_JPEG_INPUT_FILE)
|
182
|
+
expect { @ai.create_jp2(tmp_folder: bogus_folder) }.to raise_error
|
152
183
|
end
|
153
184
|
|
154
185
|
it 'should create a jp2 and preserve the temporary file if specified' do
|
155
|
-
generate_test_image(
|
156
|
-
expect(File).to exist
|
157
|
-
@ai = Assembly::Image.new(
|
158
|
-
result
|
186
|
+
generate_test_image(TEST_JPEG_INPUT_FILE)
|
187
|
+
expect(File).to exist TEST_JPEG_INPUT_FILE
|
188
|
+
@ai = Assembly::Image.new(TEST_JPEG_INPUT_FILE)
|
189
|
+
result = @ai.create_jp2(output: TEST_JP2_OUTPUT_FILE, preserve_tmp_source: true)
|
190
|
+
# Indicates a temp tiff was created.
|
191
|
+
expect(@ai.tmp_path).not_to be_nil
|
192
|
+
expect(File).to exist @ai.tmp_path
|
159
193
|
expect(result).to be_a_kind_of Assembly::Image
|
160
194
|
expect(result.path).to eq TEST_JP2_OUTPUT_FILE
|
161
195
|
expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
|
162
|
-
expect(
|
163
|
-
expect(File.exists?(@ai.tmp_path)).to be true
|
196
|
+
expect(File.exist?(@ai.tmp_path)).to be true
|
164
197
|
end
|
165
198
|
|
166
199
|
it 'should create jp2 of the same filename and in the same location as the input if no output file is specified, and should cleanup tmp file' do
|
167
200
|
generate_test_image(TEST_TIF_INPUT_FILE)
|
168
201
|
expect(File).to exist TEST_TIF_INPUT_FILE
|
169
|
-
expect(File.
|
202
|
+
expect(File.exist?(TEST_JP2_INPUT_FILE)).to be false
|
170
203
|
@ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
|
171
|
-
result
|
204
|
+
result = @ai.create_jp2
|
172
205
|
expect(result).to be_a_kind_of Assembly::Image
|
173
206
|
expect(result.path).to eq TEST_JP2_INPUT_FILE
|
174
207
|
expect(TEST_JP2_INPUT_FILE).to be_a_jp2
|
175
208
|
expect(result.exif.colorspace).to eq 'sRGB'
|
176
|
-
expect(
|
177
|
-
end
|
178
|
-
|
179
|
-
it 'should create jp2 from input JPEG of the same filename and in the same location as the input if no output file is specified, and should cleanup tmp file' do
|
180
|
-
generate_test_image(TEST_JPEG_INPUT_FILE)
|
181
|
-
expect(File).to exist TEST_JPEG_INPUT_FILE
|
182
|
-
expect(File).to_not exist TEST_JP2_INPUT_FILE
|
183
|
-
@ai = Assembly::Image.new(TEST_JPEG_INPUT_FILE)
|
184
|
-
result=@ai.create_jp2
|
185
|
-
expect(result).to be_a_kind_of Assembly::Image
|
186
|
-
expect(result.path).to eq TEST_JP2_INPUT_FILE
|
187
|
-
expect(TEST_JP2_INPUT_FILE).to be_a_jp2
|
188
|
-
expect(File.exists?(@ai.tmp_path)).to be false
|
209
|
+
expect(@ai.tmp_path).to be_nil
|
189
210
|
end
|
190
211
|
|
191
212
|
it 'should recreate jp2 if the output file exists and if you allow overwriting' do
|
@@ -194,7 +215,7 @@ describe Assembly::Image do
|
|
194
215
|
expect(File).to exist TEST_TIF_INPUT_FILE
|
195
216
|
expect(File).to exist TEST_JP2_OUTPUT_FILE
|
196
217
|
@ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
|
197
|
-
result
|
218
|
+
result = @ai.create_jp2(output: TEST_JP2_OUTPUT_FILE, overwrite: true)
|
198
219
|
expect(result).to be_a_kind_of Assembly::Image
|
199
220
|
expect(result.path).to eq TEST_JP2_OUTPUT_FILE
|
200
221
|
expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
|
@@ -206,5 +227,5 @@ describe Assembly::Image do
|
|
206
227
|
remove_files(TEST_INPUT_DIR)
|
207
228
|
remove_files(TEST_OUTPUT_DIR)
|
208
229
|
end
|
209
|
-
|
210
230
|
end
|
231
|
+
# rubocop:enable Metrics/BlockLength
|
data/spec/images_spec.rb
CHANGED
@@ -1,48 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
5
|
+
# rubocop:disable Metrics/BlockLength
|
3
6
|
describe Assembly::Images do
|
4
|
-
|
5
7
|
it 'should not run if no input folder is passed in' do
|
6
|
-
expect{Assembly::Images.batch_generate_jp2('')}.to raise_error
|
8
|
+
expect{ Assembly::Images.batch_generate_jp2('') }.to raise_error
|
7
9
|
end
|
8
10
|
|
9
11
|
it 'should not run if a non-existent input folder is passed in' do
|
10
|
-
expect{Assembly::Images.batch_generate_jp2('/junk/path')}.to raise_error
|
12
|
+
expect{ Assembly::Images.batch_generate_jp2('/junk/path') }.to raise_error
|
11
13
|
end
|
12
14
|
|
13
15
|
it 'should run and batch produe jp2s from input tiffs' do
|
14
|
-
['test1','test2','test3'].each {|image| generate_test_image(File.join(TEST_INPUT_DIR,"#{image}.tif")) }
|
15
|
-
Assembly::Images.batch_generate_jp2(TEST_INPUT_DIR
|
16
|
+
['test1', 'test2', 'test3'].each { |image| generate_test_image(File.join(TEST_INPUT_DIR, "#{image}.tif")) }
|
17
|
+
Assembly::Images.batch_generate_jp2(TEST_INPUT_DIR, output: TEST_OUTPUT_DIR)
|
16
18
|
expect(File.directory?(TEST_OUTPUT_DIR)).to be true
|
17
|
-
['test1','test2','test3'].each {|image| expect(File.join(TEST_OUTPUT_DIR,"#{image}.jp2")).to be_a_jp2 }
|
19
|
+
['test1', 'test2', 'test3'].each { |image| expect(File.join(TEST_OUTPUT_DIR, "#{image}.jp2")).to be_a_jp2 }
|
18
20
|
end
|
19
21
|
|
20
22
|
it 'should run and batch add color profile descriptions input tiffs with no color profile descriptions' do
|
21
|
-
['test1','test2','test3'].each {|image| generate_test_image(File.join(TEST_INPUT_DIR,"#{image}.tif")
|
22
|
-
['test1','test2','test3'].each {|image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR,"#{image}.tif")).exif.profiledescription).to be nil}
|
23
|
-
Assembly::Images.
|
24
|
-
['test1','test2','test3'].each {|image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR,"#{image}.tif")).exif.profiledescription).to eq 'Adobe RGB (1998)'}
|
23
|
+
['test1', 'test2', 'test3'].each { |image| generate_test_image(File.join(TEST_INPUT_DIR, "#{image}.tif"), profile: '') }
|
24
|
+
['test1', 'test2', 'test3'].each { |image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR, "#{image}.tif")).exif.profiledescription).to be nil }
|
25
|
+
Assembly::Images.batch_add_exif_profile_descr(TEST_INPUT_DIR, 'Adobe RGB 1998')
|
26
|
+
['test1', 'test2', 'test3'].each { |image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR, "#{image}.tif")).exif.profiledescription).to eq 'Adobe RGB (1998)' }
|
25
27
|
end
|
26
28
|
|
27
29
|
it 'should run and batch add color profile descriptions input tiffs, forcing over existing color profile descriptions' do
|
28
|
-
['test1','test2','test3'].each {|image| generate_test_image(File.join(TEST_INPUT_DIR,"#{image}.tif")) }
|
29
|
-
['test1','test2','test3'].each {|image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR,"#{image}.tif")).exif.profiledescription).to eq
|
30
|
-
Assembly::Images.
|
31
|
-
['test1','test2','test3'].each {|image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR,"#{image}.tif")).exif.profiledescription).to eq
|
30
|
+
['test1', 'test2', 'test3'].each { |image| generate_test_image(File.join(TEST_INPUT_DIR, "#{image}.tif")) }
|
31
|
+
['test1', 'test2', 'test3'].each { |image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR, "#{image}.tif")).exif.profiledescription).to eq 'sRGB IEC61966-2.1' }
|
32
|
+
Assembly::Images.batch_add_exif_profile_descr(TEST_INPUT_DIR, 'Adobe RGB 1998', force: true) # force overwrite
|
33
|
+
['test1', 'test2', 'test3'].each { |image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR, "#{image}.tif")).exif.profiledescription).to eq 'Adobe RGB (1998)' }
|
32
34
|
end
|
33
35
|
|
34
36
|
it 'should run and batch add color profile descriptions input tiffs, not overwriting existing color profile descriptions' do
|
35
|
-
['test1','test2','test3'].each {|image| generate_test_image(File.join(TEST_INPUT_DIR,"#{image}.tif")) }
|
36
|
-
['test1','test2','test3'].each {|image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR,"#{image}.tif")).exif.profiledescription).to eq
|
37
|
-
Assembly::Images.
|
38
|
-
['test1','test2','test3'].each {|image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR,"#{image}.tif")).exif.profiledescription).to eq
|
37
|
+
['test1', 'test2', 'test3'].each { |image| generate_test_image(File.join(TEST_INPUT_DIR, "#{image}.tif")) }
|
38
|
+
['test1', 'test2', 'test3'].each { |image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR, "#{image}.tif")).exif.profiledescription).to eq 'sRGB IEC61966-2.1' }
|
39
|
+
Assembly::Images.batch_add_exif_profile_descr(TEST_INPUT_DIR, 'Adobe RGB 1998') # do not force overwrite
|
40
|
+
['test1', 'test2', 'test3'].each { |image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR, "#{image}.tif")).exif.profiledescription).to eq 'sRGB IEC61966-2.1' }
|
39
41
|
end
|
40
42
|
|
41
|
-
|
42
43
|
after(:each) do
|
43
44
|
# after each test, empty out the input and output test directories
|
44
45
|
remove_files(TEST_INPUT_DIR)
|
45
46
|
remove_files(TEST_OUTPUT_DIR)
|
46
47
|
end
|
47
|
-
|
48
48
|
end
|
49
|
+
# rubocop:enable Metrics/BlockLength
|
data/spec/spec_helper.rb
CHANGED
@@ -1,38 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
bootfile = File.expand_path(File.dirname(__FILE__) + '/../config/boot')
|
2
4
|
require bootfile
|
5
|
+
require 'English'
|
3
6
|
|
4
|
-
TEST_INPUT_DIR = File.join(Assembly::PATH_TO_IMAGE_GEM,'spec','test_data','input')
|
5
|
-
TEST_OUTPUT_DIR = File.join(Assembly::PATH_TO_IMAGE_GEM,'spec','test_data','output')
|
6
|
-
TEST_TIF_INPUT_FILE = File.join(TEST_INPUT_DIR,'test.tif')
|
7
|
-
TEST_DPG_TIF_INPUT_FILE
|
8
|
-
TEST_JPEG_INPUT_FILE
|
9
|
-
TEST_JP2_INPUT_FILE = File.join(TEST_INPUT_DIR,'test.jp2')
|
10
|
-
TEST_JP2_OUTPUT_FILE = File.join(TEST_OUTPUT_DIR,'test.jp2')
|
7
|
+
TEST_INPUT_DIR = File.join(Assembly::PATH_TO_IMAGE_GEM, 'spec', 'test_data', 'input')
|
8
|
+
TEST_OUTPUT_DIR = File.join(Assembly::PATH_TO_IMAGE_GEM, 'spec', 'test_data', 'output')
|
9
|
+
TEST_TIF_INPUT_FILE = File.join(TEST_INPUT_DIR, 'test.tif')
|
10
|
+
TEST_DPG_TIF_INPUT_FILE = File.join(TEST_INPUT_DIR, 'oo000oo0001_00_01.tif')
|
11
|
+
TEST_JPEG_INPUT_FILE = File.join(TEST_INPUT_DIR, 'test.jpg')
|
12
|
+
TEST_JP2_INPUT_FILE = File.join(TEST_INPUT_DIR, 'test.jp2')
|
13
|
+
TEST_JP2_OUTPUT_FILE = File.join(TEST_OUTPUT_DIR, 'test.jp2')
|
11
14
|
TEST_DRUID = 'nx288wh8889'
|
12
15
|
|
13
16
|
# generate a sample image file with a specified profile
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
create_command
|
17
|
+
# rubocop:disable Metrics/AbcSize
|
18
|
+
def generate_test_image(file, params = {})
|
19
|
+
color = params[:color] || 'red'
|
20
|
+
profile = params[:profile] || 'sRGBIEC6196621'
|
21
|
+
image_type = params[:image_type]
|
22
|
+
create_command = "convert -size 100x100 xc:#{color} "
|
23
|
+
create_command += ' -profile ' + File.join(Assembly::PATH_TO_IMAGE_GEM, 'profiles', profile + '.icc') + ' ' unless profile == ''
|
20
24
|
create_command += " -type #{image_type} " if image_type
|
21
25
|
create_command += file
|
22
26
|
create_command += ' 2>&1'
|
23
|
-
output = `#{create_command}`
|
24
|
-
unless
|
25
|
-
raise "Failed to create test image #{file} (#{params}): \n#{output}"
|
26
|
-
end
|
27
|
+
output = `#{ create_command }`
|
28
|
+
raise "Failed to create test image #{file} (#{params}): \n#{output}" unless $CHILD_STATUS.success?
|
27
29
|
end
|
30
|
+
# rubocop:enable Metrics/AbcSize
|
28
31
|
|
29
32
|
def remove_files(dir)
|
30
|
-
Dir.foreach(dir)
|
33
|
+
Dir.foreach(dir) do |f|
|
34
|
+
fn = File.join(dir, f)
|
35
|
+
File.delete(fn) if !File.directory?(fn) && File.basename(fn) != '.empty'
|
36
|
+
end
|
31
37
|
end
|
32
38
|
|
33
39
|
RSpec::Matchers.define :be_a_jp2 do
|
34
40
|
match do |actual|
|
35
|
-
if File.
|
41
|
+
if File.exist?(actual)
|
36
42
|
exif = MiniExiftool.new actual
|
37
43
|
exif['mimetype'] == 'image/jp2'
|
38
44
|
else
|
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.7.
|
4
|
+
version: 1.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Mangiafico
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2019-01-25 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: assembly-objectfile
|
@@ -47,6 +47,20 @@ dependencies:
|
|
47
47
|
- - "<"
|
48
48
|
- !ruby/object:Gem::Version
|
49
49
|
version: '3'
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: rake
|
52
|
+
requirement: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
50
64
|
- !ruby/object:Gem::Dependency
|
51
65
|
name: rspec
|
52
66
|
requirement: !ruby/object:Gem::Requirement
|
@@ -62,7 +76,7 @@ dependencies:
|
|
62
76
|
- !ruby/object:Gem::Version
|
63
77
|
version: '3.0'
|
64
78
|
- !ruby/object:Gem::Dependency
|
65
|
-
name:
|
79
|
+
name: rubocop
|
66
80
|
requirement: !ruby/object:Gem::Requirement
|
67
81
|
requirements:
|
68
82
|
- - ">="
|
@@ -76,7 +90,7 @@ dependencies:
|
|
76
90
|
- !ruby/object:Gem::Version
|
77
91
|
version: '0'
|
78
92
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
93
|
+
name: yard
|
80
94
|
requirement: !ruby/object:Gem::Requirement
|
81
95
|
requirements:
|
82
96
|
- - ">="
|
@@ -100,7 +114,6 @@ files:
|
|
100
114
|
- ".gitignore"
|
101
115
|
- ".rspec"
|
102
116
|
- ".rubocop.yml"
|
103
|
-
- ".rubocop_todo.yml"
|
104
117
|
- ".rvmrc.example"
|
105
118
|
- ".travis.yml"
|
106
119
|
- Gemfile
|
@@ -142,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
155
|
version: '0'
|
143
156
|
requirements: []
|
144
157
|
rubyforge_project: assembly-image
|
145
|
-
rubygems_version: 2.6
|
158
|
+
rubygems_version: 2.7.6
|
146
159
|
signing_key:
|
147
160
|
specification_version: 4
|
148
161
|
summary: Ruby immplementation of image services needed to prepare objects to be accessioned
|
data/.rubocop_todo.yml
DELETED
@@ -1,263 +0,0 @@
|
|
1
|
-
# This configuration was generated by
|
2
|
-
# `rubocop --auto-gen-config`
|
3
|
-
# on 2015-12-15 16:19:20 -0800 using RuboCop version 0.35.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: 11
|
10
|
-
# Cop supports --auto-correct.
|
11
|
-
Lint/DeprecatedClassMethods:
|
12
|
-
Exclude:
|
13
|
-
- 'lib/assembly-image/image.rb'
|
14
|
-
- 'spec/image_spec.rb'
|
15
|
-
- 'spec/spec_helper.rb'
|
16
|
-
|
17
|
-
# Offense count: 2
|
18
|
-
Lint/RescueException:
|
19
|
-
Exclude:
|
20
|
-
- 'lib/assembly-image/image.rb'
|
21
|
-
- 'lib/assembly-image/images.rb'
|
22
|
-
|
23
|
-
# Offense count: 2
|
24
|
-
# Cop supports --auto-correct.
|
25
|
-
Lint/StringConversionInInterpolation:
|
26
|
-
Exclude:
|
27
|
-
- 'lib/assembly-image/image.rb'
|
28
|
-
|
29
|
-
# Offense count: 2
|
30
|
-
Lint/UselessAssignment:
|
31
|
-
Exclude:
|
32
|
-
- 'config/boot.rb'
|
33
|
-
- 'lib/assembly-image/images.rb'
|
34
|
-
|
35
|
-
# Offense count: 4
|
36
|
-
Metrics/AbcSize:
|
37
|
-
Max: 87
|
38
|
-
|
39
|
-
# Offense count: 2
|
40
|
-
Metrics/CyclomaticComplexity:
|
41
|
-
Max: 29
|
42
|
-
|
43
|
-
# Offense count: 2
|
44
|
-
# Configuration parameters: AllowURI, URISchemes.
|
45
|
-
Metrics/LineLength:
|
46
|
-
Max: 244
|
47
|
-
|
48
|
-
# Offense count: 5
|
49
|
-
# Configuration parameters: CountComments.
|
50
|
-
Metrics/MethodLength:
|
51
|
-
Max: 59
|
52
|
-
|
53
|
-
# Offense count: 2
|
54
|
-
Metrics/PerceivedComplexity:
|
55
|
-
Max: 30
|
56
|
-
|
57
|
-
# Offense count: 2
|
58
|
-
# Cop supports --auto-correct.
|
59
|
-
# Configuration parameters: IndentWhenRelativeTo, SupportedStyles, IndentOneStep.
|
60
|
-
Style/CaseIndentation:
|
61
|
-
Enabled: false
|
62
|
-
|
63
|
-
# Offense count: 1
|
64
|
-
# Configuration parameters: Exclude.
|
65
|
-
Style/Documentation:
|
66
|
-
Exclude:
|
67
|
-
- 'spec/**/*'
|
68
|
-
- 'test/**/*'
|
69
|
-
- 'lib/assembly-image.rb'
|
70
|
-
|
71
|
-
# Offense count: 1
|
72
|
-
# Cop supports --auto-correct.
|
73
|
-
Style/EmptyLines:
|
74
|
-
Exclude:
|
75
|
-
- 'spec/images_spec.rb'
|
76
|
-
|
77
|
-
# Offense count: 4
|
78
|
-
# Cop supports --auto-correct.
|
79
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
80
|
-
Style/EmptyLinesAroundBlockBody:
|
81
|
-
Exclude:
|
82
|
-
- 'spec/image_spec.rb'
|
83
|
-
- 'spec/images_spec.rb'
|
84
|
-
|
85
|
-
# Offense count: 2
|
86
|
-
# Cop supports --auto-correct.
|
87
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
88
|
-
Style/EmptyLinesAroundClassBody:
|
89
|
-
Exclude:
|
90
|
-
- 'lib/assembly-image/image.rb'
|
91
|
-
|
92
|
-
# Offense count: 2
|
93
|
-
# Cop supports --auto-correct.
|
94
|
-
Style/EmptyLinesAroundMethodBody:
|
95
|
-
Exclude:
|
96
|
-
- 'lib/assembly-image/image.rb'
|
97
|
-
- 'lib/assembly-image/images.rb'
|
98
|
-
|
99
|
-
# Offense count: 13
|
100
|
-
# Cop supports --auto-correct.
|
101
|
-
# Configuration parameters: AllowForAlignment.
|
102
|
-
Style/ExtraSpacing:
|
103
|
-
Exclude:
|
104
|
-
- 'lib/assembly-image/image.rb'
|
105
|
-
- 'spec/images_spec.rb'
|
106
|
-
- 'spec/spec_helper.rb'
|
107
|
-
|
108
|
-
# Offense count: 1
|
109
|
-
# Configuration parameters: Exclude.
|
110
|
-
Style/FileName:
|
111
|
-
Exclude:
|
112
|
-
- 'lib/assembly-image.rb'
|
113
|
-
|
114
|
-
# Offense count: 1
|
115
|
-
# Configuration parameters: MinBodyLength.
|
116
|
-
Style/GuardClause:
|
117
|
-
Exclude:
|
118
|
-
- 'spec/spec_helper.rb'
|
119
|
-
|
120
|
-
# Offense count: 31
|
121
|
-
# Cop supports --auto-correct.
|
122
|
-
# Configuration parameters: SupportedStyles, UseHashRocketsWithSymbolValues.
|
123
|
-
Style/HashSyntax:
|
124
|
-
EnforcedStyle: hash_rockets
|
125
|
-
|
126
|
-
# Offense count: 1
|
127
|
-
# Cop supports --auto-correct.
|
128
|
-
# Configuration parameters: Width.
|
129
|
-
Style/IndentationWidth:
|
130
|
-
Exclude:
|
131
|
-
- 'lib/assembly-image/images.rb'
|
132
|
-
|
133
|
-
# Offense count: 2
|
134
|
-
# Cop supports --auto-correct.
|
135
|
-
Style/LineEndConcatenation:
|
136
|
-
Exclude:
|
137
|
-
- 'lib/assembly-image/image.rb'
|
138
|
-
|
139
|
-
# Offense count: 1
|
140
|
-
# Cop supports --auto-correct.
|
141
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
142
|
-
Style/MethodDefParentheses:
|
143
|
-
Enabled: false
|
144
|
-
|
145
|
-
# Offense count: 2
|
146
|
-
# Cop supports --auto-correct.
|
147
|
-
Style/NegatedIf:
|
148
|
-
Exclude:
|
149
|
-
- 'lib/assembly-image/image.rb'
|
150
|
-
|
151
|
-
# Offense count: 2
|
152
|
-
# Cop supports --auto-correct.
|
153
|
-
# Configuration parameters: PreferredDelimiters.
|
154
|
-
Style/PercentLiteralDelimiters:
|
155
|
-
Exclude:
|
156
|
-
- 'assembly-image.gemspec'
|
157
|
-
|
158
|
-
# Offense count: 1
|
159
|
-
# Cop supports --auto-correct.
|
160
|
-
Style/RedundantBegin:
|
161
|
-
Exclude:
|
162
|
-
- 'lib/assembly-image/image.rb'
|
163
|
-
|
164
|
-
# Offense count: 1
|
165
|
-
# Cop supports --auto-correct.
|
166
|
-
# Configuration parameters: AllowAsExpressionSeparator.
|
167
|
-
Style/Semicolon:
|
168
|
-
Exclude:
|
169
|
-
- 'spec/spec_helper.rb'
|
170
|
-
|
171
|
-
# Offense count: 14
|
172
|
-
# Cop supports --auto-correct.
|
173
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
174
|
-
Style/SignalException:
|
175
|
-
Exclude:
|
176
|
-
- 'lib/assembly-image/image.rb'
|
177
|
-
- 'lib/assembly-image/images.rb'
|
178
|
-
- 'spec/spec_helper.rb'
|
179
|
-
|
180
|
-
# Offense count: 4
|
181
|
-
# Cop supports --auto-correct.
|
182
|
-
Style/SingleSpaceBeforeFirstArg:
|
183
|
-
Exclude:
|
184
|
-
- 'spec/images_spec.rb'
|
185
|
-
|
186
|
-
# Offense count: 93
|
187
|
-
# Cop supports --auto-correct.
|
188
|
-
Style/SpaceAfterComma:
|
189
|
-
Exclude:
|
190
|
-
- 'assembly-image.gemspec'
|
191
|
-
- 'lib/assembly-image/image.rb'
|
192
|
-
- 'lib/assembly-image/images.rb'
|
193
|
-
- 'spec/image_spec.rb'
|
194
|
-
- 'spec/images_spec.rb'
|
195
|
-
- 'spec/spec_helper.rb'
|
196
|
-
|
197
|
-
# Offense count: 4
|
198
|
-
# Cop supports --auto-correct.
|
199
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
200
|
-
Style/SpaceAroundEqualsInParameterDefault:
|
201
|
-
Enabled: false
|
202
|
-
|
203
|
-
# Offense count: 54
|
204
|
-
# Cop supports --auto-correct.
|
205
|
-
# Configuration parameters: MultiSpaceAllowedForOperators.
|
206
|
-
Style/SpaceAroundOperators:
|
207
|
-
Exclude:
|
208
|
-
- 'lib/assembly-image.rb'
|
209
|
-
- 'lib/assembly-image/image.rb'
|
210
|
-
- 'lib/assembly-image/images.rb'
|
211
|
-
- 'spec/image_spec.rb'
|
212
|
-
- 'spec/images_spec.rb'
|
213
|
-
- 'spec/spec_helper.rb'
|
214
|
-
|
215
|
-
# Offense count: 1
|
216
|
-
# Cop supports --auto-correct.
|
217
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
218
|
-
Style/SpaceBeforeBlockBraces:
|
219
|
-
Enabled: false
|
220
|
-
|
221
|
-
# Offense count: 29
|
222
|
-
# Cop supports --auto-correct.
|
223
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
|
224
|
-
Style/SpaceInsideBlockBraces:
|
225
|
-
Enabled: false
|
226
|
-
|
227
|
-
# Offense count: 4
|
228
|
-
# Cop supports --auto-correct.
|
229
|
-
Style/SpaceInsideParens:
|
230
|
-
Exclude:
|
231
|
-
- 'lib/assembly-image/image.rb'
|
232
|
-
|
233
|
-
# Offense count: 5
|
234
|
-
# Cop supports --auto-correct.
|
235
|
-
Style/SpecialGlobalVars:
|
236
|
-
Exclude:
|
237
|
-
- 'lib/assembly-image/image.rb'
|
238
|
-
- 'spec/spec_helper.rb'
|
239
|
-
|
240
|
-
# Offense count: 87
|
241
|
-
# Cop supports --auto-correct.
|
242
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
243
|
-
Style/StringLiterals:
|
244
|
-
Enabled: false
|
245
|
-
|
246
|
-
# Offense count: 1
|
247
|
-
# Cop supports --auto-correct.
|
248
|
-
# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist.
|
249
|
-
Style/TrivialAccessors:
|
250
|
-
Exclude:
|
251
|
-
- 'lib/assembly-image/images.rb'
|
252
|
-
|
253
|
-
# Offense count: 2
|
254
|
-
# Cop supports --auto-correct.
|
255
|
-
Style/UnneededPercentQ:
|
256
|
-
Exclude:
|
257
|
-
- 'assembly-image.gemspec'
|
258
|
-
|
259
|
-
# Offense count: 11
|
260
|
-
# Cop supports --auto-correct.
|
261
|
-
# Configuration parameters: WordRegex.
|
262
|
-
Style/WordArray:
|
263
|
-
MinSize: 3
|