Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
This generates 2 css files - sprite image and a css along with a datauri css.
#! /usr/local/bin/ruby -w
# This simple program takes a bunch of images and creates a sprite image along with the corrosponding
# css. It also generates the datauri css. So, we can serve performance optimized CSS depending on the
# Browsers.
#
# Browsers which do not support datauri, like IE7 and below get the sprite image and the sprite css.
# Browsers which support datauri, get the datauri.css
#
# Usage:
#
# css = SpriteWriter.new('/path/to/sprite/images', '/path/to/generated/sprite.img', '/path/to/generated/css')
# css.generate
#
# Creator: Jiren Patel.
#
require 'rubygems'
require 'RMagick'
require 'rvg/rvg'
require 'base64'
require 'pathname'
class SpriteWriter
attr_reader :dir, :image_path, :image_positions, :image_list, :css_path
attr_reader :height, :width
def initialize(dir = 'public/images/sprites', image_path = 'public/images', css_path = "public/stylesheets")
@dir = dir
@image_path = image_path
@css_path = css_path
@image_list = nil
@file_list = []
end
def generate
load_files
image_writer
css_writer
datauri_writer
end
private
def load_files
dir_path = File.expand_path(dir) + "/*"
Dir[dir_path].each do |file|
if file =~ /\.(png|gif|jpg|jpeg)$/
img = Magick::ImageList.new(file) rescue nil
if img
@file_list << file
@image_list ? @image_list << img.first : @image_list = img
end
end
end
@height = @width = 0
@image_list.each do |img|
@height = @height + img.page.height + 10
@width = img.page.width if img.page.width > @width
end
@height += 50
@width += 50
end
def image_writer
start_y = 10
@image_positions = {}
rvg = Magick::RVG.new(@width, @height) do |canvas|
#canvas.background_fill = 'white'
canvas.background_fill_opacity = 0
image_list.each do |img|
canvas.image(img, img.page.width, img.page.height, 10, start_y)
image_file = File.basename(img.filename).split('.').first
@image_positions[image_file] = [img.page.width, img.page.height, 10, start_y]
start_y = start_y + 10 + img.page.height
end
canvas.text(10, start_y + 20, "Created by Jiren")
end
rvg.draw.write(@image_path + '/sprite.png')
end
def css_writer
f = File.new(css_path + '/sprite.css', 'w')
img_str = ""
image_positions.each do |key, value|
img_str << ".#{key},"
end
f.puts img_str[0, img_str.length - 1].to_s
f.puts "{ background: url(/images/sprite.png) no-repeat top left; }"
image_positions.each do |key, value|
f.puts ".#{key} {background-position: -#{value[2]}px -#{value[3]}px; width:#{value[0]}px; height:#{value[1]}px;}"
end
f.close
end
def datauri_writer
f = File.new(css_path + '/sprite_datauri.css', 'wb')
@file_list.each do |file|
image_path = File.basename(file).split('.').first
ext = File.basename(file).split('.').last
width_height = "width:#{@image_positions[image_path][0]}px; height:#{@image_positions[image_path][1]}px;"
if(file.size > 32767)
f.puts ".#{image_path} { background: url(/images/#{image_path}.#{ext});top left no-repeat; #{width_height}}"
else
f.puts ".#{image_path} { background :url(\"data:image/#{ext};charset=utf-8;base64,#{read_file_and_encode(file)}\");top left no-repeat; #{width_height}}"
end
end
f.close
end
def read_file_and_encode(file)
data = File.open(file, 'rb') {|f| f.read }
Base64.encode64(data).gsub(/\n/, '')
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment