Skip to content
Browse files

bam! replacing our own png reader with chunky_png

  • Loading branch information...
1 parent 1ebfa06 commit 01e77a7e5d69feb806ec2fe619ada71cde7912b4 @aberant committed Mar 22, 2011
View
13 lib/css-spriter.rb
@@ -1,17 +1,6 @@
-require 'zlib'
-
-require 'css-spriter/png/file_header'
-require 'css-spriter/png/parser'
-require 'css-spriter/png/filters'
-require 'css-spriter/png/chunk'
-require 'css-spriter/png/ihdr'
-require 'css-spriter/png/idat'
-require 'css-spriter/png/iend'
-require 'css-spriter/png/image'
require 'css-spriter/sprite'
-require 'css-spriter/chunky_sprite'
+require 'css-spriter/image'
require 'css-spriter/directory_processor'
require 'css-spriter/stylesheet_builder'
require 'css-spriter/processor'
require 'css-spriter/mtime_tracker'
-require 'css-spriter/image_data'
View
47 lib/css-spriter/chunky_sprite.rb
@@ -1,47 +0,0 @@
-require 'chunky_png'
-
-class ChunkySprite
- attr_reader :images, :max_height
-
- def initialize
- @images = []
- @locations = {}
- end
-
- def append( image )
- @images << image
- @max_height = @images.map{ |i| i.height }.max
- end
-
- def append_file( filename )
- append( ChunkyPNG::Image.from_file( filename ))
- end
-
- def locations
- @images.inject(0) do |x, image|
- @locations[image.name.to_sym] = { :x => -(x),
- :width => image.width,
- :height => image.height}
- image.width + x
- end
- @locations
- end
-
- def write( output_filename )
- return if @images.empty?
-
- sprite_height = @images.map{ |i| i.height }.max
- sprite_width = @images.inject(0){|sum, image| sum + image.width }
-
- sprite = ChunkyPNG::Image.new(sprite_width, sprite_height)
-
- current_x = 0
-
- images.each do |image|
- sprite.replace(image, current_x, 0)
- current_x += image.width
- end
-
- sprite.save( output_filename, :best_compression )
- end
-end
View
13 lib/css-spriter/image.rb
@@ -0,0 +1,13 @@
+module CssSpriter
+ class Image < ::ChunkyPNG::Image
+ attr_accessor :name
+
+ def self.from_file( filename )
+ name = File.basename( filename, ".png" )
+
+ image = super
+ image.name = name
+ image
+ end
+ end
+end
View
128 lib/css-spriter/image_data.rb
@@ -1,128 +0,0 @@
-require 'enumerator'
-
-module CssSpriter
- class ImageData
- RGB_WIDTH = 3
- RGBA_WIDTH = 4
-
- def initialize(options = {})
- @data = (options.delete :data) || []
- @properties = options
- end
-
- def name; @properties[:name] || "default"; end
- def scanline_width; @properties[:scanline_width]; end
- def width; scanline_width / pixel_width; end
- def pixel_width; @properties[:pixel_width]; end
-
- # need better checks, because currently compatible is
- # similar color type, or depth.. maybe it doesn't matter...
- def compatible?(image)
- self.pixel_width == image.pixel_width
- end
-
- def to_s
- "#{name} pixel width: #{pixel_width}"
- end
-
- def last_scanline(idx)
- last_row_index = idx - 1
- (last_row_index < 0 ? [] : @data[last_row_index])
- end
-
- def merge_left( other )
- merged = ImageData.new(@properties.merge(:scanline_width => self.scanline_width + other.scanline_width,
- :name => "#{self.name}_#{other.name}"))
- other.each_with_index do |row, idx|
- merged[idx] = row + self[idx]
- end
- merged
- end
-
- def fill_to_height( desired_height )
- return self if desired_height == height
-
- img = ImageData.new(@properties.merge(:data => @data.clone))
- empty_row = [0] * ( scanline_width )
-
- ( desired_height - height ).times do
- img << empty_row
- end
- img
- end
-
- def to_rgba( alpha_value=255 )
- # test that conversion updates pixel width, scanline width
-
- return self if pixel_width == RGBA_WIDTH
-
- # so ruby 1.9 has different ideas then 1.8 on how Enumerable should work
- # 1.9 returns Enumerable object if no block given
- # 1.8 complains if no block, unless using enum_x methods
- slice_method = (RUBY_VERSION.include?( "1.9" )) ? :each_slice : :enum_slice
-
- rgba_data = @data.map do |row|
- pixels = row.send( slice_method, RGB_WIDTH )
- pixels.inject([]){|result, pixel| result + pixel + [alpha_value] }
- end
-
- ImageData.new( :data => rgba_data,
- :pixel_width => 4,
- :scanline_width => (@properties[:scanline_width] / RGB_WIDTH) * RGBA_WIDTH,
- :name => name)
- end
-
- def [](row)
- @data[row]
- end
-
- def []=(idx, row_data)
- @data[idx] = row_data
- end
-
- def scanline(row)
- self[row]
- end
-
- def empty?
- @data.empty?
- end
-
- def height
- size
- end
-
- def size
- @data.size
- end
-
- def last
- @data.last
- end
-
- def <<(row)
- @data << row
- self
- end
-
- def each(&block)
- @data.each &block
- end
-
- def each_with_index(&block)
- @data.each_with_index(&block)
- end
-
- def flatten!
- @data.flatten!
- end
-
- def pack(*args)
- @data.pack(*args)
- end
-
- def == (other)
- @data == other
- end
- end
-end
View
12 lib/css-spriter/png/chunk.rb
@@ -1,12 +0,0 @@
-module PNG
- class Chunk
- def chunk_name
- raise "looks like you havn't subclassed and defined a chunk_name"
- end
-
- def to_chunk
- to_check = chunk_name + encode
- [encode.length].pack("N") + to_check + [Zlib.crc32(to_check)].pack("N")
- end
- end
-end
View
7 lib/css-spriter/png/file_header.rb
@@ -1,7 +0,0 @@
-module PNG
- class FileHeader
- def encode
- [137, 80, 78, 71, 13, 10, 26, 10].pack("C*")
- end
- end
-end
View
80 lib/css-spriter/png/filters.rb
@@ -1,80 +0,0 @@
-module PNG
- class Filters
- class << self
- def fetch_pixel(idx, row)
- idx < 0 ? 0 : row[idx] || 0
- end
-
- #filter methods are inlined here for performance
- def decode( filter_type, value, index, row, last_row, record_width )
- case filter_type
- when 0
- #no filter
- value
- when 1
- #left
- (value + fetch_pixel(index - record_width, row)) % 256
- when 2
- #left
- (value + fetch_pixel(index, last_row)) % 256
- when 3
- #avg
- (value + ( (fetch_pixel(index - record_width, row) + fetch_pixel(index, last_row)) / 2 ).floor) % 256
- when 4
- #paeth
- left = fetch_pixel(index - record_width, row)
- above = fetch_pixel(index, last_row)
- upper_left = fetch_pixel(index - record_width, last_row)
-
- pr = paeth_predictor( left, above, upper_left )
-
- (value + pr) % 256
- else
- raise "Invalid filter type (#{filter_type})"
- end
- end
- def encode( filter_type, value, index, row, last_row, record_width )
- case filter_type
- when 0
- value
- when 1
- #left
- (value - fetch_pixel(index - record_width, row)) % 256
- when 2
- #up
- (value - fetch_pixel(index, last_row)) % 256
- when 3
- #avg
- (value - ( (fetch_pixel(index - record_width, row) + fetch_pixel(index, last_row)) / 2 ).floor) % 256
- when 4
- #paeth
- left = fetch_pixel(index - record_width, row)
- above = fetch_pixel(index, last_row)
- upper_left = fetch_pixel(index - record_width, last_row)
-
- pr = paeth_predictor( left, above, upper_left )
- (value - pr) % 256
- else
- raise "Filter type (#{filter_type}) is not supported"
- end
- end
-
- private
-
- def paeth_predictor( left, above, upper_left )
- p = left + above - upper_left
- pa = (p - left).abs
- pb = (p - above).abs
- pc = (p - upper_left).abs
-
- pr = upper_left
- if ( pa <= pb and pa <= pc)
- pr = left
- elsif (pb <= pc)
- pr = above
- end
- pr
- end
- end
- end
-end
View
26 lib/css-spriter/png/idat.rb
@@ -1,26 +0,0 @@
-module PNG
- class IDAT < Chunk
- # I don't like that @compressed contains different values depending on how you're using it
- # maybe we should introduce a builder?
- def initialize( uncompressed="" )
- @compressed = ""
- @compressed += Zlib::Deflate.deflate( uncompressed.pack("C*") ) unless uncompressed == ""
- end
-
- def <<( data )
- @compressed << data
- end
-
- def encode
- @compressed
- end
-
- def uncompressed
- @uncompressed ||= Zlib::Inflate.inflate( @compressed ).unpack("C*")
- end
-
- def chunk_name
- "IDAT"
- end
- end
-end
View
9 lib/css-spriter/png/iend.rb
@@ -1,9 +0,0 @@
-module PNG
- class IEND < Chunk
- def encode; "" end
-
- def chunk_name
- "IEND"
- end
- end
-end
View
34 lib/css-spriter/png/ihdr.rb
@@ -1,34 +0,0 @@
-module PNG
- class IHDR < Chunk
- SUPPORTED_COLOR_TYPES = [2,3,6]
- attr_accessor :width, :height, :depth, :color_type
- # attr_accessor :compression_method, :filter_method, :interlace_method
-
- def self.new_from_raw( data )
- raw = data.unpack("N2C5")
-
- new( *raw[0..6] )
- end
-
- def initialize( width, height, depth=8, color_type=2, compression=0, filter=0, interlace=0 )
- raise "for now, css-spriter only supports non-interlaced images" unless interlace == 0
- raise "for now, css-spriter only supports images with a bit depth of 8" unless depth == 8
- unless SUPPORTED_COLOR_TYPES.include? color_type
- raise "for now, css-spriter only supports color types #{SUPPORTED_COLOR_TYPES.JOIN(',')} color type was #{color_type}"
- end
- @width, @height, @depth, @color_type = width, height, depth, color_type
- end
-
- def encode
- to_a.pack("N2C5")
- end
-
- def to_a
- [@width, @height, @depth, @color_type, 0, 0, 0]
- end
-
- def chunk_name
- "IHDR"
- end
- end
-end
View
153 lib/css-spriter/png/image.rb
@@ -1,153 +0,0 @@
-module PNG
- class Image
- #color types
- RGB = 2
- RGBA = 6
-
- class << self
- def image_data( file_name, options={} )
- image_options = {:rgba => true}.merge( options )
-
- png = open(file_name)
-
- return png.to_image unless image_options[:rgba]
- png.to_image.to_rgba
- end
-
- def open( file_name )
- name = File.basename( file_name, ".png" )
-
- File.open(file_name, "r") do |f|
- ihdr, idat = Parser.go!( f )
- Image.new( ihdr, idat, name )
- end
- end
-
- def write( file_name, data, options = {} )
- ihdr = PNG::IHDR.new(data.width, data.height, 8, color_type_of(data.pixel_width))
-
- Image.new(ihdr, nil, file_name, :rows => data).write( file_name, options)
- end
-
- def default_filter_type
- 4 # paeth
- end
-
- private # class methods
-
- def color_type_of(pixel_width)
- case pixel_width
- when 3
- RGB
- when 4
- RGBA
- end
- end
- end
-
- def initialize( ihdr, idat, name, options = {} )
- @ihdr = ihdr
- @idat = idat
- @name = name
- @rows = options[:rows]
- end
-
- attr_reader :name
- def width; @ihdr.width end
- def height; @ihdr.height end
- def depth; @ihdr.depth end
- def color_type; @ihdr.color_type end
- def uncompressed; @idat.uncompressed end
-
- def write(file_name, options={})
- filter_type = options[:filter_type] || Image.default_filter_type
- File.open(file_name, 'w') do |f|
- f.write(generate_png( filter_type ))
- end
- end
-
- # check for RGB or RGBA
- def pixel_width
- ( color_type == RGB ? 3 : 4)
- end
-
- def filter_encoded_rows(filter_type)
- out = Array.new(height)
- rows.each_with_index do |row, scanline|
- last_row = rows.last_scanline(scanline)
- out[scanline] = encode_row( row, last_row, filter_type, pixel_width)
- end
- out
- end
-
- def to_image
- uncompressed = @idat.uncompressed
-
- #scanline_width - 1 because we're stripping the filter bit
- n_out = CssSpriter::ImageData.new(:scanline_width => scanline_width - 1,
- :pixel_width => pixel_width,
- :name => self.name,
- :data => Array.new(height))
- offset = 0
- height.times do |scanline|
- end_row = scanline_width + offset
- row = uncompressed.slice(offset, scanline_width)
- n_out[scanline] = decode(scanline, row, n_out, pixel_width)
- offset = end_row
- end
- n_out
- end
-
- def to_s
- inspect
- end
-
- def inspect
- "#{@name} (#{height} x #{width}) [color type: #{color_type}, depth: #{depth}]"
- end
-
- private
-
- def scanline_width
- # + 1 adds filter byte
- (width * pixel_width) + 1
- end
-
- def rows
- @rows ||= to_image
- end
-
- def decode(current, row, data, pixel_width)
- filter_type = row.shift
- decode_row(row, data.last_scanline(current), filter_type, pixel_width)
- end
-
- def decode_row(row, last_scanline, filter_type, pixel_width)
- o = Array.new(row.size)
- row.each_with_index do |byte, i|
- o[i] = Filters.decode(filter_type, byte, i, o, last_scanline, pixel_width)
- end
- o
- end
-
- def encode_row( row, last_scanline, filter_type, pixel_width )
- o = Array.new(row.size)
- row.each_with_index do |byte, scanline|
- o[scanline] = Filters.encode( filter_type, byte, scanline, row, last_scanline, pixel_width)
- end
- o.unshift( filter_type )
- end
-
- def generate_png( filter_type )
- file_header = PNG::FileHeader.new.encode
- raw_data = filter_encoded_rows( filter_type )
- raw_data.flatten!
-
- ihdr = PNG::IHDR.new( width, height, depth, color_type ).to_chunk
- idat = PNG::IDAT.new( raw_data ).to_chunk
- iend = PNG::IEND.new.to_chunk
-
- file_header + ihdr + idat + iend
- end
- end
-end
View
54 lib/css-spriter/png/parser.rb
@@ -1,54 +0,0 @@
-module PNG
- class Parser
- def self.go!(file)
- #TODO: Wanted to remove instance go! and use initialize, didn't work.
- #Weird
- Parser.new.go!(file)
- end
- def go!( file )
- check_header( file )
-
- while(not file.eof?) do
- parse_chunk(file)
- end
-
- [ @ihdr, @idat ]
- end
-
- private
- def check_header( file )
- header = file.read(8)
- raise "Invalid PNG file header" unless ( header == FileHeader.new.encode)
- end
-
- def parse_chunk(f)
- len = f.read(4).unpack("N")
- type = f.read(4)
- data = f.read(len[0])
- crc = f.read(4)
-
- raise "invalid CRC for chunk type #{type}" if crc_invalid?( type, data, crc )
-
- handle(type, data)
- end
-
- def handle(type, data)
- case(type)
- when "IHDR"
- @ihdr = PNG::IHDR.new_from_raw( data )
- @width, @height, @depth, @color_type = @ihdr.to_a
- when "IDAT"
- @idat ||= PNG::IDAT.new
- @idat << data
- when "IEND"
- # NOOP
- else
- #puts "Ignoring chunk type #{type}"
- end
- end
-
- def crc_invalid?( type, data, crc )
- [Zlib.crc32( type + data )] != crc.unpack("N")
- end
- end
-end
View
28 lib/css-spriter/sprite.rb
@@ -1,5 +1,4 @@
class Sprite
- class ImageFormatException < Exception; end
attr_reader :images, :max_height
def initialize
@@ -8,18 +7,12 @@ def initialize
end
def append( image )
- @images.each do |i|
- unless i.compatible? image
- raise ImageFormatException.new("Image #{i} not compatible with #{image}")
- end
- end
-
@images << image
@max_height = @images.map{ |i| i.height }.max
end
def append_file( filename )
- append( PNG::Image.image_data( filename ))
+ append( CssSpriter::Image.from_file( filename ))
end
def locations
@@ -34,10 +27,19 @@ def locations
def write( output_filename )
return if @images.empty?
- right_sized = @images.map{|i| i.fill_to_height(@max_height)}
- # head is the last image, then we merge left
- head, *tail = right_sized.reverse
- result = tail.inject( head ){ |head, image| head.merge_left( image ) }
- PNG::Image.write( output_filename, result )
+
+ sprite_height = @images.map{ |i| i.height }.max
+ sprite_width = @images.inject(0){|sum, image| sum + image.width }
+
+ sprite = ChunkyPNG::Image.new(sprite_width, sprite_height)
+
+ current_x = 0
+
+ images.each do |image|
+ sprite.replace(image, current_x, 0)
+ current_x += image.width
+ end
+
+ sprite.save( output_filename, :best_compression )
end
end
View
11 spec/builders/image_builder.rb
@@ -8,16 +8,11 @@ def initialize( general_options={} )
@general_options = default_options.merge general_options
end
- def data(width, height)
- Array.new((width * height * 3) + height).fill(0)
- end
-
def build( specific_options={} )
args = @general_options.merge specific_options
-
- ihdr = PNG::IHDR.new( args[:width], args[:height] )
- idat = PNG::IDAT.new( args[:data] || data(args[:width], args[:height]) )
- PNG::Image.new( ihdr, idat, args[:name] )
+ image = CssSpriter::Image.new( args[:width], args[:height], ChunkyPNG::Color::TRANSPARENT )
+ image.name = args[:name]
+ image
end
end
View
63 spec/image_data_spec.rb
@@ -1,63 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
-
-describe CssSpriter::ImageData do
- before do
- data = [[1,2,3],
- [4,5,6]]
- @id = CssSpriter::ImageData.new(:scanline_width => 3, :pixel_width => 3, :data => data)
- end
-
- it "can fill to a specified height" do
- result = @id.fill_to_height(3)
- result.should == [[1,2,3], [4,5,6], [0,0,0]]
- end
- it "has scanline width and pixel width attributes" do
- @id.scanline_width.should == 3
- @id.pixel_width.should == 3
- end
-
- it "can give you any arbitrary row in the data set" do
- @id[0].should == [1,2,3]
- @id.scanline(0).should == [1,2,3]
- end
-
- it "has an empty array by default" do
- id = CssSpriter::ImageData.new
- id.empty?.should be_true
- end
-
- it "should return nil when asked for an index that doesn't exist" do
- id = CssSpriter::ImageData.new
- id[0].should be_nil
- end
-
- it "can be assigned a row" do
- @id[0] = [1,2,3]
- @id[0].should == [1,2,3]
- end
-
- it "behaves like an array" do
- @id << [1,2,3]
- @id.last.should == [1,2,3]
-
- @id.size.should == 3
- end
-
- it "will return the last scanline given a current index" do
- @id.last_scanline(1).should == [1,2,3]
- end
-
- describe "RGBA conversion" do
- it "updates pixel width" do
- @id.to_rgba.pixel_width.should == 4 # RGBA pixel width
- end
-
- it "updates scanline width" do
- @id.to_rgba.scanline_width.should == 4
- end
-
- it "puts in an alpha byte with a default value of 255" do
- @id.to_rgba[0].should == [1,2,3,255]
- end
- end
-end
View
73 spec/integration_spec.rb
@@ -1,28 +1,5 @@
-require 'benchmark'
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
-describe 'PNG' do
- before do
- @img_dir = File.dirname(__FILE__) + '/images'
- @expected_dir = File.dirname(__FILE__) + '/expected_output'
- @tmp_dir = File.dirname(__FILE__) + '/tmp'
- end
-
- it 'can read and write a PNG' do
- img = PNG::Image.open("#{@img_dir}/lightening.png")
- img.write("#{@tmp_dir}/write_test.png", :filter_type => 0)
- read("#{@expected_dir}/write_test.png").should == read("#{@tmp_dir}/write_test.png")
- end
-
- it 'can merge one PNG on the left of another' do
- one = PNG::Image.image_data("#{@img_dir}/lightening.png", :rgba => false)
- two = PNG::Image.image_data("#{@img_dir}/lightening.png", :rgba => false)
- merged = one.merge_left two
- PNG::Image.write("#{@tmp_dir}/merge_right_test.png", merged, :filter_type => 0)
- read("#{@expected_dir}/merge_right_test.png").should == read("#{@tmp_dir}/merge_right_test.png")
- end
-end
-
describe "Dir sprite" do
before :all do
@dir = File.dirname(__FILE__) + "/sprite_dirs/words"
@@ -32,114 +9,114 @@
@spriter.write
end
- after :all do
+ after :all do
@spriter.cleanup
end
- describe "Sprite generation" do
- it "provides the correct dir name" do
+ describe "Sprite generation" do
+ it "provides the correct dir name" do
@spriter.dir_name.should == 'words'
end
- it "find all the pngs in a directory" do
+ it "find all the pngs in a directory" do
expected = ['latitude.png', 'of.png', 'set.png', 'specified.png']
images = @spriter.images
images.map{|f| f.split('/').last}.should == expected
end
- it "sprites all the images in a directory" do
+ it "sprites all the images in a directory" do
File.exists?(@sprite_file).should be_true
end
end
- describe "CSS fragments" do
- before :all do
+ describe "CSS fragments" do
+ before :all do
@template = @dir + "/template.css"
@css = @spriter.css
end
- after do
+ after do
File.delete(@template) rescue nil
end
- it "should compose class names" do
+ it "should compose class names" do
@css.should include( ".words_latitude")
@css.should include( ".words_of" )
end
- it "has the correct image path" do
+ it "has the correct image path" do
@css.should include( "/sprite_dirs/words/sprite.png" )
end
- it "should write css fragments for a sprite" do
+ it "should write css fragments for a sprite" do
File.exists?(@css_file).should be_true
end
- it "can be overidden by including a template.css in the sprite directory" do
+ it "can be overidden by including a template.css in the sprite directory" do
File.open(@template, 'w'){|f| f.write("override")}
@spriter.write
@spriter.css.should include("override")
end
end
end
-describe 'Stylesheet generator' do
- before :all do
+describe 'Stylesheet generator' do
+ before :all do
@dir = File.dirname(__FILE__) + "/css_fragments"
@out = @dir + "/complete.css"
@builder = StylesheetBuilder.new(@dir)
@builder.output_file(@out)
@css = @builder.css
end
- after :all do
+ after :all do
@builder.cleanup
end
- it "takes the css fragments and concatonates them into a single stylesheet" do
+ it "takes the css fragments and concatonates them into a single stylesheet" do
@css.should include( ".some_style" )
end
- it "can handle nested folder structures" do
+ it "can handle nested folder structures" do
@css.should include( ".deep" )
end
- it "writes the css file to the specified location" do
+ it "writes the css file to the specified location" do
@builder.write
File.exists?(@out).should be_true
end
end
-describe "Complete spriting process" do
- before :all do
+describe "Complete spriting process" do
+ before :all do
@dir = File.dirname(__FILE__) + "/sprite_dirs"
@css_file = @dir + "/sprite.css"
@spriter = CssSpriter::Processor.new(:path_prefix => "/images", :source => @dir, :css_file => @css_file)
@spriter.write
end
- after :all do
+ after :all do
@spriter.cleanup
#making sure it cleans things up - shitty place for these
File.exists?(@css_file).should be_false
File.exists?(@dir + "/words/sprite.png").should be_false
end
- it "prepends a path prefix to all sprites in the css file" do
+ it "prepends a path prefix to all sprites in the css file" do
file = read(@css_file)
file.should include("/images/sprite_dirs/words")
end
- it "can find all the sprite directories" do
+ it "can find all the sprite directories" do
dirs = @spriter.directories.map{|d| d.split('/').last}
dirs.should include( "words" )
end
- it "generates the css file at the appropriate location" do
+ it "generates the css file at the appropriate location" do
File.exists?(@css_file).should be_true
end
- it "creates sprites/css for all subfolders" do
+ it "creates sprites/css for all subfolders" do
File.exists?(@dir + "/words/sprite.png").should be_true
File.exists?(@dir + "/words/fragment.css").should be_true
end
View
31 spec/lib/chunky_sprite_spec.rb
@@ -1,31 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
-
-describe ChunkySprite do
- before :each do
- @sprite = ChunkySprite.new
- @builder = ImageBuilder.new
-
- #TODO - We should just create ImageData objects here
- @image1 = @builder.build( :width => 50, :height => 50, :name => "image1").to_image
- @image2 = @builder.build( :width => 50, :height => 50, :name => "image2").to_image
- end
-
- it "knows the location of each image in the sprite" do
- @sprite.append( @image1 )
- @sprite.append( @image2 )
-
- @sprite.locations[@image1.name.to_sym].should == {:x => -( 0 ), :width=> @image1.width, :height => @image1.height }
- @sprite.locations[@image2.name.to_sym].should == {:x => -( @image2.width ), :width=> @image2.width, :height => @image2.height }
- end
-
- it "knows the height of the tallest image" do
- max_height = 70
-
- @image3 = @builder.build( :width => 50, :height => max_height, :name => "image3")
-
- @sprite.append( @image1 )
- @sprite.append( @image3 )
-
- @sprite.max_height.should == max_height
- end
-end
View
8 spec/lib/css_spriter_image_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+
+describe CssSpriter::Image do
+ it "sets the name with the filename of the image" do
+ image = CssSpriter::Image.from_file( File.dirname(__FILE__) + '/../images/lightening.png')
+ image.name.should == 'lightening'
+ end
+end
View
10 spec/lib/file_header_spec.rb
@@ -1,10 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
-
-describe PNG::FileHeader do
- # the pnd header provides sanity checks against most common file transfer errrors
- it "outputs the PNG header" do
- header = PNG::FileHeader.new.encode
- header.should == [137, 80, 78, 71, 13, 10, 26, 10].pack("C*")
- end
-end
-
View
31 spec/lib/idat_spec.rb
@@ -1,31 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
-
-describe PNG::IDAT do
- before :each do
- # it's just "Hello, World!" encoded
- @data = "x\234\363H\315\311\311\327Q\b\317/\312IQ\004\000\037\236\004j"
- end
-
- it "accepts compressed data" do
- @idat = PNG::IDAT.new
-
- @idat << @data
-
- @idat.encode.should == @data
- end
-
- it "can chunk its self" do
- @idat = PNG::IDAT.new
- @idat << @data
- @chunk = chunk( "IDAT", @idat.encode )
-
- @idat.to_chunk.should == @chunk
- end
-
- it "accepts uncompressed data for it's constructor" do
- @idat = PNG::IDAT.new( "Hello, World!".unpack("C*") )
-
- @idat.encode.should == @data
- end
-
-end
View
43 spec/lib/ihdr_spec.rb
@@ -1,43 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
-
-describe PNG::IHDR do
- before :each do
- @width = 40
- @height = 40
- @bit_depth = 8
- @color_type = 2
-
- @raw = [@width, @height, @bit_depth, @color_type, 0, 0, 0].pack("N2C5")
- @chunk = chunk( "IHDR", @raw )
- end
-
- it "pulls out the width from the ihdr block" do
- @header = PNG::IHDR.new_from_raw( @raw )
- @header.width.should == @width
- end
-
- it "pulls out the height from the ihdr block" do
- @header = PNG::IHDR.new_from_raw( @raw )
- @header.height.should == @height
- end
-
- it "pulls out the bit depth from the ihdr block" do
- @header = PNG::IHDR.new_from_raw( @raw )
- @header.depth.should == @bit_depth
- end
-
- it "pulls out the color type from the ihdr block" do
- @header = PNG::IHDR.new_from_raw( @raw )
- @header.color_type.should == @color_type
- end
-
- it "encodes it's self properly" do
- @header = PNG::IHDR.new_from_raw( @raw )
- @header.encode.should == @raw
- end
-
- it "should be able to make a header chunk" do
- @header = PNG::IHDR.new_from_raw( @raw )
- @header.to_chunk.should == @chunk
- end
-end
View
42 spec/lib/image_spec.rb
@@ -1,42 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
-
-describe PNG::Image do
- before :each do
- @sprite = Sprite.new
-
- @builder = ImageBuilder.new
-
- # 0 is the filter type for the row, then an RGB triplet since builder defaults to color type 2
- @image1 = @builder.build( :width => 1, :height => 1, :name => "image1", :data => [0,1,2,3] )
- @image2 = @builder.build( :width => 1, :height => 1, :name => "image2", :data => [0,4,5,6] )
- end
-
- it "can merge left" do
- result = @image1.to_image.merge_left @image2.to_image
-
- result.should == [[4,5,6,1,2,3]]
- end
-
- it "can encode the rows with filter 0" do
- @image1.filter_encoded_rows(0).should == [[0, 1, 2, 3]]
- end
-
-
- it "can encode the rows with filter 1" do
- image = @builder.build( :width => 2, :height => 1, :name => "image1", :data => [0,1,2,3,4,5,6] )
-
- # filter byte of 1
- # first byte of pixel 2 - pixel 1 is 3
- # second byte of pixel 2 - pixel 1 is 3.. etc
- image.filter_encoded_rows(1).should == [[1, 1, 2, 3, 3, 3, 3]]
- end
-
- it "can encode the rows with filter 2" do
- image = @builder.build( :width => 2, :height => 2, :name => "image1",
- :data => [0,1,2,3,4,5,6,
- 0,0,0,0,0,0,0])
- result = image
- # filter byte of 2
- result.filter_encoded_rows(2).should == [[2, 1, 2, 3, 4, 5, 6], [2, 255, 254, 253, 252, 251, 250]]
- end
-end
View
13 spec/lib/parser_spec.rb
@@ -1,13 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
-require 'stringio'
-
-describe PNG::Parser do
- it "errors out when the file header is wrong" do
- bad_header = [5, 80, 78, 71, 13, 10, 26, 10].pack("C*")
- file = StringIO.new( bad_header)
-
- lambda {
- Parser.go!( file )
- }.should raise_error
- end
-end
View
12 spec/lib/sprite_spec.rb
@@ -5,9 +5,8 @@
@sprite = Sprite.new
@builder = ImageBuilder.new
- #TODO - We should just create ImageData objects here
- @image1 = @builder.build( :width => 50, :height => 50, :name => "image1").to_image
- @image2 = @builder.build( :width => 50, :height => 50, :name => "image2").to_image
+ @image1 = @builder.build( :width => 50, :height => 50, :name => "image1")
+ @image2 = @builder.build( :width => 50, :height => 50, :name => "image2")
end
it "can merge an image to the right" do
@@ -35,11 +34,4 @@
@sprite.max_height.should == max_height
end
-
- it "accepts file names to append to the sprite" do
- PNG::Image.should_receive(:image_data).with("dog.png").and_return(@image1)
-
- @sprite.append_file( "dog.png" )
- end
-
end
View
2 spec/spec_helper.rb
@@ -1,8 +1,10 @@
require 'rspec'
require 'rspec/autorun'
+require 'chunky_png'
require 'css-spriter'
+
require 'builders/image_builder'
RSpec.configure do |config|

0 comments on commit 01e77a7

Please sign in to comment.
Something went wrong with that request. Please try again.