class IiifS3::Builder

Constants

HEADER_VAL

Attributes

config[R]

@!attribute [r] config

@return [IiifS3::Config] The configuration object
data[R]

@!attribute [r] data

@return [Array<Hash>] The raw data computed for the given set of images
manifests[RW]

@!attribute [r] manifests

@return [Array<Hash>] The manifest hashes for this configuration

Public Class Methods

new(config = {}) click to toggle source

Initialize the builder.

@param [Hash] config an optional configuration object. @see IiifS3::Config @return [Void]

# File lib/iiif_s3/builder.rb, line 31
def initialize(config = {})
  @manifests = []
  @config = IiifS3::Config.new(config)
end

Public Instance Methods

create_build_directories() click to toggle source

Creates the required directories for exporting to the file system.

@return [Void]

# File lib/iiif_s3/builder.rb, line 109
def create_build_directories
root_dir =  generate_build_location("")
  Dir.mkdir root_dir unless Dir.exists?(root_dir)
  img_dir = generate_image_location("","").split("/")[0...-1].join("/")
  Dir.mkdir img_dir unless Dir.exists?(img_dir)
end
generate_collection(label="top") click to toggle source
# File lib/iiif_s3/builder.rb, line 100
def generate_collection(label="top")
  collection = Collection.new(label,@config)
  manifests.each{|m| collection.add_manifest(m)}
  collection.save
end
load(data) click to toggle source

Load data into the IIIF builder.

This will load the data, perform some basic verifications on it, and sort it into proper order.

@param [Array<ImageRecord>, ImageRecord] data

Either a single ImageRecord or an Array of ImageRecords.

@raise [IiifS3::Error::InvalidImageData] if any of the data does

not pass the validation checks

@return [Void]

# File lib/iiif_s3/builder.rb, line 50
def load(data)
  @data = [data].flatten # handle hashes and arrays of hashes

  # validate
  @data.each  do |image_record| 
    raise IiifS3::Error::InvalidImageData, "Image record #{image_record.inspect} is not an ImageRecord" unless image_record.is_a? ImageRecord
    raise IiifS3::Error::InvalidImageData, "Image record #{image_record.inspect} does not have an ID and/or a page number" if image_record.id.nil? || image_record.page_number.nil?
  end
end
load_csv(csv_path) click to toggle source

Load data into the IIIF server from a CSV

@param [String] csv_path Path to the CSV file containing the image data

@return [Void] @todo Fix this to use the correct data format!

# File lib/iiif_s3/builder.rb, line 123
def load_csv(csv_path)
  raise Error::InvalidCSV unless File.exist? csv_path
  begin
    vals = CSV.read(csv_path)
  rescue CSV::MalformedCSVError
    raise Error::InvalidCSV
  end  

  raise Error::BlankCSV if vals.length == 0
  raise Error::InvalidCSV if vals[0].length != 3

  # remove optional header
  vals.shift if vals[0][0] == HEADER_VAL

  @data = vals.collect do |data|
    {
      "image_path" => data[0],
      "id"       => data[1],
      "label"    => data[2]
    }
  end
end
process_data(force_image_generation=false) click to toggle source

Take the loaded data and generate all the files.

@param [Boolean] force_image_generation Generate images even if they already exist

@return [Void]

# File lib/iiif_s3/builder.rb, line 68
def process_data(force_image_generation=false)
  return nil if @data.nil? # do nothing without data.
  @manifests = []

  resources = {}
  @data.each do |image_record|
    
    # image generation
    #
    # It attempts to load the info files and skip generation — not currently working.
    info_file = image_info_file_name(image_record)
    if (File.exist?(info_file) && !force_image_generation)
      puts "skipping #{info_file}" if @config.verbose?
      image_record.variants = load_variants(info_file)
    else
      image_record.variants = generate_variants(image_record, @config)
      generate_tiles(image_record, @config)
      generate_image_json(image_record, @config)
    end
    # Save the image info for the manifest
    resources[image_record.id] ||= []
    resources[image_record.id].push image_record
  end

  # Generate the manifests
  resources.each do |key, val|
    manifests.push generate_manifest(val, @config) 
  end

  generate_collection
end

Protected Instance Methods

build_a_manifest() click to toggle source
# File lib/iiif_s3/builder.rb, line 228
def build_a_manifest

  manifest_uri = "@config.s3.bucket/#{generate_id(record)}/manifest.json"
  # response = Typhoeus.get(manifest_uri, followlocation: true)
  # if response.code == 200
  #   puts "Skipping #{file}—Manifest already exists." if verbose
  #   data = JSON.parse(response.body)
  #   obj = IiifS3::FakeManifest.new(data["@id"], data["@type"], data["label"])
  #   @iiif.manifests.push(obj)
  #   next
  # end
end
generate_image_json(data, config) click to toggle source
# File lib/iiif_s3/builder.rb, line 205
def generate_image_json(data, config) 
  filename = image_info_file_name(data)
  info = ImageInfo.new(data.variants["full"].id, data.variants ,config.tile_width, config.tile_scale_factors)

  puts "writing #{filename}" if config.verbose?
  Pathname.new(Pathname.new(filename).dirname).mkpath
  File.open(filename, "w") do |file|
   file.puts info.to_json 
  end
  if @config.upload_to_s3
    add_file_to_s3(filename)
    add_default_redirect(filename)
  end
  return info
end
generate_manifest(data, config) click to toggle source
# File lib/iiif_s3/builder.rb, line 222
def generate_manifest(data, config)
    m = Manifest.new(data, config)
    m.save_all_files_to_disk
    return m
end
generate_tiles(data, config) click to toggle source
# File lib/iiif_s3/builder.rb, line 165
def generate_tiles(data, config) 
  width = data.variants["full"].width
  tile_width = config.tile_width
  height = data.variants["full"].height
  tiles = []
  config.tile_scale_factors.each do |s|
    (0..(height*1.0/(tile_width*s)).floor).each do |tileY|
      (0..(width*1.0/(tile_width*s)).floor).each do |tileX|
        tile = {
          scale_factor: s,
          xpos: tileX,
          ypos: tileY,
          x: tileX * tile_width * s,
          y: tileY * tile_width * s,
          width: tile_width * s,
          height: tile_width * s,
          xSize: tile_width,
          ySize: tile_width
        }
        if (tile[:x] + tile[:width]  > width)
          tile[:width]  = width  - tile[:x]
          tile[:xSize]  = (tile[:width]/(s*1.0)).ceil
        end
        if (tile[:y] + tile[:height] > height)
          tile[:height] = height - tile[:y] 
          tile[:ySize]  = (tile[:height]/(s*1.0)).ceil
        end
        tiles.push(tile)
      end
    end
  end
  tiles.each do |tile|
    ImageTile.new(data, @config, tile)
  end
end
generate_variants(data, config) click to toggle source
# File lib/iiif_s3/builder.rb, line 242
def generate_variants(data, config)
  obj = {
    "full" => FullImage.new(data, config),
    "thumbnail" => Thumbnail.new(data, config)
  }

  config.variants.each do |key,image_size|
    obj[key] = ImageVariant.new(data, config, image_size, image_size)
  end
  return obj
end
image_info_file_name(data) click to toggle source
# File lib/iiif_s3/builder.rb, line 201
def image_info_file_name(data)
  "#{generate_image_location(data.id,data.page_number)}/info.json"
end
load_variants(path) click to toggle source
# File lib/iiif_s3/builder.rb, line 149
def load_variants(path)

  data = JSON.parse File.read(path)
  id = data["@id"]
  w = data["width"]
  h = data["height"]
  thumb_size = data["sizes"].find{|a| a["width"] == config.thumbnail_size || a["height"] == config.thumbnail_size}
  thumb_w = thumb_size["width"]
  thumb_h = thumb_size["height"]
  full_url = "#{id}/full/full/0/default.jpg"
  thumb_url = "#{id}/full/#{thumb_w},/0/default.jpg"
  full = FakeImageVariant.new( id,w, h,full_url, "image/jpeg")
  thumbnail = FakeImageVariant.new( id, thumb_w, thumb_h, thumb_url, "image/jpeg")
  return {"full" => full, "thumbnail" => thumbnail}
end