wax_iiif 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +25 -0
  4. data/.travis.yml +2 -2
  5. data/Gemfile +3 -2
  6. data/README.md +4 -4
  7. data/lib/wax_iiif.rb +34 -44
  8. data/lib/wax_iiif/base_properties.rb +90 -0
  9. data/lib/wax_iiif/builder.rb +252 -0
  10. data/lib/wax_iiif/collection.rb +58 -0
  11. data/lib/{iiif_s3 → wax_iiif}/config.rb +46 -60
  12. data/lib/{iiif_s3 → wax_iiif}/errors.rb +6 -12
  13. data/lib/{iiif_s3 → wax_iiif}/full_image.rb +3 -8
  14. data/lib/wax_iiif/image_info.rb +89 -0
  15. data/lib/{iiif_s3 → wax_iiif}/image_record.rb +48 -63
  16. data/lib/{iiif_s3 → wax_iiif}/image_tile.rb +8 -14
  17. data/lib/{iiif_s3 → wax_iiif}/image_variant.rb +20 -38
  18. data/lib/wax_iiif/manifest.rb +151 -0
  19. data/lib/{iiif_s3 → wax_iiif}/thumbnail.rb +5 -9
  20. data/lib/{iiif_s3 → wax_iiif}/utilities.rb +5 -5
  21. data/lib/{iiif_s3 → wax_iiif}/utilities/helpers.rb +18 -48
  22. data/lib/{iiif_s3 → wax_iiif}/utilities/pdf_splitter.rb +20 -23
  23. data/spec/base_properties_spec.rb +8 -12
  24. data/spec/shared_contexts.rb +28 -92
  25. data/spec/spec_helper.rb +3 -3
  26. data/spec/wax_iiif/builder_spec.rb +143 -0
  27. data/spec/wax_iiif/collection_spec.rb +53 -0
  28. data/spec/wax_iiif/config_spec.rb +15 -0
  29. data/spec/wax_iiif/image_info_spec.rb +57 -0
  30. data/spec/wax_iiif/image_record_spec.rb +82 -0
  31. data/spec/wax_iiif/image_variant_spec.rb +66 -0
  32. data/spec/wax_iiif/manifest_spec.rb +97 -0
  33. data/spec/wax_iiif/utilities/pdf_splitter_spec.rb +14 -0
  34. data/wax_iiif.gemspec +15 -19
  35. metadata +52 -97
  36. data/Guardfile +0 -10
  37. data/Rakefile +0 -24
  38. data/lib/iiif_s3/base_properties.rb +0 -95
  39. data/lib/iiif_s3/builder.rb +0 -241
  40. data/lib/iiif_s3/collection.rb +0 -61
  41. data/lib/iiif_s3/image_info.rb +0 -96
  42. data/lib/iiif_s3/manifest.rb +0 -151
  43. data/lib/iiif_s3/version.rb +0 -5
  44. data/spec/iiif_s3/builder_spec.rb +0 -152
  45. data/spec/iiif_s3/collection_spec.rb +0 -68
  46. data/spec/iiif_s3/config_spec.rb +0 -15
  47. data/spec/iiif_s3/image_info_spec.rb +0 -57
  48. data/spec/iiif_s3/image_record_spec.rb +0 -96
  49. data/spec/iiif_s3/image_variant_spec.rb +0 -68
  50. data/spec/iiif_s3/manifest_spec.rb +0 -97
  51. data/spec/iiif_s3/utilities/pdf_splitter_spec.rb +0 -17
  52. data/test.rb +0 -77
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31844c9c4c8aa58c1e5e940fd0bc447c073e0b4e1e5bf8f7dc77970eeaac95b5
4
- data.tar.gz: d17b64b8d0f9a6c69340128571128c74bb44c26fb119911aff496dd71a4abc5f
3
+ metadata.gz: b8e8bfe689315b674d1af11bb292df7b42c6da7dcdaa4fe277b746ab2fcacc5c
4
+ data.tar.gz: 787041b5e001e26094254a123bf1d42327e1a2ec1d4c7af729f4b1aabb432318
5
5
  SHA512:
6
- metadata.gz: b8b751aaa0cc21122743f4a2a6f7d166cac8cc7bb36942c631cae2343d382973fe2400282dc1c9e884dc4b9b4902ef8b42fa50a214c69b315a0168c29390b334
7
- data.tar.gz: 7ee23f85b57d3ee86abe9002220b73a5138a950dc94406499d2fa59bd7824c56cab91682cd6dc94d8aa311a185e28e774ea2c09e139269c9866324eb5ae0cc15
6
+ metadata.gz: 3bed76dcd0835a29fcbf74eb01c38c4980d91af269eabde4d5f6535c058a2e81e4e7a2252a6b2d24c7c9029d142baf8600d6179ae3db2de95622682ea5a6acfe
7
+ data.tar.gz: 15683183c49c2968751abb425cc0d75a4b42d7d21ef7d11a0725b4cddc991079324bf3cf69d4ea9e330a81faf0b05303bd7c92ae827bd5a766eff7683b90d38d
data/.gitignore CHANGED
@@ -20,6 +20,7 @@ tmp
20
20
  *.o
21
21
  *.a
22
22
  mkmf.log
23
+ temp
23
24
 
24
25
  .env
25
26
 
@@ -0,0 +1,25 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4
3
+ Exclude: ['spec/**/*']
4
+ Metrics/LineLength:
5
+ IgnoredPatterns: ['raise', 'puts', '#', '@', 'spec']
6
+ Style/FrozenStringLiteralComment:
7
+ Enabled: false
8
+ Style/RedundantSelf:
9
+ Enabled: false
10
+ Metrics/MethodLength:
11
+ Enabled: false
12
+ Style/DoubleNegation:
13
+ Enabled: false
14
+ Metrics/AbcSize:
15
+ Enabled: false
16
+ Metrics/CyclomaticComplexity:
17
+ Enabled: false
18
+ Metrics/PerceivedComplexity:
19
+ Enabled: false
20
+ Metrics/ClassLength:
21
+ Enabled: false
22
+ Layout/EmptyLineAfterGuardClause:
23
+ Enabled: false
24
+ Lint/UriEscapeUnescape:
25
+ Enabled: false
@@ -1,11 +1,11 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2
4
- - 2.3
5
3
  - 2.4
4
+ - 2.5
6
5
  addons:
7
6
  apt:
8
7
  packages:
9
8
  - ghostscript
10
9
  script:
10
+ - bundle exec rubocop
11
11
  - bundle exec rspec
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in wax_iiif.gemspec
4
2
  gemspec
3
+
4
+ gem 'rubocop', '0.59.0', require: false
5
+ gem 'yard', require: false
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # wax_iiif
2
- [![Build Status](https://travis-ci.org/mnyrop/wax_iiif.svg?branch=master)](https://travis-ci.org/mnyrop/wax_iiif) [![Dependency Status](https://gemnasium.com/badges/github.com/mnyrop/wax_iiif.svg)](https://gemnasium.com/github.com/mnyrop/wax_iiif) [![Maintainability](https://api.codeclimate.com/v1/badges/3eb2fcf5ae47e7b6d686/maintainability)](https://codeclimate.com/github/mnyrop/wax_iiif/maintainability)
2
+ [![Gem Version](https://badge.fury.io/rb/wax_iiif.svg)](https://badge.fury.io/rb/wax_iiif) [![Build Status](https://travis-ci.org/mnyrop/wax_iiif.svg?branch=master)](https://travis-ci.org/mnyrop/wax_iiif) [![Maintainability](https://api.codeclimate.com/v1/badges/3eb2fcf5ae47e7b6d686/maintainability)](https://codeclimate.com/github/mnyrop/wax_iiif/maintainability)
3
3
 
4
- This fork is TRULY just a copy of the [iiif_s3 gem](https://github.com/cmoa/iiif_s3) with all the s3 dependencies and functionality removed!
4
+ ![License](https://img.shields.io/badge/license-MIT-green.svg) [![docs](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](https://www.rubydoc.info/github/minicomp/wax_iiif/)
5
5
 
6
- It enables the static creation of IIIF derivatives (level 0) for static exhibtion sites with [wax](https://minicomp.github.io/wax/).
6
+ This fork is *mostly* a copy of the [iiif_s3 gem](https://github.com/cmoa/iiif_s3) with all the s3 dependencies and functionality removed. It creates level 0 IIIF derivatives for static exhibition sites with [Minicomp/Wax](https://minicomp.github.io/wax/) via [Wax_Tasks](https://minicomp.github.io/wax_tasks/).
7
7
 
8
- For credit and documentation, head over to [iiif_s3](https://github.com/cmoa/iiif_s3).
8
+ Documentation for using `wax_iiif` without `wax_tasks` is forthcoming. In the meantime, check out [rubydoc](https://www.rubydoc.info/gems/wax_iiif).
@@ -1,83 +1,73 @@
1
1
  require 'csv'
2
2
  require 'json'
3
3
 
4
- require "iiif_s3/version"
5
- require "iiif_s3/errors"
6
- require "iiif_s3/base_properties"
7
- require "iiif_s3/image_record"
8
- require "iiif_s3/builder"
9
- require "iiif_s3/manifest"
10
- require "iiif_s3/config"
11
- require "iiif_s3/collection"
12
- require "iiif_s3/image_variant"
13
- require "iiif_s3/thumbnail"
14
- require "iiif_s3/image_tile"
15
- require "iiif_s3/full_image"
16
- require "iiif_s3/image_info"
17
- require "iiif_s3/utilities"
4
+ require_relative 'wax_iiif/errors'
5
+ require_relative 'wax_iiif/base_properties'
6
+ require_relative 'wax_iiif/image_record'
7
+ require_relative 'wax_iiif/builder'
8
+ require_relative 'wax_iiif/manifest'
9
+ require_relative 'wax_iiif/config'
10
+ require_relative 'wax_iiif/collection'
11
+ require_relative 'wax_iiif/image_variant'
12
+ require_relative 'wax_iiif/thumbnail'
13
+ require_relative 'wax_iiif/image_tile'
14
+ require_relative 'wax_iiif/full_image'
15
+ require_relative 'wax_iiif/image_info'
16
+ require_relative 'wax_iiif/utilities'
18
17
 
19
- # Module IiifS3 is a tool for generating IIIF resources from a set of files.
18
+ # Module WaxIiif is a tool for generating IIIF resources from a set of files.
20
19
  # It's designed to support the IIIF level 0 profile, and generates entirely static files.
21
20
  #
22
21
  # @author David Newbury <david.newbury@gmail.com>
23
22
  #
24
- module IiifS3
25
-
26
-
23
+ module WaxIiif
27
24
  #--------------------------------------------------------------------------
28
25
  # CONSTANTS
29
26
  #--------------------------------------------------------------------------
30
27
 
31
-
32
28
  # @return [String] The URI of the presentation context for the IIIF V.2
33
- PRESENTATION_CONTEXT = "http://iiif.io/api/presentation/2/context.json"
29
+ PRESENTATION_CONTEXT = 'http://iiif.io/api/presentation/2/context.json'.freeze
34
30
  # @return [String] The URI of the image context for the IIIF V.2
35
- IMAGE_CONTEXT = "http://iiif.io/api/image/2/context.json"
31
+ IMAGE_CONTEXT = 'http://iiif.io/api/image/2/context.json'.freeze
36
32
  # @return [String] The URI of the image protocol for IIIF
37
- IMAGE_PROTOCOL = "http://iiif.io/api/image"
33
+ IMAGE_PROTOCOL = 'http://iiif.io/api/image'.freeze
38
34
  # @return [String] The URI of the Level 0 profile for the IIIF V.2
39
- LEVEL_0 = "http://iiif.io/api/image/2/level0.json"
35
+ LEVEL_0 = 'http://iiif.io/api/image/2/level0.json'.freeze
40
36
  # @return [String] The IIIF default type for a sequence.
41
- SEQUENCE_TYPE = "sc:Sequence"
37
+ SEQUENCE_TYPE = 'sc:Sequence'.freeze
42
38
  # @return [String] The IIIF default type for a canvas
43
- CANVAS_TYPE = "sc:Canvas"
39
+ CANVAS_TYPE = 'sc:Canvas'.freeze
44
40
  # @return [String] The IIIF default type for a annotation.
45
- ANNOTATION_TYPE = "oa:Annotation"
41
+ ANNOTATION_TYPE = 'oa:Annotation'.freeze
46
42
  # @return [String] The IIIF default type for an image.
47
- IMAGE_TYPE = "dcterms:Image"
43
+ IMAGE_TYPE = 'dcterms:Image'.freeze
48
44
  # @return [String] The default label for a canvas without a specified name.
49
- MOTIVATION = "sc:painting"
45
+ MOTIVATION = 'sc:painting'.freeze
50
46
  # @return [String] The default label for a canvas without a specified name.
51
- DEFAULT_CANVAS_LABEL = "front"
47
+ DEFAULT_CANVAS_LABEL = 'front'.freeze
52
48
  # @return [String] The default name for a sequence without a specified name.
53
- DEFAULT_SEQUENCE_NAME = "default"
49
+ DEFAULT_SEQUENCE_NAME = 'default'.freeze
54
50
  # @return [String] The default reading direction for this manifest.
55
- DEFAULT_VIEWING_DIRECTION = "left-to-right"
51
+ DEFAULT_VIEWING_DIRECTION = 'left-to-right'.freeze
56
52
  # @return [Number] The size in pixels below which the canvas will be doubled.
57
53
  MIN_CANVAS_SIZE = 1200
58
54
 
59
-
60
- #--------------------------------------------------------------------------
61
- # HELPERS
62
- #--------------------------------------------------------------------------
63
-
64
-
55
+ #--------------------------------------------------------------------------
56
+ # HELPERS
57
+ #--------------------------------------------------------------------------
65
58
 
66
59
  # Validates a viewing direction string against the IIIF V.2.0 spec.
67
60
  #
68
61
  # According to v2 of the IIIF standards, there are only four valid viewing directions:
69
- # "left-to-right", "top-to-bottom”, "bottom-to-top" , and "right-to-left". This
62
+ # 'left-to-right', 'top-to-bottom', 'bottom-to-top' , and 'right-to-left'. This
70
63
  # returns true if the provided direction is one of these, and falst for anything else.
71
64
  #
72
65
  # @param [String] direction A viewing direction string
73
66
  #
74
67
  # @return [boolean] Is the provided string a valid viewing direction?
75
68
  #
76
- def self.is_valid_viewing_direction(direction)
77
- direction == "left-to-right" ||
78
- direction == "top-to-bottom" ||
79
- direction == "bottom-to-top" ||
80
- direction == "right-to-left"
69
+ def self.valid_viewing_direction?(direction)
70
+ valid = %w[left-to-right top-to-bottom bottom-to-top right-to-left]
71
+ valid.include? direction
81
72
  end
82
-
83
73
  end
@@ -0,0 +1,90 @@
1
+ require_relative 'utilities'
2
+ module WaxIiif
3
+ # Module BaseProperties provides the set of properties that are
4
+ # shared across all IIIF types.
5
+ #
6
+ # It is not a comprehensive list (yet), but it does handle
7
+ # most of the shared types. It does not include any types
8
+ # that have class-based restrictions.
9
+ #
10
+ # It also performs some basic sanity checking on (some of) the
11
+ # fields, and provides utility classes that are applicable across
12
+ # the fields.
13
+ #
14
+ # @todo Add within, service, seeAlso, viewingHint fields
15
+ # @author David Newbury <david.newbury@gmail.com>
16
+ #
17
+ module BaseProperties
18
+ include Utilities::Helpers
19
+
20
+ # @!attribute [rw] label
21
+ # @return [String] The human-readable label for this record
22
+ attr_accessor :label
23
+ # @!attribute [r] id
24
+ # @return [String] The URI for this record
25
+ attr_reader :id
26
+ # @!attribute [rw] description
27
+ # @return [String] The long-form description of this record
28
+ attr_accessor :description
29
+ # @!attribute [rw] metadata
30
+ # @return [Hash] A set of key/value pairs describing additional metadata for the object.
31
+ attr_accessor :metadata
32
+ # @!attribute [rw] attribution
33
+ # @return [String] a human-readable label, typically used for attribution or credit.
34
+ attr_accessor :attribution
35
+ # @!attribute [rw] logo
36
+ # @return [String] The URI to an image for the logo of the institution associated with this record.
37
+ attr_accessor :logo
38
+ # @!attribute [rw] license
39
+ # @return [String] The URI to a resource that describes the license or rights statement associated.
40
+ attr_accessor :license
41
+ # @!attribute [rw] related
42
+ # @return [String, Array<String>] The URI to related resources. Can be both a string or an array
43
+ attr_accessor :related
44
+
45
+ # The type of resource provided by this record.
46
+ #
47
+ # @return [String] The type of record
48
+ def type
49
+ self.class::TYPE
50
+ end
51
+
52
+ # Set the unique id for this record.
53
+ # This will automatically append the defined prefixes and suffixes.
54
+ #
55
+ # @param [String] _id The unique portion of this ID
56
+ # @return [string] The URI for this record
57
+ def id=(the_id)
58
+ @id = generate_id(the_id)
59
+ end
60
+
61
+ # Return the base data structure for this record as a Hash
62
+ # This will be in IIIF format, and should convert to JSON as JSON-LD nicely.
63
+ #
64
+ # @return [Hash] The base properties of this record
65
+ def base_properties
66
+ obj = {
67
+ '@context' => PRESENTATION_CONTEXT,
68
+ '@id' => self.id,
69
+ '@type' => self.type,
70
+ 'label' => self.label
71
+ }
72
+ obj['attribution'] = self.attribution if self.attribution
73
+ obj['logo'] = self.logo if self.logo
74
+ obj['description'] = self.description if self.description
75
+ obj['attribution'] = self.attribution if self.attribution
76
+ obj['license'] = self.license if self.license
77
+ obj['related'] = self.related if self.related
78
+ obj['metadata'] = self.metadata if self.metadata
79
+
80
+ obj
81
+ end
82
+
83
+ # Save the JSON representation of this record to disk
84
+ #
85
+ # @return [Void]
86
+ def save
87
+ save_to_disk(JSON.parse(self.to_json))
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,252 @@
1
+ require_relative 'utilities'
2
+ require 'pathname'
3
+
4
+ module WaxIiif
5
+ # Builder class
6
+ class Builder
7
+ include Utilities::Helpers
8
+
9
+ HEADER_VAL = 'filename'.freeze
10
+
11
+ #
12
+ # @!attribute [r] data
13
+ # @return [Array<Hash>] The raw data computed for the given set of images
14
+ attr_reader :data
15
+
16
+ #
17
+ # @!attribute [r] manifests
18
+ # @return [Array<Hash>] The manifest hashes for this configuration
19
+ attr_accessor :manifests
20
+
21
+ # @!attribute [r] config
22
+ # @return [WaxIiif::Config] The configuration object
23
+ attr_reader :config
24
+
25
+ # Initialize the builder.
26
+ #
27
+ # @param [Hash] config an optional configuration object.
28
+ # @see WaxIiif::Config
29
+ # @return [Void]
30
+ #
31
+ def initialize(config = {})
32
+ @manifests = []
33
+ @config = WaxIiif::Config.new(config)
34
+ end
35
+
36
+ #
37
+ # Load data into the IIIF builder.
38
+ #
39
+ # This will load the data, perform some basic verifications on it, and sort
40
+ # it into proper order.
41
+ #
42
+ # @param [Array<ImageRecord>, ImageRecord] data
43
+ # Either a single ImageRecord or an Array of ImageRecords.
44
+ # @raise [WaxIiif::Error::InvalidImageData] if any of the data does
45
+ # not pass the validation checks
46
+ #
47
+ # @return [Void]
48
+ #
49
+ def load(data)
50
+ @data = [data].flatten # handle hashes and arrays of hashes
51
+ # validate
52
+ @data.each do |image_record|
53
+ raise WaxIiif::Error::InvalidImageData, "Image record #{image_record.inspect} is not an ImageRecord" unless image_record.is_a? ImageRecord
54
+ raise WaxIiif::Error::InvalidImageData, "Image record #{image_record.inspect} does not have an ID" if image_record.id.nil?
55
+ end
56
+ end
57
+
58
+ #
59
+ # Take the loaded data and generate all the files.
60
+ #
61
+ # @param [Boolean] force_image_generation Generate images even if they already exist
62
+ #
63
+ # @return [Void]
64
+ #
65
+ def process_data(force_image_generation = false)
66
+ return nil if @data.nil? # do nothing without data.
67
+
68
+ @manifests = []
69
+ @data.group_by(&:manifest_id).each do |key, value|
70
+ resources = {}
71
+ manifest_id = key
72
+ image_records = value
73
+
74
+ # genrate the images
75
+ image_records.each do |image_record|
76
+ # It attempts to load the info files and skip generation - not currently working.
77
+ info_file = image_info_file_name(image_record)
78
+ if File.exist?(info_file) && !force_image_generation
79
+ puts "skipping #{info_file}" if @config.verbose?
80
+ image_record.variants = load_variants(info_file)
81
+ else
82
+ image_record.variants = generate_variants(image_record, @config)
83
+ generate_tiles(image_record, @config)
84
+ generate_image_json(image_record, @config)
85
+ end
86
+ # Save the image info for the manifest
87
+ resources[image_record.id] ||= []
88
+ resources[image_record.id].push image_record
89
+ end
90
+
91
+ # Generate the manifest
92
+ if manifest_id.to_s.empty?
93
+ resources.each do |_key, val|
94
+ manifests.push generate_manifest(val, @config)
95
+ end
96
+ else
97
+ manifests.push generate_manifest(image_records, @config)
98
+ end
99
+ end
100
+
101
+ generate_collection
102
+ end
103
+
104
+ def generate_collection
105
+ collection = Collection.new(@config)
106
+ manifests.each { |m| collection.add_manifest(m) }
107
+ collection.save
108
+ end
109
+
110
+ # Creates the required directories for exporting to the file system.
111
+ #
112
+ # @return [Void]
113
+ def create_build_directories
114
+ root_dir = generate_build_location('')
115
+ Dir.mkdir root_dir unless Dir.exist?(root_dir)
116
+ img_dir = generate_image_location('').split('/')[0...-1].join('/')
117
+ Dir.mkdir img_dir unless Dir.exist?(img_dir)
118
+ end
119
+
120
+ # Load data into the IIIF server from a CSV
121
+ #
122
+ # @param [String] csv_path Path to the CSV file containing the image data
123
+ #
124
+ # @return [Void]
125
+ # @todo Fix this to use the correct data format!
126
+ #
127
+ def load_csv(csv_path)
128
+ raise Error::InvalidCSV unless File.exist? csv_path
129
+ begin
130
+ vals = CSV.read(csv_path)
131
+ rescue CSV::MalformedCSVError
132
+ raise Error::InvalidCSV
133
+ end
134
+
135
+ raise Error::BlankCSV if vals.length.zero?
136
+ raise Error::InvalidCSV if vals[0].length != 3
137
+
138
+ # remove optional header
139
+ vals.shift if vals[0][0] == HEADER_VAL
140
+
141
+ @data = vals.collect do |data|
142
+ {
143
+ 'image_path' => data[0],
144
+ 'id' => data[1],
145
+ 'label' => data[2]
146
+ }
147
+ end
148
+ end
149
+
150
+ protected
151
+
152
+ #----------------------------------------------------------------
153
+ def load_variants(path)
154
+ data = JSON.parse escape_yaml(File.read(path))
155
+ id = data['@id']
156
+ w = data['width']
157
+ h = data['height']
158
+
159
+ thumb_size = data['sizes'].find do |a|
160
+ same_width = a['width'] == config.thumbnail_size
161
+ same_height = a['height'] == config.thumbnail_size
162
+ same_width || same_height
163
+ end
164
+
165
+ thumb_w = thumb_size['width']
166
+ thumb_h = thumb_size['height']
167
+ full_url = "#{id}/full/full/0/default.jpg"
168
+ thumb_url = "#{id}/full/#{thumb_w},/0/default.jpg"
169
+ full = FakeImageVariant.new(id,
170
+ w,
171
+ h,
172
+ full_url,
173
+ 'image/jpeg')
174
+ thumbnail = FakeImageVariant.new(id,
175
+ thumb_w,
176
+ thumb_h,
177
+ thumb_url,
178
+ 'image/jpeg')
179
+
180
+ { 'full' => full, 'thumbnail' => thumbnail }
181
+ end
182
+
183
+ def generate_tiles(data, config)
184
+ width = data.variants['full'].width
185
+ tile_width = config.tile_width
186
+ height = data.variants['full'].height
187
+ tiles = []
188
+ config.tile_scale_factors.each do |s|
189
+ (0..(height * 1.0 / (tile_width * s)).floor).each do |tile_y|
190
+ (0..(width * 1.0 / (tile_width * s)).floor).each do |tile_x|
191
+ tile = {
192
+ scale_factor: s,
193
+ xpos: tile_x,
194
+ ypos: tile_y,
195
+ x: tile_x * tile_width * s,
196
+ y: tile_y * tile_width * s,
197
+ width: tile_width * s,
198
+ height: tile_width * s,
199
+ xSize: tile_width,
200
+ ySize: tile_width
201
+ }
202
+ if tile[:x] + tile[:width] > width
203
+ tile[:width] = width - tile[:x]
204
+ tile[:xSize] = (tile[:width] / (s * 1.0)).ceil
205
+ end
206
+ if tile[:y] + tile[:height] > height
207
+ tile[:height] = height - tile[:y]
208
+ tile[:ySize] = (tile[:height] / (s * 1.0)).ceil
209
+ end
210
+ tiles.push(tile)
211
+ end
212
+ end
213
+ end
214
+ tiles.each do |tile|
215
+ ImageTile.new(data, @config, tile)
216
+ end
217
+ end
218
+
219
+ def image_info_file_name(data)
220
+ "#{generate_image_location(data.id)}/info.json"
221
+ end
222
+
223
+ def generate_image_json(data, config)
224
+ filename = image_info_file_name(data)
225
+ info = ImageInfo.new(data.variants['full'].id,
226
+ data.variants,
227
+ config.tile_width,
228
+ config.tile_scale_factors)
229
+ puts "writing #{filename}" if config.verbose?
230
+ Pathname.new(Pathname.new(filename).dirname).mkpath
231
+ File.open(filename, 'w') { |file| file.puts info.to_json }
232
+ info
233
+ end
234
+
235
+ def generate_manifest(data, config)
236
+ m = Manifest.new(data, config)
237
+ m.save_all_files_to_disk
238
+ m
239
+ end
240
+
241
+ def generate_variants(data, config)
242
+ obj = {
243
+ 'full' => FullImage.new(data, config),
244
+ 'thumbnail' => Thumbnail.new(data, config)
245
+ }
246
+ config.variants.each do |key, image_size|
247
+ obj[key] = ImageVariant.new(data, config, image_size)
248
+ end
249
+ obj
250
+ end
251
+ end
252
+ end