Navigation Menu

Skip to content
This repository has been archived by the owner on Feb 20, 2018. It is now read-only.

Commit

Permalink
Background configurarion for images with alpha channels
Browse files Browse the repository at this point in the history
  • Loading branch information
peleteiro committed Feb 25, 2010
1 parent 8c660ec commit ce2a057
Show file tree
Hide file tree
Showing 19 changed files with 114 additions and 24 deletions.
12 changes: 8 additions & 4 deletions config.ru
@@ -1,9 +1,13 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
$:.unshift(::File.expand_path(::File.join(::File.dirname(__FILE__), 'lib'))) $:.unshift(::File.expand_path(::File.join(::File.dirname(__FILE__), "lib")))
require 'mugshot' require "mugshot"


system "mkdir -p /tmp/mugshot && cp -f spec/files/test.jpg /tmp/mugshot/test" system "mkdir -p /tmp/mugshot"
%w[test.jpg with_alpha_channel.png].each do |filename|
system "cp -f features/support/files/#{filename} /tmp/mugshot/#{filename.split('.').first}"
end


run Mugshot::Application.new( run Mugshot::Application.new(
:storage => Mugshot::ProxyStorage.new{|id| "http://foo.com/#{id}.jpg"} :storage => Mugshot::FSStorage.new("/tmp/mugshot")
) )

2 changes: 1 addition & 1 deletion cucumber.yml
@@ -1 +1 @@
default: -r features/support/env.rb -r features/step_definitions default: --guess -r features/support/env.rb -r features/step_definitions
5 changes: 5 additions & 0 deletions features/image_format.feature
Expand Up @@ -9,3 +9,8 @@ Feature: Image Format
When I upload an image When I upload an image
And I ask for a jpg image And I ask for a jpg image
Then I should get a jpg image Then I should get a jpg image

Scenario: Image as png
When I upload an image
And I ask for a png image
Then I should get a png image
7 changes: 7 additions & 0 deletions features/set_background.feature
@@ -0,0 +1,7 @@
Feature: Set Background

Scenario: Set background for a png image with alpha channel
Given a png image with alpha channel
When I ask for it with a red background
Then I should get it with a red background

18 changes: 18 additions & 0 deletions features/step_definitions/all_steps.rb
@@ -1,4 +1,22 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
Given /^a (.*) image (.*)$/ do |ext, name|
@image = {
:name => name,
:ext => ext,
:filename => "#{name.gsub(' ', '_')}.#{ext}"}

@image[:id] = write_image(@image[:filename])
end

When /^I ask for it with a (.*) background$/ do |color|
get "/background/#{color}/#{@image[:id]}/img.jpg"
@retrieved_image = Magick::Image.from_blob(last_response.body).first
end

Then /^I should get it (.*)$/ do |name|
@retrieved_image.should be_same_image_as("#{@image[:name].gsub(' ', '_')}-#{name.underscore.gsub(' ', '_')}.jpg")
end

When /^I upload an image$/ do When /^I upload an image$/ do
post '/', "file" => Rack::Test::UploadedFile.new("features/support/files/test.jpg", "image/jpeg") post '/', "file" => Rack::Test::UploadedFile.new("features/support/files/test.jpg", "image/jpeg")
@image_id = last_response.body @image_id = last_response.body
Expand Down
5 changes: 5 additions & 0 deletions features/support/env.rb
Expand Up @@ -17,6 +17,11 @@ module CucumberWorld
def app def app
Mugshot::Application.new(Mugshot::FSStorage.new('/tmp/mugshot/cucumber')) Mugshot::Application.new(Mugshot::FSStorage.new('/tmp/mugshot/cucumber'))
end end

def write_image(filename)
Mugshot::FSStorage.new('/tmp/mugshot/cucumber').
write(IO.read(File.expand_path(filename, "features/support/files/")))
end
end end
World(CucumberWorld) World(CucumberWorld)


Expand Down
Binary file added features/support/files/test.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added features/support/files/with_alpha_channel.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions lib/mugshot.rb
Expand Up @@ -7,4 +7,5 @@ module Mugshot
autoload :FSStorage, "mugshot/fs_storage" autoload :FSStorage, "mugshot/fs_storage"
autoload :Application, "mugshot/application" autoload :Application, "mugshot/application"
autoload :HTTPStorage, "mugshot/http_storage" autoload :HTTPStorage, "mugshot/http_storage"
autoload :MagickFactory, "mugshot/magick_factory"
end end
8 changes: 7 additions & 1 deletion lib/mugshot/application.rb
Expand Up @@ -2,6 +2,9 @@
require 'sinatra/base' require 'sinatra/base'


class Mugshot::Application < Sinatra::Base class Mugshot::Application < Sinatra::Base

VALID_OPERATIONS = %w[background crop resize quality]

set :static, true set :static, true
set :public, ::File.expand_path(::File.join(::File.dirname(__FILE__), "public")) set :public, ::File.expand_path(::File.join(::File.dirname(__FILE__), "public"))


Expand Down Expand Up @@ -36,19 +39,22 @@ def initialize(opts)
opts.to_options! opts.to_options!


@storage = opts[:storage] @storage = opts[:storage]

@background = opts[:background].to_s if opts.include?(:background)
@quality = opts[:quality].to_s if opts.include?(:quality) @quality = opts[:quality].to_s if opts.include?(:quality)
end end


private private
def process_default_operations(image) def process_default_operations(image)
image.background!(@background) if !!@background
image.quality!(@quality) if !!@quality image.quality!(@quality) if !!@quality
end end


def process_operations(image, splat) def process_operations(image, splat)
operations = [] operations = []
begin begin
operations = Hash[*splat.split('/')] operations = Hash[*splat.split('/')]
operations.assert_valid_keys("crop", "resize", "quality") operations.assert_valid_keys(VALID_OPERATIONS)
rescue rescue
halt 404 halt 404
end end
Expand Down
1 change: 1 addition & 0 deletions lib/mugshot/http_storage.rb
Expand Up @@ -4,6 +4,7 @@
require 'net/http' require 'net/http'


class Mugshot::HTTPStorage < Mugshot::Storage class Mugshot::HTTPStorage < Mugshot::Storage

def read(id) def read(id)
url = URI.parse(@url_resolver.call(id)) url = URI.parse(@url_resolver.call(id))
res = Net::HTTP.start(url.host, url.port) {|http| http.get(url.path)} res = Net::HTTP.start(url.host, url.port) {|http| http.get(url.path)}
Expand Down
20 changes: 13 additions & 7 deletions lib/mugshot/image.rb
@@ -1,12 +1,9 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
require 'RMagick' require 'RMagick'
class Mugshot::Image class Mugshot::Image
def width
@image.columns
end


def height def background!(color)
@image.rows @background_color = color
end end


def resize!(size) def resize!(size)
Expand Down Expand Up @@ -38,6 +35,9 @@ def destroy!


def to_blob(opts = {}) def to_blob(opts = {})
opts.merge!(:quality => @quality) opts.merge!(:quality => @quality)

set_background(@background_color) if !!@background_color

@image.strip! @image.strip!
@image.to_blob do @image.to_blob do
self.format = opts[:format].to_s if opts.include?(:format) self.format = opts[:format].to_s if opts.include?(:format)
Expand All @@ -54,12 +54,18 @@ def initialize(file_or_blob)
end end


# initialize attrs # initialize attrs
@quality = nil @background_color = @quality = nil
end end


private private

def parse_size(size) def parse_size(size)
size.to_s.split("x").map{|i| i.blank? ? nil : i.to_i} size.to_s.split("x").map{|i| i.blank? ? nil : i.to_i}
end end

def set_background(color)
@image = Mugshot::MagickFactory.
create_canvas(@image.columns, @image.rows, color).
composite(@image, Magick::NorthWestGravity, Magick::OverCompositeOp)
end
end end

12 changes: 12 additions & 0 deletions lib/mugshot/magick_factory.rb
@@ -0,0 +1,12 @@
# -*- encoding: utf-8 -*-
require 'RMagick'

