add support for alternate file sources for image size analysis

This commit is contained in:
John Bintz 2012-05-25 20:19:00 -04:00
parent b1c34a24f2
commit 4dd1223682
3 changed files with 51 additions and 29 deletions

View File

@ -40,7 +40,8 @@ module Compass
:preferred_syntax, :preferred_syntax,
:disable_warnings, :disable_warnings,
:sprite_engine, :sprite_engine,
:chunky_png_options :chunky_png_options,
:images_file_source
].flatten ].flatten
ARRAY_ATTRIBUTES = [ ARRAY_ATTRIBUTES = [

View File

@ -23,13 +23,23 @@ module Compass::SassExtensions::Functions::ImageSize
raise Sass::SyntaxError, "Unrecognized file type: #{@file_type}" raise Sass::SyntaxError, "Unrecognized file type: #{@file_type}"
end end
private private
def open_file_source
source = Compass.configuration.images_file_source || lambda { |file| File.open(file, 'rb') }
io = source.call(@file)
result = yield io
io.close
result
end
def get_size_for_png def get_size_for_png
File.open(@file, "rb") {|io| io.read}[0x10..0x18].unpack('NN') open_file_source {|io| io.read}[0x10..0x18].unpack('NN')
end end
def get_size_for_gif def get_size_for_gif
File.open(@file, "rb") {|io| io.read}[6..10].unpack('SS') open_file_source {|io| io.read}[6..10].unpack('SS')
end end
def get_size_for_jpg def get_size_for_jpg
@ -37,12 +47,14 @@ module Compass::SassExtensions::Functions::ImageSize
end end
def get_size_for_jpeg def get_size_for_jpeg
jpeg = JPEG.new(@file) open_file_source do |io|
[jpeg.width, jpeg.height] jpeg = JPEG.new(io)
[ jpeg.width, jpeg.height ]
end
end end
end end
private private
def image_dimensions(image_file) def image_dimensions(image_file)
options[:compass] ||= {} options[:compass] ||= {}
@ -69,15 +81,11 @@ private
class JPEG class JPEG
attr_reader :width, :height, :bits attr_reader :width, :height, :bits
def initialize(file) def initialize(io)
if file.kind_of? IO examine(io)
examine(file)
else
File.open(file, 'rb') { |io| examine(io) }
end
end end
private private
def examine(io) def examine(io)
class << io class << io
unless method_defined?(:readbyte) unless method_defined?(:readbyte)
@ -99,15 +107,15 @@ private
while marker = io.next while marker = io.next
case marker case marker
when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers
length, @bits, @height, @width, components = io.readsof length, @bits, @height, @width, components = io.readsof
raise 'malformed JPEG' unless length == 8 + components * 3 raise 'malformed JPEG' unless length == 8 + components * 3
when 0xD9, 0xDA then break # EOI, SOS when 0xD9, 0xDA then break # EOI, SOS
when 0xFE then @comment = io.readframe # COM when 0xFE then @comment = io.readframe # COM
when 0xE1 then io.readframe # APP1, contains EXIF tag when 0xE1 then io.readframe # APP1, contains EXIF tag
else io.readframe # ignore frame else io.readframe # ignore frame
end end
end end
end end
end end
end end

View File

@ -167,7 +167,6 @@ class SassExtensionsTest < Test::Unit::TestCase
assert_equal "url('data:font/truetype;base64,#{base64_string}') format('truetype')", evaluate("inline_font_files('bgrove.ttf', truetype)") assert_equal "url('data:font/truetype;base64,#{base64_string}') format('truetype')", evaluate("inline_font_files('bgrove.ttf', truetype)")
end end
def test_image_size_should_respond_to_to_path def test_image_size_should_respond_to_to_path
object = mock() object = mock()
object.expects(:to_path).returns('foo.jpg') object.expects(:to_path).returns('foo.jpg')
@ -176,6 +175,20 @@ class SassExtensionsTest < Test::Unit::TestCase
Compass::SassExtensions::Functions::ImageSize::ImageProperties.new(object) Compass::SassExtensions::Functions::ImageSize::ImageProperties.new(object)
end end
def test_image_properites_should_be_able_to_use_file_like_object
source = Class.new do
def self.open(*args, &block)
File.open(*args, &block)
end
end
Compass.configuration.images_file_source = lambda { |file| source.open(file) }
properties = Compass::SassExtensions::Functions::ImageSize::ImageProperties.new('test/fixtures/sprites/public/images/colors/blue.png')
assert_equal [ 10, 10 ], properties.size
end
def test_reject def test_reject
assert_equal "b d", evaluate("reject(a b c d, a, c)") assert_equal "b d", evaluate("reject(a b c d, a, c)")
assert_equal "a b c d", evaluate("reject(a b c d, e)") assert_equal "a b c d", evaluate("reject(a b c d, e)")