assembly-image 1.6.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b213d29d1bbd1206e9268adeff0d7eba4f9e8b26
4
+ data.tar.gz: 04d757adec2931a7ca42ac9f1cf7f29d6b7dbbc0
5
+ SHA512:
6
+ metadata.gz: 84120410f44ab8fdbf8fe2f7e9943d6209058e6bc4ffc707e149ba134c65b3165e1839ec869bf40b33a823ab395ed7ddfbbb22582f8aee53c2a5befaf8d31b62
7
+ data.tar.gz: fb93f15796aacf0500337b0afe7997cec9d832edb39f23f6078cacaef061c36efb5e85b48b4f40607f2b7d86bd3d58afdd569f33f3babfe1c980de90179b89d6
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ .rvmrc
2
+ *.gem
3
+ .DS_Store
4
+ .bundle
5
+ Gemfile.lock
6
+ config/certs/*
7
+ config/environments/*
8
+ doc/*
9
+ log/*
10
+ pkg/*
11
+ tags
12
+ tmp
13
+ .yardoc/*
data/.rvmrc.example ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3@assembly-image --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in assembly-image.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ #############################################################################################################
2
+ # Copyright (c) 2012-2014 by The Board of Trustees of the Leland Stanford Junior University. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
data/README.rdoc ADDED
@@ -0,0 +1,139 @@
1
+ = Assembly Image Gem
2
+
3
+ ==Overview
4
+ This gem contains classes used by the Stanford University Digital Library to perform
5
+ image operations necessary for accessioning of content.
6
+
7
+ ==Releases
8
+
9
+ - 0.0.1 initial release
10
+ - 0.0.2 small bug fixes
11
+ - 0.0.3 more bug fixes
12
+ - 0.0.4 update jp2 creation method to restrict allowed input types and improve color profile handling
13
+ - 0.0.5 updated documentation to yard format
14
+ - 0.0.6 updated dependency declarations
15
+ - 0.1.0 move color profile extraction to tmp folder instead of gem profiles folder
16
+ - 0.1.1 fix problem with digest require statement
17
+ - 0.1.2 move check for file existence to when an action occurs instead of object initialization; more error checking and messages on command execution
18
+ - 0.1.3 added a filesize attribute to the file object to allow easy access to filesize in bytes
19
+ - 0.1.4 added a new images class that allows you batch create jp2s from an input TIFF directory
20
+ - 0.2.0 added a new method to the image class to handle TIFF "sanity-check" -- can be used to ensure TIFFs are valid before JP2 generation
21
+ - 1.0.0 bump the version number up to an official production level release
22
+ - 1.1.0 remove common object file behaviors to a separate gem and use that gem as a dependency
23
+ - 1.1.1 minor changes to spec tests
24
+ - 1.1.2 remove the addition of 'format' node to file types in content metadata generation
25
+ - 1.1.3 changes to content metadata generation method: change md5 and sha1 computations so that they come from the assembly-objectfile gem, and set preserve/publish/shelve attributes using mimetype defaults
26
+ - 1.2.0 support tiffs that have embedded thumbnails when creating jp2
27
+ - 1.2.1 raise a SecurityError if the user attempts to overwrite an existing jp2 when creating it, to make it easier to catch in assembly
28
+ - 1.2.2 add height and width methods for an image that gets it from exif
29
+ - 1.2.4 prepare for release listing on DLSS release board
30
+ - 1.2.5 small change to use the jp2able method instead of the valid? method when creating jp2s
31
+ - 1.2.6 update how version number is set to make it easier to show
32
+ - 1.3.0 added a new method to the Assembly::Images class to allow for batch adding of color profiles to all tiffs in a directory; allow batch methods to run recursively
33
+ - 1.3.1 remove content metadata generation method and add to assembly-objectfile gem instead
34
+ - 1.3.3 update gemspec to force use of latest assembly-objectfile gem to allow gem to work in Ruby 1.9 projects
35
+ - 1.3.4 update to latest version of lyberteam gems
36
+ - 1.3.5 fix a problem that could occur if there were spaces in input filenames
37
+ - 1.3.6 add new attribute to give you default jp2 filename that will be used
38
+ - 1.3.7 add new attribute to give you default dpg jp2 filename
39
+ - 1.3.8 allow for batch processing of image extensions other than tif
40
+ - 1.3.9 create new methods for getting a color profile from exif and for force adding color profile to a single image
41
+ - 1.4.0 and 1.4.1 set the imagemagick tmp folder location environment variable when creating jp2
42
+ - 1.5.0 allow images with a color profile to have jp2 derivatives generated
43
+ - 1.5.1 relax nokogiri version requirement
44
+ - 1.6.1 bump version number of assembly-objectfile required to fix UTF-8 errors during JP2-create
45
+ - 1.6.2-1.6.3 small change to jp2 generation to try and fix bug with tiffs that have multiple input profile layers
46
+ - 1.6.4 added in some additional checks to try and create jp2s with mismatching exif data
47
+ - 1.6.5 fix problem with lack of extension in incoming tif causing a problem when creating jp2
48
+ - 1.6.7 release to github/rubygems
49
+ ==Notes
50
+
51
+ 1. The gem assumes that the user context in which it is executed has write access to the 'tmp' folder.
52
+ This is because color profiles can be extracted from images during the JP2 creation process, and these profiles need to
53
+ be stored as local files, and it is beneficial to cache them for later usage by images with the same color profile.
54
+ If you know there are color profiles which are commonly used, it is better to capture them in the gem itself in the profile
55
+ folder so they can be re-used and do not need to be extracted.
56
+
57
+ 2. If any errors occur during JP2 generation for any reason, a runtime exception will be thrown with a description of the error.
58
+
59
+ 3. If an image is passed in with a color profile that cannot be determined by examining the exif header data, an exception will be thrown.
60
+ This can commonally occur in basic test TIFs that are black/white and have no profile, so beware during testing.
61
+
62
+ ==Usage
63
+
64
+ To use the JP2 creation method, you first instantiate the image object with an input image and then operate on it.
65
+
66
+ require 'assembly-image'
67
+ input=Assembly::Image.new('/full/path/to/file.tif')
68
+ puts input.exif # this will show you exif header information for the TIF
69
+ output=input.create_jp2(:output=>'/full/path/to/output.jp2') # this will generate a new JP2 in the output location specified
70
+ puts output.exif # this will show you exif header information for the JP2
71
+
72
+ ==Running tests
73
+
74
+ bundle exec rspec spec
75
+
76
+ ==Generate documentation
77
+ To generate documentation into the "doc" folder:
78
+
79
+ yard
80
+
81
+ To keep a local server running with up to date code documentation that you can view in your browser:
82
+
83
+ yard server --reload
84
+
85
+ ==Prerequisites
86
+
87
+ 1. Perl
88
+
89
+ 2. Kakadu Software Binaries - for JP2 generation
90
+
91
+ Download and install demonstration binaries from Kakadu:
92
+ http://www.kakadusoftware.com/index.php?option=com_content&task=view&id=26&Itemid=22
93
+
94
+ Note: The binaries will not work with RHEL 5.x; an RPM for RHEL 5 with
95
+ compatible binaries coming soon.
96
+
97
+ 3. Imagemagick 6.5.4 or higher
98
+
99
+ RHEL 6
100
+
101
+ The version of ImageMagick included with RHEL 6 has all of the dependency libraries included:
102
+
103
+ yum install ImageMagick
104
+
105
+ RHEL 5: (RPM to install with included binaries comming soon)
106
+
107
+ The version of ImageMagic included with RHEL 5 is too old and does not have all the proper binaries included/built
108
+
109
+ Required libraries are:
110
+
111
+ yum install lcms lcms-devel libjpeg \
112
+ libjpeg-devel libpng libpng-devel
113
+
114
+ Required libraries from source:
115
+ * libtiff (version 3.9.4 or higher)
116
+
117
+ Build Imagemagick from source:
118
+ http://www.imagemagick.org/download/ImageMagick.tar.gz
119
+
120
+ Mac users:
121
+
122
+ brew install jasper
123
+ brew install libtiff
124
+ brew install imagemagick --use-tiff --use-jpeg2000
125
+
126
+ 4. Exiftool
127
+
128
+ RHEL: (RPM to install comming soon)
129
+ Download latest version from: http://www.sno.phy.queensu.ca/~phil/exiftool
130
+
131
+ tar -xf Image-ExifTool-#.##.tar.gz
132
+ cd Image-ExifTool-#.##
133
+ perl Makefile.PL
134
+ make test
135
+ sudo make install
136
+
137
+ Mac users:
138
+
139
+ brew install exiftool
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "Run specs"
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
@@ -0,0 +1,30 @@
1
+ $LOAD_PATH.push File.expand_path("../lib", __FILE__)
2
+ require 'assembly-image/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'assembly-image'
6
+ s.version = Assembly::Image::VERSION
7
+ s.authors = ["Peter Mangiafico", "Renzo Sanchez-Silva","Monty Hindman","Tony Calavano"]
8
+ s.email = ["pmangiafico@stanford.edu"]
9
+ s.homepage = ""
10
+ s.summary = %q{Ruby immplementation of image services needed to prepare objects to be accessioned in SULAIR digital library}
11
+ s.description = %q{Contains classes to create derivative image files and perform other image operations}
12
+
13
+ s.rubyforge_project = 'assembly-image'
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ['lib']
19
+
20
+ s.add_dependency 'uuidtools'
21
+ s.add_dependency 'assembly-objectfile', ">= 1.6.4"
22
+ s.add_dependency 'mini_exiftool', "~> 1.6"
23
+ s.add_dependency 'activesupport'
24
+ s.add_dependency 'nokogiri'
25
+
26
+ s.add_development_dependency "rspec", "~> 3.0"
27
+ s.add_development_dependency "yard"
28
+ s.add_development_dependency "rake"
29
+
30
+ end
data/bin/console ADDED
@@ -0,0 +1,8 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'irb'
5
+
6
+ require File.expand_path(File.dirname(__FILE__) + '/../config/boot')
7
+
8
+ IRB.start
data/bin/run_all_tests ADDED
@@ -0,0 +1,3 @@
1
+ #! /bin/bash
2
+
3
+ bundle exec rspec spec
data/config/boot.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+
3
+ environment = ENV['ENVIRONMENT'] ||= 'development'
4
+ project_root = File.expand_path(File.dirname(__FILE__) + '/..')
5
+
6
+ # Load config for current environment.
7
+ $LOAD_PATH.unshift(project_root + '/lib')
8
+
9
+ require 'assembly-image'
@@ -0,0 +1,216 @@
1
+ require 'uuidtools'
2
+ require 'assembly-objectfile'
3
+
4
+ module Assembly
5
+
6
+ # The Image class contains methods to operate on an image.
7
+ class Image
8
+
9
+ # include common behaviors from assembly-objectfile gem
10
+ include Assembly::ObjectFileable
11
+
12
+ # stores the path to the tmp file generated during the JP2 creation process
13
+ attr_accessor :tmp_path
14
+
15
+ # Examines the input image for validity. Used to determine if image is correct and if JP2 generation is likely to succeed.
16
+ # This method is automatically called before you create a jp2 but it can be called separately earlier as a sanity check.
17
+ #
18
+ # @return [boolean] true if image is valid, false if not.
19
+ #
20
+ # Example:
21
+ # source_img=Assembly::ObjectFile.new('/input/path_to_file.tif')
22
+ # puts source_img.valid? # gives true
23
+ def valid?
24
+ valid_image? # behavior is defined in assembly-objectfile gem
25
+ end
26
+
27
+ # Get the image color profile
28
+ #
29
+ # @return [string] image color profile
30
+ # Example:
31
+ # source_img=Assembly::Image.new('/input/path_to_file.tif')
32
+ # puts source_img.profile # gives 'Adobe RGB 1998'
33
+ def profile
34
+ exif.nil? ? nil : exif['profiledescription']
35
+ end
36
+
37
+ # Get the image height from exif data
38
+ #
39
+ # @return [integer] image height in pixels
40
+ # Example:
41
+ # source_img=Assembly::Image.new('/input/path_to_file.tif')
42
+ # puts source_img.height # gives 100
43
+ def height
44
+ exif.imageheight
45
+ end
46
+
47
+ # Get the image width from exif data
48
+ #
49
+ # @return [integer] image height in pixels
50
+ # Example:
51
+ # source_img=Assembly::Image.new('/input/path_to_file.tif')
52
+ # puts source_img.width # gives 100
53
+ def width
54
+ exif.imagewidth
55
+ end
56
+
57
+ # Add an exif color profile descriptions to the image.
58
+ # This is useful if your source TIFFs do not have color profile descriptions in the EXIF data, but you know what it should be.
59
+ # This will allow the images to pass the validaty check and have JP2s created successfully.
60
+ #
61
+ # Note you will need full read/write access to the source path so that new EXIF data can be saved.
62
+ #
63
+ # @param [String] profile_name profile name to be added, current options are 'Adobe RBG 1998','Dot Gain 20%','sRGB IEC61966-2.1'
64
+ #
65
+ # @param [String] force if set to true, force overwrite a color profile description even if it already exists (default: false)
66
+ #
67
+ # Example:
68
+ # source_img=Assembly::Image.new('/input/path_to_file.tif')
69
+ # source_img.add_exif_profile_description('Adobe RGB 1998')
70
+ def add_exif_profile_description(profile_name,force=false)
71
+ begin
72
+ if profile.nil? || force
73
+ input_profile = profile_name.gsub(/[^[:alnum:]]/, '') # remove all non alpha-numeric characters, so we can get to a filename
74
+ path_to_profiles = File.join(Assembly::PATH_TO_IMAGE_GEM,'profiles')
75
+ input_profile_file = File.join(path_to_profiles,"#{input_profile}.icc")
76
+ command="exiftool '-icc_profile<=#{input_profile_file}' #{path}"
77
+ result=`#{command} 2>&1`
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}"
82
+ end
83
+ end
84
+
85
+ # Returns the full default jp2 path and filename that will be created from the given image
86
+ #
87
+ # @return [string] full default jp2 path and filename that will be created from the given image
88
+ # Example:
89
+ # source_img=Assembly::Image.new('/input/path_to_file.tif')
90
+ # puts source_img.jp2_filename # gives /input/path_to_file.jp2
91
+ def jp2_filename
92
+ File.extname(@path).empty? ? "#{@path}.jp2" : @path.gsub(File.extname(@path),'.jp2')
93
+ end
94
+
95
+ # Returns the full DPG equivalent jp2 path and filename that would match with the given image
96
+ #
97
+ # @return [string] full DPG equivalent jp2 path and filename
98
+ # Example:
99
+ # source_img=Assembly::Image.new('/input/path_to_file.tif')
100
+ # puts source_img.jp2_filename # gives /input/path_to_file.jp2
101
+ def dpg_jp2_filename
102
+ jp2_filename.gsub('_00_','_05_')
103
+ end
104
+
105
+ # Create a JP2 file for the current image.
106
+ # Important note: this will not work for multipage TIFFs.
107
+ #
108
+ # @return [Assembly::Image] object containing the generated JP2 file
109
+ #
110
+ # @param [Hash] params Optional parameters specified as a hash, using symbols for options:
111
+ # * :output => path to the output JP2 file (default: mirrors the source file name and path, but with a .jp2 extension)
112
+ # * :overwrite => if set to false, an existing JP2 file with the same name won't be overwritten (default: false)
113
+ # * :tmp_folder => the temporary folder to use when creating the jp2 (default: '/tmp'); also used by imagemagick
114
+ # * :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)
115
+ #
116
+ # Example:
117
+ # source_img=Assembly::Image.new('/input/path_to_file.tif')
118
+ # derivative_img=source_img.create_jp2(:overwrite=>true)
119
+ # puts derivative_img.mimetype # 'image/jp2'
120
+ # puts derivative_image.path # '/input/path_to_file.jp2'
121
+ def create_jp2(params = {})
122
+
123
+ check_for_file
124
+
125
+ raise "input file is not a valid image, or is the wrong mimetype" if !self.jp2able?
126
+
127
+ output = params[:output] || jp2_filename
128
+ overwrite = params[:overwrite] || false
129
+
130
+ raise SecurityError,"output #{output} exists, cannot overwrite" if !overwrite && File.exists?(output)
131
+
132
+ raise SecurityError,"cannot recreate jp2 over itself" if overwrite && mimetype=='image/jp2' && output == @path
133
+
134
+ tmp_folder = params[:tmp_folder] || '/tmp'
135
+ raise "tmp_folder #{tmp_folder} does not exists" unless File.exists?(tmp_folder)
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
+ 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
+
142
+ raise "output profile #{output_profile} invalid" if !File.exists?(output_profile_file)
143
+
144
+ samples_per_pixel=exif['samplesperpixel'].to_s || ""
145
+ bits_per_sample=exif['bitspersample'] || ""
146
+
147
+ path_to_profiles = File.join(Assembly::PATH_TO_IMAGE_GEM,'profiles')
148
+
149
+ if !profile.nil? # if the input color profile exists, contract paths to the profile and setup the command
150
+
151
+ input_profile = profile.gsub(/[^[:alnum:]]/, '') # remove all non alpha-numeric characters, so we can get to a filename
152
+
153
+ # construct a path to the input profile, which might exist either in the gem itself or in the tmp folder
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
157
+
158
+ # if input profile was extracted and does not matches an existing known profile either in the gem or in the tmp folder,
159
+ # we'll issue an imagicmagick command to extract the profile to the tmp folder
160
+ unless File.exists?(input_profile_file)
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
166
+
167
+ profile_conversion_switch = "-profile #{input_profile_file} -profile #{output_profile_file}"
168
+
169
+ else
170
+
171
+ profile_conversion_switch = "" # no conversion needed if input color profile does not exist
172
+
173
+ end
174
+
175
+ # make temp tiff filename
176
+ @tmp_path = "#{tmp_folder}/#{UUIDTools::UUID.random_create.to_s}.tif"
177
+
178
+ options = ""
179
+ case samples_per_pixel
180
+ when "3"
181
+ options += "-type TrueColor"
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?
192
+
193
+ pixdem = width > height ? width : height
194
+ layers = (( Math.log(pixdem) / Math.log(2) ) - ( Math.log(96) / Math.log(2) )).ceil + 1
195
+
196
+ # jp2 creation command
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?
206
+
207
+ File.delete(@tmp_path) unless preserve_tmp_source
208
+
209
+ # create output response object, which is an Assembly::Image type object
210
+ return Assembly::Image.new(output)
211
+
212
+ end
213
+
214
+ end
215
+
216
+ end
@@ -0,0 +1,97 @@
1
+ require 'logger'
2
+ module Assembly
3
+
4
+ # The Images class contains methods to operate on multiple images in batch.
5
+ class Images
6
+
7
+ def self.logger
8
+ @logger ||= Logger.new(STDERR)
9
+ end
10
+
11
+ def self.logger= logger
12
+ @logger = logger
13
+ end
14
+
15
+ # Pass in a source path and have exif color profile descriptions added to all images contained.
16
+ # This is useful if your source TIFFs do not have color profile descriptions in the EXIF data, but you know what it should be.
17
+ # This will allow the images to pass the validty check and have JP2s created successfully.
18
+ #
19
+ # Note you will need full read/write access to the source path so that new EXIF data can be saved.
20
+ #
21
+ # @param [String] source path full path to the directory containing TIFFs
22
+ # @param [String] profile_name profile name to be added, current options are 'Adobe RBG 1998','Dot Gain 20%','sRGB IEC61966-2.1'
23
+ #
24
+ # @param [Hash] params Optional parameters specified as a hash, using symbols for options:
25
+ # * :force => if set to true, force overwrite a color profile description even if it already exists (default: false)
26
+ # * :recusrive => if set to true, directories will be searched recursively for TIFFs from the source specified, false searches the top level only (default: false)
27
+ # * :extension => defines the types of files that will be processed (default '.tif')
28
+ #
29
+ # Example:
30
+ # Assembly::Images.batch_add_exif_profile_description('/full_path_to_tifs','Adobe RGB 1998')
31
+ def self.batch_add_exif_profile_description(source,profile_name,params={})
32
+
33
+ extension = params[:extension] || 'tif'
34
+ recursive = params[:recursive] || false
35
+ force = params[:force] || false
36
+
37
+ raise "Input path does not exist" unless File.directory?(source)
38
+
39
+ logger.debug "Source: #{source}"
40
+
41
+ # iterate over input directory looking for tifs
42
+ pattern = recursive ? "**/*.#{extension}" : "*.#{extension}*"
43
+ Dir.glob(File.join(source,pattern)).each do |file|
44
+ img=Assembly::Image.new(file)
45
+ logger.debug "Processing #{file}"
46
+ img.add_exif_profile_description(profile_name,force)
47
+ end
48
+ return "Complete"
49
+ end
50
+
51
+ # Pass in a source path and get JP2s generate for each tiff that is in the source path
52
+ #
53
+ # If not passed in, the destination will be a "jp2" subfolder within the source folder.
54
+ # Note you will need read access to the source path, and write access to the destination path.
55
+ #
56
+ # @param [String] source path full path to the directory containing TIFFs to be converted to JP2
57
+ #
58
+ # @param [Hash] params Optional parameters specified as a hash, using symbols for options:
59
+ # * :output=>'/full/path_to_jp2' # specifies full path to folder where jp2s will be created (default: jp2 subdirectory from source path)
60
+ # * :overwrite => if set to false, an existing JP2 file with the same name won't be overwritten (default: false)
61
+ # * :recursive => if set to true, directories will be searched recursively for TIFFs from the source specified, false searches the top level only (default: false)
62
+ # * :extension => defines the types of files that will be processed (default '.tif')
63
+ #
64
+ # Example:
65
+ # Assembly::Images.batch_generate_jp2('/full_path_to_tifs')
66
+ def self.batch_generate_jp2(source,params={})
67
+
68
+ raise "Input path does not exist" unless File.directory?(source)
69
+ output = params[:output] || File.join(source,'jp2') # default output directgory is jp2 sub-directory from source
70
+ extension = params[:extension] || 'tif'
71
+ overwrite = params[:overwrite] || false
72
+ recursive = params[:recursive] || false
73
+
74
+ Dir.mkdir(output) unless File.directory?(output) # attemp to make output directory
75
+ raise "Output path does not exist or could not be created" unless File.directory?(output)
76
+
77
+ logger.debug "Source: #{source}"
78
+ logger.debug "Destination: #{output}"
79
+
80
+ pattern = recursive ? "**/*.#{extension}" : "*.#{extension}*"
81
+
82
+ # iterate over input directory looking for tifs
83
+ Dir.glob(File.join(source,pattern)).each do |file|
84
+ source_img=Assembly::Image.new(file)
85
+ 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
86
+ begin
87
+ derivative_img=source_img.create_jp2(:overwrite=>overwrite,:output=>output_img)
88
+ logger.debug "Generated jp2 for #{File.basename(file)}"
89
+ rescue Exception => e
90
+ logger.debug "** Error for #{File.basename(file)}: #{e.message}"
91
+ end
92
+ end
93
+ return 'Complete'
94
+
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,8 @@
1
+ # Main Assembly namespace
2
+ module Assembly
3
+ # Main Image class
4
+ class Image
5
+ # Project version number
6
+ VERSION = "1.6.7"
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Assembly
2
+
3
+ # the path to the gem, used to access profiles stored with the gem
4
+ PATH_TO_IMAGE_GEM = File.expand_path(File.dirname(__FILE__) + '/..')
5
+
6
+ end
7
+
8
+ # auto-include all files in the lib sub-directory directory
9
+ Dir[File.dirname(__FILE__) + '/assembly-image/*.rb'].each {|file| require file unless file=='version.rb'}
Binary file
Binary file
Binary file
@@ -0,0 +1,203 @@
1
+ require 'spec_helper'
2
+
3
+ describe Assembly::Image do
4
+
5
+ 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
+ end
9
+
10
+ it "should indicate the default jp2 filename" do
11
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
12
+ expect(@ai.jp2_filename).to eq TEST_TIF_INPUT_FILE.gsub('.tif','.jp2')
13
+ end
14
+
15
+ it "should indicate the default jp2 filename" do
16
+ @ai = Assembly::Image.new("/path/to/a/file_with_no_extension")
17
+ expect(@ai.jp2_filename).to eq "/path/to/a/file_with_no_extension.jp2"
18
+ end
19
+
20
+ it "should indicate the default DPG jp2 filename" do
21
+ @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_')
23
+ end
24
+
25
+ it "should indicate the default jp2 filename" do
26
+ @ai = Assembly::Image.new("/path/to/a/file_with_no_00_extension")
27
+ expect(@ai.dpg_jp2_filename).to eq "/path/to/a/file_with_no_05_extension.jp2"
28
+ end
29
+
30
+ it "should create jp2 when given an RGB tif" do
31
+ generate_test_image(TEST_TIF_INPUT_FILE)
32
+ expect(File).to exist TEST_TIF_INPUT_FILE
33
+ expect(File).to_not exist TEST_JP2_OUTPUT_FILE
34
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
35
+ result=@ai.create_jp2(:output => TEST_JP2_OUTPUT_FILE)
36
+ expect(result).to be_a_kind_of Assembly::Image
37
+ expect(result.path).to eq TEST_JP2_OUTPUT_FILE
38
+ expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
39
+ expect(result.exif.colorspace).to eq "sRGB"
40
+ @jp2=Assembly::Image.new(TEST_JP2_OUTPUT_FILE)
41
+ expect(@jp2.height).to eq 100
42
+ expect(@jp2.width).to eq 100
43
+ end
44
+
45
+ it "should create grayscale jp2 when given a bitonal tif" do
46
+ generate_test_image(TEST_TIF_INPUT_FILE,:color=>'white',:image_type=>"Bilevel")
47
+ expect(File).to exist TEST_TIF_INPUT_FILE
48
+ expect(File).to_not exist TEST_JP2_OUTPUT_FILE
49
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
50
+ expect(@ai).to have_color_profile
51
+ result=@ai.create_jp2(:output => TEST_JP2_OUTPUT_FILE)
52
+ expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
53
+ expect(result.exif.colorspace).to eq "Grayscale"
54
+ end
55
+
56
+ it "should create color jp2 when given a color tif but bitonal image data (1 channels and 1 bits per pixel)" do
57
+ generate_test_image(TEST_TIF_INPUT_FILE,:color=>'white',:image_type=>"TrueColor",:profile=>'')
58
+ expect(File).to exist TEST_TIF_INPUT_FILE
59
+ expect(File).to_not exist TEST_JP2_OUTPUT_FILE
60
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
61
+ expect(@ai).to_not have_color_profile
62
+ result=@ai.create_jp2(:output => TEST_JP2_OUTPUT_FILE)
63
+ expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
64
+ expect(result.exif.colorspace).to eq "sRGB"
65
+ end
66
+
67
+ it "should create grayscale jp2 when given a graycale tif but with bitonal image data (1 channel and 1 bits per pixel)" do
68
+ generate_test_image(TEST_TIF_INPUT_FILE,:color=>'white',:image_type=>"Grayscale",:profile=>'')
69
+ expect(File).to exist TEST_TIF_INPUT_FILE
70
+ expect(File).to_not exist TEST_JP2_OUTPUT_FILE
71
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
72
+ expect(@ai).to_not have_color_profile
73
+ result=@ai.create_jp2(:output => TEST_JP2_OUTPUT_FILE)
74
+ expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
75
+ expect(result.exif.colorspace).to eq "Grayscale"
76
+ end
77
+
78
+ it "should create color jp2 when given a color tif but with greyscale image data (1 channel and 8 bits per pixel)" do
79
+ generate_test_image(TEST_TIF_INPUT_FILE,:color=>'gray',:image_type=>"TrueColor",:profile=>'')
80
+ expect(File).to exist TEST_TIF_INPUT_FILE
81
+ expect(File).to_not exist TEST_JP2_OUTPUT_FILE
82
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
83
+ expect(@ai).to_not have_color_profile
84
+ result=@ai.create_jp2(:output => TEST_JP2_OUTPUT_FILE)
85
+ expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
86
+ expect(result.exif.colorspace).to eq "sRGB"
87
+ end
88
+
89
+ it "should create a jp2 when the source image has no profile" do
90
+ generate_test_image(TEST_TIF_INPUT_FILE,:profile=>'') # generate a test input with no profile
91
+ expect(File).to exist TEST_TIF_INPUT_FILE
92
+ expect(File).to_not exist TEST_JP2_OUTPUT_FILE
93
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
94
+ expect(@ai).to_not have_color_profile
95
+ expect(@ai).to be_a_valid_image
96
+ expect(@ai).to be_jp2able
97
+ @ai.create_jp2(:output => TEST_JP2_OUTPUT_FILE)
98
+ expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
99
+ end
100
+
101
+ it "should not run if the output file exists and you don't allow overwriting" do
102
+ generate_test_image(TEST_TIF_INPUT_FILE)
103
+ generate_test_image(TEST_JP2_OUTPUT_FILE)
104
+ expect(File).to exist TEST_TIF_INPUT_FILE
105
+ expect(File).to exist TEST_JP2_OUTPUT_FILE
106
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
107
+ expect{@ai.create_jp2(:output => TEST_JP2_OUTPUT_FILE)}.to raise_error(SecurityError)
108
+ end
109
+
110
+ it "should get the correct image height and width" do
111
+ generate_test_image(TEST_TIF_INPUT_FILE)
112
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
113
+ expect(@ai.height).to eq 100
114
+ expect(@ai.width).to eq 100
115
+ end
116
+
117
+ it "should not run if the input file is a jp2" do
118
+ generate_test_image(TEST_JP2_OUTPUT_FILE)
119
+ expect(File).to exist TEST_JP2_OUTPUT_FILE
120
+ @ai = Assembly::Image.new(TEST_JP2_OUTPUT_FILE)
121
+ expect(@ai).to be_valid_image
122
+ expect(@ai).to_not be_jp2able
123
+ expect { @ai.create_jp2 }.to raise_error
124
+ end
125
+
126
+ it "should run if you specify a bogus output profile, because this is not currently an option" do
127
+ generate_test_image(TEST_TIF_INPUT_FILE)
128
+ expect(File).to exist TEST_TIF_INPUT_FILE
129
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
130
+ result=@ai.create_jp2(:output_profile=>'bogusness')
131
+ expect(result).to be_a_kind_of Assembly::Image
132
+ expect(result.path).to eq TEST_JP2_INPUT_FILE
133
+ expect(TEST_JP2_INPUT_FILE).to be_a_jp2
134
+ expect(result.exif.colorspace).to eq "sRGB"
135
+ end
136
+
137
+ it "should not run if you specify a bogus tmp folder" do
138
+ generate_test_image(TEST_TIF_INPUT_FILE)
139
+ bogus_folder='/crapsticks'
140
+ expect(File).to exist TEST_TIF_INPUT_FILE
141
+ expect(File).to_not exist bogus_folder
142
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
143
+ expect { @ai.create_jp2(:tmp_folder=>bogus_folder) }.to raise_error
144
+ end
145
+
146
+ it "should create a jp2 and preserve the temporary file if specified" do
147
+ generate_test_image(TEST_TIF_INPUT_FILE)
148
+ expect(File).to exist TEST_TIF_INPUT_FILE
149
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
150
+ result=@ai.create_jp2(:output => TEST_JP2_OUTPUT_FILE, :preserve_tmp_source=>true)
151
+ expect(result).to be_a_kind_of Assembly::Image
152
+ expect(result.path).to eq TEST_JP2_OUTPUT_FILE
153
+ expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
154
+ expect(result.exif.colorspace).to eq "sRGB"
155
+ expect(File.exists?(@ai.tmp_path)).to be true
156
+ end
157
+
158
+ 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
159
+ generate_test_image(TEST_TIF_INPUT_FILE)
160
+ expect(File).to exist TEST_TIF_INPUT_FILE
161
+ expect(File.exists?(TEST_JP2_INPUT_FILE)).to be false
162
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
163
+ result=@ai.create_jp2
164
+ expect(result).to be_a_kind_of Assembly::Image
165
+ expect(result.path).to eq TEST_JP2_INPUT_FILE
166
+ expect(TEST_JP2_INPUT_FILE).to be_a_jp2
167
+ expect(result.exif.colorspace).to eq "sRGB"
168
+ expect(File.exists?(@ai.tmp_path)).to be false
169
+ end
170
+
171
+ 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
172
+ generate_test_image(TEST_JPEG_INPUT_FILE)
173
+ expect(File).to exist TEST_JPEG_INPUT_FILE
174
+ expect(File).to_not exist TEST_JP2_INPUT_FILE
175
+ @ai = Assembly::Image.new(TEST_JPEG_INPUT_FILE)
176
+ result=@ai.create_jp2
177
+ expect(result).to be_a_kind_of Assembly::Image
178
+ expect(result.path).to eq TEST_JP2_INPUT_FILE
179
+ expect(TEST_JP2_INPUT_FILE).to be_a_jp2
180
+ expect(result.exif.colorspace).to eq "sRGB"
181
+ expect(File.exists?(@ai.tmp_path)).to be false
182
+ end
183
+
184
+ it "should recreate jp2 if the output file exists and if you allow overwriting" do
185
+ generate_test_image(TEST_TIF_INPUT_FILE)
186
+ generate_test_image(TEST_JP2_OUTPUT_FILE)
187
+ expect(File).to exist TEST_TIF_INPUT_FILE
188
+ expect(File).to exist TEST_JP2_OUTPUT_FILE
189
+ @ai = Assembly::Image.new(TEST_TIF_INPUT_FILE)
190
+ result=@ai.create_jp2(:output => TEST_JP2_OUTPUT_FILE,:overwrite => true)
191
+ expect(result).to be_a_kind_of Assembly::Image
192
+ expect(result.path).to eq TEST_JP2_OUTPUT_FILE
193
+ expect(TEST_JP2_OUTPUT_FILE).to be_a_jp2
194
+ expect(result.exif.colorspace).to eq "sRGB"
195
+ end
196
+
197
+ after(:each) do
198
+ # after each test, empty out the input and output test directories
199
+ remove_files(TEST_INPUT_DIR)
200
+ remove_files(TEST_OUTPUT_DIR)
201
+ end
202
+
203
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Assembly::Images do
4
+
5
+ it "should not run if no input folder is passed in" do
6
+ expect{Assembly::Images.batch_generate_jp2('')}.to raise_error
7
+ end
8
+
9
+ 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
11
+ end
12
+
13
+ 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,:output=>TEST_OUTPUT_DIR)
16
+ 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 }
18
+ end
19
+
20
+ 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"),:profile=>'') }
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.batch_add_exif_profile_description(TEST_INPUT_DIR,'Adobe RGB 1998')
24
+ ['test1','test2','test3'].each {|image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR,"#{image}.tif")).exif.profiledescription).to eq 'Adobe RGB (1998)'}
25
+ end
26
+
27
+ 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 'sRGB IEC61966-2.1'}
30
+ Assembly::Images.batch_add_exif_profile_description(TEST_INPUT_DIR,'Adobe RGB 1998',:force=>true) # force overwrite
31
+ ['test1','test2','test3'].each {|image| expect(Assembly::Image.new(File.join(TEST_INPUT_DIR,"#{image}.tif")).exif.profiledescription).to eq 'Adobe RGB (1998)'}
32
+ end
33
+
34
+ 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 'sRGB IEC61966-2.1'}
37
+ Assembly::Images.batch_add_exif_profile_description(TEST_INPUT_DIR,'Adobe RGB 1998') # do not force overwrite
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
+ end
40
+
41
+
42
+ after(:each) do
43
+ # after each test, empty out the input and output test directories
44
+ remove_files(TEST_INPUT_DIR)
45
+ remove_files(TEST_OUTPUT_DIR)
46
+ end
47
+
48
+ end
@@ -0,0 +1,42 @@
1
+ bootfile = File.expand_path(File.dirname(__FILE__) + '/../config/boot')
2
+ require bootfile
3
+
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 = File.join(TEST_INPUT_DIR,'oo000oo0001_00_01.tif')
8
+ TEST_JPEG_INPUT_FILE = File.join(TEST_INPUT_DIR,'test.jpg')
9
+ TEST_JP2_INPUT_FILE = File.join(TEST_INPUT_DIR,'test.jp2')
10
+ TEST_JP2_OUTPUT_FILE = File.join(TEST_OUTPUT_DIR,'test.jp2')
11
+ TEST_DRUID = "nx288wh8889"
12
+
13
+ # generate a sample image file with a specified profile
14
+ def generate_test_image(file,params={})
15
+ color=params[:color] || 'red'
16
+ profile=params[:profile] || 'sRGBIEC6196621'
17
+ image_type=params[:image_type]
18
+ create_command="convert -size 100x100 xc:#{color} "
19
+ create_command += " -profile " + File.join(Assembly::PATH_TO_IMAGE_GEM,'profiles',profile+'.icc') + " " unless profile == ''
20
+ create_command += " -type #{image_type} " if image_type
21
+ create_command += file
22
+ create_command += " 2>&1"
23
+ output = `#{create_command}`
24
+ unless $?.success?
25
+ raise "Failed to create test image #{file} (#{params}): \n#{output}"
26
+ end
27
+ end
28
+
29
+ def remove_files(dir)
30
+ Dir.foreach(dir) {|f| fn = File.join(dir, f); File.delete(fn) if !File.directory?(fn) && File.basename(fn) != '.empty'}
31
+ end
32
+
33
+ RSpec::Matchers.define :be_a_jp2 do
34
+ match do |actual|
35
+ if File.exists?(actual)
36
+ exif = MiniExiftool.new actual
37
+ exif['mimetype'] == 'image/jp2'
38
+ else
39
+ false
40
+ end
41
+ end
42
+ end
File without changes
File without changes
metadata ADDED
@@ -0,0 +1,190 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: assembly-image
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.6.7
5
+ platform: ruby
6
+ authors:
7
+ - Peter Mangiafico
8
+ - Renzo Sanchez-Silva
9
+ - Monty Hindman
10
+ - Tony Calavano
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2014-07-25 00:00:00.000000000 Z
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
+ - !ruby/object:Gem::Dependency
31
+ name: assembly-objectfile
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 1.6.4
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.6.4
44
+ - !ruby/object:Gem::Dependency
45
+ name: mini_exiftool
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - "~>"
49
+ - !ruby/object:Gem::Version
50
+ version: '1.6'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '1.6'
58
+ - !ruby/object:Gem::Dependency
59
+ name: activesupport
60
+ requirement: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ - !ruby/object:Gem::Dependency
73
+ name: nokogiri
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ type: :runtime
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ - !ruby/object:Gem::Dependency
87
+ name: rspec
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - "~>"
91
+ - !ruby/object:Gem::Version
92
+ version: '3.0'
93
+ type: :development
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '3.0'
100
+ - !ruby/object:Gem::Dependency
101
+ name: yard
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ type: :development
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ - !ruby/object:Gem::Dependency
115
+ name: rake
116
+ requirement: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ description: Contains classes to create derivative image files and perform other image
129
+ operations
130
+ email:
131
+ - pmangiafico@stanford.edu
132
+ executables:
133
+ - console
134
+ - run_all_tests
135
+ extensions: []
136
+ extra_rdoc_files: []
137
+ files:
138
+ - ".gitignore"
139
+ - ".rvmrc.example"
140
+ - Gemfile
141
+ - LICENSE
142
+ - README.rdoc
143
+ - Rakefile
144
+ - assembly-image.gemspec
145
+ - bin/console
146
+ - bin/run_all_tests
147
+ - config/boot.rb
148
+ - lib/assembly-image.rb
149
+ - lib/assembly-image/image.rb
150
+ - lib/assembly-image/images.rb
151
+ - lib/assembly-image/version.rb
152
+ - profiles/AdobeRGB1998.icc
153
+ - profiles/DotGain20.icc
154
+ - profiles/sRGBIEC6196621.icc
155
+ - spec/image_spec.rb
156
+ - spec/images_spec.rb
157
+ - spec/spec_helper.rb
158
+ - spec/test_data/input/.empty
159
+ - spec/test_data/output/.empty
160
+ homepage: ''
161
+ licenses: []
162
+ metadata: {}
163
+ post_install_message:
164
+ rdoc_options: []
165
+ require_paths:
166
+ - lib
167
+ required_ruby_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ required_rubygems_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ requirements: []
178
+ rubyforge_project: assembly-image
179
+ rubygems_version: 2.2.2
180
+ signing_key:
181
+ specification_version: 4
182
+ summary: Ruby immplementation of image services needed to prepare objects to be accessioned
183
+ in SULAIR digital library
184
+ test_files:
185
+ - spec/image_spec.rb
186
+ - spec/images_spec.rb
187
+ - spec/spec_helper.rb
188
+ - spec/test_data/input/.empty
189
+ - spec/test_data/output/.empty
190
+ has_rdoc: