-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@dblock => Allow a Fog::Storage uploader to be passed in for uploading of generated tiles rather than local storage #5
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
### Next | ||
|
||
* [#5](https://github.com/dblock/dzt/pull/5) Allow a Fog::Storage uploader to be passed in for uploading of generated tiles rather than local storage - [@mzikherman](https://github.com/mzikherman) | ||
|
||
### 0.1.0 (3/16/2014) | ||
|
||
* Initial public release - [@dblock](https://github.com/dblock). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ gemspec | |
|
||
gem "rspec" | ||
gem "rake" | ||
gem "fog" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
module DZT | ||
class FileStorage | ||
# | ||
# @param destination: Full directory in which to output tiles, defaults to 'tiles' in the current dir. | ||
# | ||
def initialize(options = {}) | ||
@store_path = options[:destination] || File.join(Dir.pwd, 'tiles') | ||
end | ||
|
||
def exists? | ||
File.directory?(@store_path) && ! Dir["@{@store_path}/*"].empty? | ||
end | ||
|
||
def storage_location(level) | ||
File.join(@store_path, level.to_s) | ||
end | ||
|
||
def mkdir(path) | ||
FileUtils.mkdir_p(path) | ||
end | ||
|
||
def write(file, dest, options = {}) | ||
quality = options[:quality] | ||
file.write(dest) { @quality = quality if quality } | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
module DZT | ||
class S3Storage | ||
# | ||
# @param s3_acl: ACL to use for storing, defaults to 'public-read'. | ||
# @param s3_bucket: Bucket to store tiles. | ||
# @param s3_key: Key to prefix stored files. | ||
# @param aws_id: AWS Id. | ||
# @param aws_secret: AWS Secret. | ||
# | ||
def initialize(options = {}) | ||
@s3_acl = options[:s3_acl] || 'public-read' | ||
@s3_bucket = options[:s3_bucket] | ||
@s3_key = options[:s3_key] | ||
@s3_id = options[:aws_id] | ||
@s3_secret = options[:aws_secret] | ||
end | ||
|
||
def s3 | ||
@s3 ||= Fog::Storage.new( | ||
provider: 'AWS', | ||
aws_access_key_id: @s3_id, | ||
aws_secret_access_key: @s3_secret | ||
) | ||
end | ||
|
||
# Currently does not supporting checking S3 fo overwritten files | ||
def exists? | ||
false | ||
end | ||
|
||
def storage_location(level) | ||
"#{@s3_key}/#{level.to_s}" | ||
end | ||
|
||
# no-op | ||
def mkdir(path) | ||
end | ||
|
||
def write(file, dest, options = {}) | ||
quality = options[:quality] | ||
@s3.put_object(@s3_bucket, dest, file.to_blob { @quality = quality if quality }, | ||
'Content-Type' => file.mime_type, | ||
'x-amz-acl' => @s3_acl | ||
) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
# Deep Zoom module for generating Deep Zoom (DZI) tiles from a source image | ||
require_relative 'file_storage' | ||
require_relative 's3_storage' | ||
module DZT | ||
class Tiler | ||
# Defaults | ||
|
@@ -14,32 +16,32 @@ class Tiler | |
# @param format Format for output tiles (default: "jpg") | ||
# @param size Size, in pixels, for tile squares (default: 512) | ||
# @param overlap Size, in pixels, of the overlap between tiles (default: 2) | ||
# @param overwrite If true, overwrites existing tiles (default: false) | ||
# @param destination: Full directory in which to output tiles. | ||
# @param overwrite Whether or not to overwrite if the destination exists (default: false) | ||
# @param storage Either an instance of S3Storage or FileStorage | ||
# | ||
def initialize(options) | ||
@tile_source = options[:source] | ||
raise "Missing options[:source]." unless @tile_source | ||
|
||
@tile_source = Magick::Image.read(@tile_source)[0] if @tile_source.is_a?(String) | ||
@tile_size = options[:size] || DEFAULT_TILE_SIZE | ||
@tile_overlap = options[:overlap] || DEFAULT_TILE_OVERLAP | ||
@tile_format = options[:format] || DEFAULT_TILE_FORMAT | ||
|
||
@max_tiled_height = @tile_source.rows | ||
@max_tiled_width = @tile_source.columns | ||
|
||
@tile_quality = options[:quality] || DEFAULT_QUALITY | ||
@overwrite = options[:overwrite] || false | ||
@destination = options[:destination] || File.join(Dir.pwd, "tiles") | ||
@storage = options[:storage] | ||
end | ||
|
||
## | ||
# Generates the DZI-formatted tiles and sets necessary metadata on this object. | ||
# Uses a default tile size of 512 pixels, with a default overlap of 2 pixel. | ||
## | ||
def slice!(&block) | ||
if ! @overwrite && File.directory?(@destination) && ! Dir["@{@destination}/*"].empty? | ||
raise "Output directory #{@destination} already exists!" | ||
@overwrite ? Rails.logger.warn(msg) : raise(msg) | ||
end | ||
raise "Output #{@destination} already exists!" if ! @overwrite && @storage.exists? | ||
|
||
image = @tile_source.dup | ||
orig_width, orig_height = image.columns, image.rows | ||
|
@@ -48,11 +50,10 @@ def slice!(&block) | |
max_level(orig_width, orig_height).downto(0) do |level| | ||
width, height = image.columns, image.rows | ||
|
||
current_level_dir = File.join(@destination, level.to_s) | ||
FileUtils.mkdir_p(current_level_dir) | ||
|
||
current_level_storage_dir = @storage.storage_location(level) | ||
@storage.mkdir(current_level_storage_dir) | ||
if block_given? | ||
yield current_level_dir | ||
yield current_level_storage_dir | ||
end | ||
|
||
# iterate over columns | ||
|
@@ -61,7 +62,7 @@ def slice!(&block) | |
# iterate over rows | ||
y, row_count = 0, 0 | ||
while y < height | ||
dest_path = File.join(current_level_dir, "#{col_count}_#{row_count}.#{@tile_format}") | ||
dest_path = File.join(current_level_storage_dir, "#{col_count}_#{row_count}.#{@tile_format}") | ||
tile_width, tile_height = tile_dimensions(x, y, @tile_size, @tile_overlap) | ||
|
||
save_cropped_image(image, dest_path, x, y, tile_width, tile_height, @tile_quality) | ||
|
@@ -120,7 +121,7 @@ def save_cropped_image(src, dest, x, y, width, height, quality = 75) | |
# The crop method retains the offset information in the cropped image. | ||
# To reset the offset data, adding true as the last argument to crop. | ||
cropped = img.crop(x, y, width, height, true) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This becomes |
||
cropped.write(dest) { @quality = quality } | ||
@storage.write(cropped, dest, quality: quality) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,65 @@ | ||
require 'spec_helper' | ||
require 'RMagick' | ||
include Magick | ||
|
||
describe DZT::Tiler do | ||
before :each do | ||
@fixtures_dir = File.expand_path(File.join(__FILE__, '../../fixtures')) | ||
end | ||
it "slices an image" do | ||
Dir.mktmpdir do |tmpdir| | ||
tiler = DZT::Tiler.new( | ||
context 'storing files locally' do | ||
it "slices an image and stores files" do | ||
Dir.mktmpdir do |tmpdir| | ||
storage = DZT::FileStorage.new(destination: tmpdir) | ||
tiler = DZT::Tiler.new( | ||
source: File.join(@fixtures_dir, "francisco-jose-de-goya-y-lucientes-senora-sabasa-garcia.jpg"), | ||
storage: storage | ||
) | ||
tiler.slice! | ||
expect(Dir["#{tmpdir}/*"].map { |dir| dir.split("/").last.to_i }.sort).to eq((0..12).to_a) | ||
# center | ||
image = Magick::Image::read("#{tmpdir}/11/1_1.jpg").first | ||
expect(image.columns).to eq(512) | ||
expect(image.rows).to eq(512) | ||
# edge | ||
image = Magick::Image::read("#{tmpdir}/11/2_2.jpg").first | ||
expect(image.columns).to eq(168) | ||
expect(image.rows).to eq(443) | ||
end | ||
end | ||
end | ||
context 'uploading resultant files to S3' do | ||
before :each do | ||
Fog.mock! | ||
Fog::Mock.reset | ||
storage = DZT::S3Storage.new( | ||
s3_acl: 'public-read', | ||
s3_bucket: 'tiled-images', | ||
s3_key: 'dztiles', | ||
aws_id: 'id', | ||
aws_secret: 'secret' | ||
) | ||
@bucket = storage.s3.directories.create(key: 'tiled-images') | ||
@tiler = DZT::Tiler.new( | ||
source: File.join(@fixtures_dir, "francisco-jose-de-goya-y-lucientes-senora-sabasa-garcia.jpg"), | ||
destination: tmpdir | ||
storage: storage | ||
) | ||
tiler.slice! | ||
Dir["#{tmpdir}/*"].map { |dir| dir.split("/").last.to_i }.sort.should == (0..12).to_a | ||
# center | ||
image = Magick::Image::read("#{tmpdir}/11/1_1.jpg").first | ||
image.columns.should == 512 | ||
image.rows.should == 512 | ||
# edge | ||
image = Magick::Image::read("#{tmpdir}/11/2_2.jpg").first | ||
image.columns.should == 168 | ||
image.rows.should == 443 | ||
end | ||
it 'slices the images' do | ||
@tiler.slice! | ||
file = @bucket.files.select { |f| f.key == 'dztiles/11/1_1.jpg' }.first | ||
image = Image.from_blob(file.body).first | ||
expect(image.columns).to eq(512) | ||
expect(image.rows).to eq(512) | ||
file = @bucket.files.select { |f| f.key == 'dztiles/11/2_2.jpg' }.first | ||
image = Image.from_blob(file.body).first | ||
expect(image.columns).to eq(168) | ||
expect(image.rows).to eq(443) | ||
end | ||
it 'stores the files properly' do | ||
expect_any_instance_of(Fog::Storage::AWS::Mock).to receive(:put_object).at_least(53).times do |*args| | ||
expect(args.last).to eq("Content-Type" => "image/jpeg", "x-amz-acl" => "public-read") | ||
end | ||
@tiler.slice! | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,6 @@ | |
|
||
describe DZT do | ||
it "has a version" do | ||
DZT::VERSION.should_not be_nil | ||
expect(DZT::VERSION).to_not be_nil | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ | |
require 'rspec' | ||
require 'tmpdir' | ||
require 'dzt' | ||
require 'fog' |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no-op since S3 doesn't have directories, no need to create anything ahead of time, as long as the right key/prefix is used.