class Mugshot::MagickFactory
class << self

def create_canvas(columns, rows, color)
Magick::Image.new(columns, rows){ self.background_color = color }
end

end
end
Binary file added spec/files/firefox_png.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added spec/files/test_png.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion spec/mugshot/application_spec.rb
Expand Up @@ -20,6 +20,14 @@ def app
@image.should_receive(:quality!).with("42") @image.should_receive(:quality!).with("42")
get "/image_id/any_name.jpg" get "/image_id/any_name.jpg"
end end

it "should accept default value for background" do
def app
Mugshot::Application.new(:storage => @storage, :background => 'blue')
end
@image.should_receive(:background!).with("blue")
get "/image_id/any_name.jpg"
end
end end


describe "POST /" do describe "POST /" do
Expand Down Expand Up @@ -70,8 +78,9 @@ def app
@image.should_receive(:resize!).with("140x140") @image.should_receive(:resize!).with("140x140")
@image.should_receive(:crop!).with("140x105") @image.should_receive(:crop!).with("140x105")
@image.should_receive(:quality!).with("70") @image.should_receive(:quality!).with("70")
@image.should_receive(:background!).with("red")


get "/resize/140x140/crop/140x105/quality/70/image_id/any_name.jpg" get "/background/red/resize/140x140/crop/140x105/quality/70/image_id/any_name.jpg"
end end


it "should halt 404 on operations that are not allowed" do it "should halt 404 on operations that are not allowed" do
Expand Down
23 changes: 13 additions & 10 deletions spec/mugshot/image_spec.rb
Expand Up @@ -3,8 +3,7 @@


describe Mugshot::Image do describe Mugshot::Image do
before :each do before :each do
@magick_image = mock(Magick::Image) @magick_image = mock(Magick::Image, :null_object => true, :columns => 100, :rows => 100)
@magick_image.stub!(:strip!)
@magick_image.instance_eval do # TODO: Explain it @magick_image.instance_eval do # TODO: Explain it
def to_blob(&block) def to_blob(&block)
block.call if block.present? block.call if block.present?
Expand All @@ -22,14 +21,6 @@ def to_blob(&block)
Mugshot::Image.new("blob") Mugshot::Image.new("blob")
end end


it 'should return image width and height' do
@magick_image.stub!(:columns).and_return(100)
@magick_image.stub!(:rows).and_return(200)

@image.width.should == 100
@image.height.should == 200
end

describe "to blob" do describe "to blob" do
it 'should return image as a blob using default options' do it 'should return image as a blob using default options' do
@image.to_blob.should == 'blob_data' @image.to_blob.should == 'blob_data'
Expand All @@ -47,6 +38,17 @@ def to_blob(&block)
@image.quality!("75") @image.quality!("75")
@image.to_blob @image.to_blob
end end

it 'should set background for transparent images' do
canvas = mock(Magick::Image)
Mugshot::MagickFactory.stub!(:create_canvas).and_return(canvas)
canvas.should_receive(:composite).
with(@magick_image, Magick::NorthWestGravity, Magick::OverCompositeOp).
and_return(@magick_image)

@image.background!("gray")
@image.to_blob
end


it "should resize image to given width and height" do it "should resize image to given width and height" do
@magick_image.should_receive(:resize!).with(300, 200) @magick_image.should_receive(:resize!).with(300, 200)
Expand Down Expand Up @@ -74,3 +76,4 @@ def to_blob(&block)
end end


end end

13 changes: 13 additions & 0 deletions spec/mugshot/magick_factory_spec.rb
@@ -0,0 +1,13 @@
# -*- encoding: utf-8 -*-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

describe Mugshot::MagickFactory do

it "should create a canvas given columns, rows and background color" do
canvas = Mugshot::MagickFactory.create_canvas(100, 200, 'red')
canvas.columns.should == 100
canvas.rows.should == 200
canvas.background_color == 'red'
end

end

0 comments on commit ce2a057

Please sign in to comment.