Coder Social home page Coder Social logo

spritemapper's Introduction

Spritemapper

Homepage

http://yostudios.github.com/Spritemapper/

Authors

Yo Studios <[email protected]>

Spritemapper is an application that merges multiple images into one and generates CSS positioning for the corresponding slices.

The package consists of a simple command-line tool that "does the job" and a Python library including its own PNG and CSS parser. The choice of writing/bundling this was to stay off 3rd-party requirements. Anybody who has ever had the pleasant job of installing PIL on various platforms should have a pretty good idea about what we're trying to avoid.

There are multiple alternatives to Spritemapper, but they all require a bit too much manual labour, whereas Spritemapper reads your current CSS, replacing background images and position with the generated result.

This technique drastically improves your website's loading speed, effectively reducing bandwidth by downloading fewer images.

Spritemapper in action

Here's a simple example illustrating what Spritemapper will do with your CSS:

.emote.smile {
  background: red url(../img/emoticons/smile.png) no-repeat;
}
.emote.grin {
  background: white url(../img/emoticons/grin.png) no-repeat;
}

turns into:

.emote.smile {
  background: red url(../img/emoticons.png) no-repeat 0 0;
}
.emote.grin {
  background: white url(../img/emoticons.png) no-repeat 0 -16px;
}

Check our homepage for real life examples.

Usage

-h, --help

show a help message and exit

-c INI, --conf=INI

read base configuration from INI (see Configuration options)

--padding=N

keep N pixels of padding between sprites

Configuration options

Configuration options can be specified in one of two ways: inline in the CSS, or using passing an INI file with defaults. For CSS it looks something like:

/* spritemapper.output_css = foofile.css

You can do the exact equivalent using an INI file, like this:

[spritemapper]
output_css = foofile.css

It's important to note that all paths are relative to the CSS file being processed.

base_url

a url at which the resulting css and image files can be reached. by default uses file-relative paths (recommended).

sprite_dirs

a list of directories within which to allow spritemaps to be generated. by default all directories are eligible.

recursive

set if sub-spritemaps should be generated when sub-directories are found. set by default.

output_image

the name of output spritemap image. sprite_dirs is incompatible with this because both tell the spritemapper how to sort sprites into spritemaps. by default <dir> + .png.

output_css

the name for the rewritten CSS file. by default sm_{basename}{extension}.

padding

amount of padding space between two images. this is mostly useful to counteract subpixel rendering artifacts on iOS devices. by default 1.

anneal_steps

a larger number here makes the box packer algorithm try more combinations. by default 9200.

Running tests

The test suite requires Nose. You can run them through setup.py, python setup.py test or plain nosetests.

spritemapper's People

Contributors

jbergstroem avatar jnordberg avatar lericson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spritemapper's Issues

Parallelize work done by spritemapper

Some things such as annealing and reading image sizes could be parallelized on modern-day CPUs. multiprocessing.cpu_count() could help us figure out number of cores (>=python 2.6), but I'm not sure if multiprocessing is the right tool for doing the actual work? This is not a massively scalable web server, so I guess a couple of forks would do the job. Opinions? (fyi, multiprocessing is backported to 2.4,2.5 as well: http://pypi.python.org/pypi/multiprocessing/ )

Absolute paths should be spritemappable

A not very uncommon case is the following

.foo { background: url("/img/sprites/foo.png"); }
.bar { background: url("/img/sprites/bar.png"); }
.qux { background: url("/img/sprites/qux.png"); }

We should be able to support this by figuring out the DocumentRoot (this is a great keyword for PHP newbies.) Perhaps something along the lines of

/* spritemapper.web_root = .. */

This would, like everything else, be relative to the CSS file. It would make a lot more sense to pass this as a command-line option.

Single-line declarations fail

The parser seems to bail on single-line declarations

This causes a problem: body { line-height: 1 }

While this is valid: body { line-height: 1; }

Optimize your CSS

I haven't tried it yet but I was looking at your CSS on your homepage and you could optimize it a bit. Instead of declaring the background image multiple times just do it once in the "letter" class like so:

.letter {
  background: url(../img/awesome-font.png);
}
.letter.a {
  width: 22px; height: 17px;
  background-position: -x -y;
}
.letter.b {
   width: 15px; height: 17px;
   background-position: -x -y;
}
.letter.c {
   width: 16px; height: 17px;
   background-position: -x -y;
}

Great tool by the way!

spritecss.png.FormatError: FormatError: PNG file has invalid signature.

Please change the error message to display the invalid file.

More often than not (as reported in other issues), the following error message is issued:

spritecss.png.FormatError: FormatError: PNG file has invalid signature.

It is not helpful as it is unrelated to the actual error. It seems to indicate a parsing error on an unsupported image format, sometimes. But other issues seem to indicate that it can happen when a parse error occurs on a background: stanza. I've tried numerous combinations of my CSS input file and always got the same error message. I used strace to try to guess where it failed but did not get more information. I tried --verbose which reported to use a number of files but did not report which would be invalid.

I eventually removed the jpg file and it solved the problem.

I hope the short storry of my frustrating experience will inspire someone to produce a patch that displays a clear error message such as "XXX.jpg : unsupported file format" ;-)

Python 3 support

While discussed at work, this doesn't feel like the most important thing to do since no one in web development uses Python 3, but for completeness, future proof and since py3 is actually considered stable's sake - lets have it open.

Running a 2to3 against the entire repo will give:

# PYTHONPATH=build/lib nosetests3
......E...
======================================================================
ERROR: tests.test_parser.test_reprint_test_files
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.1/site-packages/nose-0.11.0.dev_r601-py3.1.egg/nose/case.py", line 177, in runTest
    self.test(*self.arg)
  File "/home/jbergstroem/Spritemapper/tests/test_parser.py", line 40, in test_reprint_test_files
    reprint(fp.read())
  File "/home/jbergstroem/Spritemapper/tests/test_parser.py", line 19, in reprint
    reprinted = "".join(parser.CSSParser(data=css).iter_print_css())
  File "/home/jbergstroem/Spritemapper/spritecss/css/parser.py", line 549, in iter_print_css
    for event in parser:
  File "/home/jbergstroem/Spritemapper/spritecss/css/parser.py", line 45, in iter_events
    self._emit_events()
  File "/home/jbergstroem/Spritemapper/spritecss/css/parser.py", line 433, in _emit_events
    self.state = self.evaluate()
  File "/home/jbergstroem/Spritemapper/spritecss/css/parser.py", line 451, in evaluate
    next(st)
  File "/home/jbergstroem/Spritemapper/spritecss/css/parser.py", line 308, in __next__
    self.token = tok = next(self.tokens)
  File "/home/jbergstroem/Spritemapper/spritecss/css/parser.py", line 216, in _css_tokenizer_lineno
    for tok in toks:
  File "/home/jbergstroem/Spritemapper/spritecss/css/parser.py", line 204, in _css_tokenizer_lvl1
    if tok.lexeme == "char" and tok.value.isspace():
AttributeError: 'int' object has no attribute 'isspace'

----------------------------------------------------------------------
Ran 10 tests in 0.044s

FAILED (errors=1)

Small bug in documentation on homepage

Hi,
in the documentation on the homepage, I believe that under the "From Source" installation part, it should be

git clone https://github.com/yostudios/Spritemapper.git — copy the source code
rather than
git clone git://github.com/yostudios/Spritemapper.git — copy the source code

Cheers
Jana

Skip unsupported image formats

We should handle FormatError's and put out a warning saying that file has ben skipped instead of halting the process.

Spritemapper on Windows w/ Python 2.7.8 not working

Hey guys.
First time using this - but having no luck:

  1. Installed Python for windows 2.7.8
  2. Set paths of pythong / scripts in PATH var
  3. Tried running and then this happened:

C:\Python27\Scripts>spritemapper c:\z\css\global.css
Traceback (most recent call last):
File "C:\Python27\Scripts\spritemapper-script.py", line 8, in
load_entry_point('spritemapper==1.0.0', 'console_scripts', 'spritemapper')()
File "C:\Python27\lib\site-packages\spritecss\main.py", line 141, in main
spritemap([css_cls.open_file(fn, conf=conf) for fn in args], conf=conf)
File "C:\Python27\lib\site-packages\spritecss\main.py", line 33, in open_file
return cls(fname, conf=CSSConfig(p, base=conf, fname=fname))
File "C:\Python27\lib\site-packages\spritecss\config.py", line 28, in init
self._data.update(iter_css_config(parser))
File "C:\Python27\lib\site-packages\spritecss\config.py", line 17, in iter_css_config
for ev in iter_events(parser, lexemes=("comment",)):
File "C:\Python27\lib\site-packages\spritecss\css\parser.py", line 43, in iter_events
self._emit_events()
File "C:\Python27\lib\site-packages\spritecss\css\parser.py", line 410, in _emit_events
self.state = self.evaluate()
File "C:\Python27\lib\site-packages\spritecss\css\parser.py", line 429, in evaluate
new = h(st)
File "C:\Python27\lib\site-packages\spritecss\css\parser.py", line 490, in _handle_declaration
"missing semicolon?" % (st,))
RuntimeError: unconsumed declaration in <CSSParseState handler=<bound method CSSParser._handle_declaration of <spritecss.css.parser.CSSParse
r object at 0x0000000002E362B0>>, prev=None, counter=42, tokens=<generator object _css_tokenizer_lineno at 0x0000000002E2DD38>, token=Token(
'block_end', '}', line_no=16, col_no=22), selector='.f_right ', declaration='float:right', at_rule='', comment='', whitespace=''>, missing s
emicolon?

I suggest to don't use relative import in SpriteMapper project

Hi,

I suggest to don't use this syntax :

from . import SpriteRef
from .config import CSSConfig
from .css import split_declaration

but use this syntax :

from spritemapper import SpriteRef
from spritemapper.config import CSSConfig
from spritemapper.css import split_declaration

Generally, I don't see and I don't use relative import.
Usual python project convention don't use relative import.

Lately, I've executed this command :

$ python ../Spritemapper/spritecss/finder.py mime.css
Traceback (most recent call last):
  File "../Spritemapper/spritecss/finder.py", line 7, in <module>
    from . import SpriteRef
ValueError: Attempted relative import in non-package

If the project don't use relative import, I would not get this error.

What do you think about this suggestion ?

I can fix it if you want ?

Regards,
Stéphane

Add option for outputting image dimensions

First off: great script! Love it! It would be a really nice feature though if Spritemapper could optionally output the original image dimensions. That way I would have to manually check and set them myself.

So for example:

example{

background: url('images/sprite.png') no-repeat 0 -186px;
width: 45px;
height: 30px;
}

PNG output, but not CSS

Hi,

Thanks for creating this app, spriting is really fiddly so this has the potential to be a massive time-saver, and of course encourage devs to use spriting for faster loading pages.

This is my first time using spritemapper but I am running into a few issues.

  1. I have reexported my image files as PNG24
  2. I have rewritten my background URL paths to use the default relative pathing
  3. I have moved all images to be sprited into a single folder

When I run the generator in Terminal (OS X 10.7.3):

  1. the sprite png is output, as a sibling of the target image folder
  2. the modified CSS file is output, as a sibling of the source CSS file, but the only modification is that an extra space is inserted before the url() parameter, eg background:url() becomes background: url(), background: url() becomes background: url() etc

Any idea what I could be doing wrong?

Thanks,
Dan

Partial handling of "background-image" property

SpriteMapper successfully detects the pictures in "background-image" CSS properties and adds them in the spritesheet, but it "forgets" to handle the "background-image" in the resulting CSS file : they are not updated to target the spritesheet PNG file, and no "background-position" is set.
The "background" properties in the same file are OK, though...

A solution could be replacing "background-image: " with "background :" in the CSS file ; but they are some cases where you really need to use "background-image " instead of "background".

Error:spritecss.main: image : not readable

thank you for taking the time and effort to create spritemapper.
this is exactly what we have been looking for,

unfortunately i am having a slight problem,

i'm specifying configuration options inline in the css,
i only have one folder of images,
but i keep getting this error:

ERROR:spritecss.main: ../go.jpg : not readable

i've checked my file paths and everything seems to be in order.

any thoughts?

ty again for your work, it's a really great tool and we'd love to use it in our production work,

Make cssutils and PIL optional dependencies to increase Spritemapper's reliability

I really appreciate the concept behind Spritemapper and also see advantages in the "zero-dependency" approach, but in practice Spritemapper runs quite fragile and with unsatisfying results:

  • For some strange reason, Spritemapper isn't capable of parsing a css statement like background: transparent url('arrow-tiny.png') no-repeat;. It took me a while of tweaking to find out that the color word transparent causes SpriteMapper to ignore the following url statement.
  • Spritemapper also failed to read some PNGs and skipped them, although they were produced using fairly common settings (PNG-ZIP) encoding.

My point: why not make cssutils (http://packages.python.org/cssutils) and PIL optional dependencies. I had good experiences parsing complex stylesheets with cssutils, and you can extract all linked images easily with cssutils.getUrls()

If a system lacks these two deps, SpriteMapper can still fall back to its internal, but more experimental CSS/PNG tools.

Support for simple repeat-x and repeat-y images

There's currently no support for spritemaps that include only images that repeat on the X or Y axis. This is simple to do, by putting all the images either vertically or horizontally respectively on the spritemap.

This should be pretty straightforward to implement and is rather useful when you're trying to have the least amount of requests.

Automation Sprites Generation

Hi Guys,

First great script !!!
I love it and I use it very often it saves so much time. Great work and thank you for sharing it us !!!

I have a question is it possible to automate the generation of the sprites by just lets say putting the images into a folder and running the application with option folder for example. By doing this let the script get the dimensions of the images and generate the css using images names as classes and the sprites. Instead of supplying the script with css file with image dimensions and class names.

I've never done anything with Python so i don't have an idea how hard that could be ! Actually I am quite new to programming. So forgive me if my question is out of tune :-D

Cheerz,
Guby

parser fails on inline @media blocks

The parser fails on

@media screen and (max-width: 1025px) {
  #block .link {
    position: relative;
  }
}

with the following error

RuntimeError: invalid transition from <CSSParseState handler=<bound method CSSParser._handle_declaration of <spritecss.css.parser.CSSParser object at 0xaf86d10>>, prev=None, counter=3, tokens=<generator object _css_tokenizer_lineno at 0xaf79aa0>, token=Token('block_begin', '{', line_no=2, col_no=16), selector='', declaration='#block .link ', at_rule='', comment='', whitespace=''>

no JPEG support

why is this only PNG? I need JPEG which gives much lower filesize for images with many colors.

"spritemapper.padding = N" in CSS file doesn't work

The "padding" option works well when I set it through the command line with the "--padding=N", but it seems to be ineffective when put in a CSS file comment.
(although "spritemapper.output_image", for example, works well)

Adding timestamp to spritemaps filenames

I think it would be useful to add a timestamp to each of the filenames of the generated spritemaps, so as to ensure that they won't be cached.

As things are now we either have to change the filename of the spritemaps manually on the configuration (and we can only do this if there isn't more than one spritemap per stylesheet) each time we generate the spritemap, or change the name of the file after it has been generated and also all the references on the stylesheets.

By adding a timestamp to all spritemaps most of this issues would be solved. I've been looking into it but I'm somewhat at a loss as to where the logic should be added, it seems as if the filenames of the maps are not centralized in one spot and that might make matters more complicated.

compact form for background is not handled

input code

div.1 {
  background: url("img/1.png") center no-repeat;
}
div.2 {
  background: url(img/2.png) ;
}

produces an identical output code, whereas

div.1 {
  background: url("public/images/explore_all.png");
}
div.2 {
  background: url(public/images/explore_places.png) ;
}

produces an expected output of

div.1 {
  background: url('img/images.png') no-repeat 0 0;
}
div.2 {
  background: url('img/images.png') no-repeat -54px 0;
}

IMO spritemapper should at least report "unsupported xxx" in cases such as this, if it cannot support it better.

fail with extjs-3.4.0

I'm trying to use spritemapper with extjs-3.40 and it "invalid transition" error.
extjs-3.4.0 can be downloaded from:
http://extjs.cachefly.net/ext-3.4.0.zip

The error I'm getting:

~/Downloads/ext-3.4.0/resources/css$ spritemapper ext-all.css
Traceback (most recent call last):
  File "/usr/local/bin/spritemapper", line 9, in <module>
    load_entry_point('spritemapper==1.0.0', 'console_scripts', 'spritemapper')()
  File "/usr/local/lib/python2.7/dist-packages/spritemapper-1.0.0-py2.7.egg/spritecss/main.py", line 141, in main
    spritemap([css_cls.open_file(fn, conf=conf) for fn in args], conf=conf)
  File "/usr/local/lib/python2.7/dist-packages/spritemapper-1.0.0-py2.7.egg/spritecss/main.py", line 33, in open_file
    return cls(fname, conf=CSSConfig(p, base=conf, fname=fname))
  File "/usr/local/lib/python2.7/dist-packages/spritemapper-1.0.0-py2.7.egg/spritecss/config.py", line 28, in __init__
    self._data.update(iter_css_config(parser))
  File "/usr/local/lib/python2.7/dist-packages/spritemapper-1.0.0-py2.7.egg/spritecss/config.py", line 17, in iter_css_config
    for ev in iter_events(parser, lexemes=("comment",)):
  File "/usr/local/lib/python2.7/dist-packages/spritemapper-1.0.0-py2.7.egg/spritecss/css/parser.py", line 43, in iter_events
    self._emit_events()
  File "/usr/local/lib/python2.7/dist-packages/spritemapper-1.0.0-py2.7.egg/spritecss/css/parser.py", line 410, in _emit_events
    self.state = self.evaluate()
  File "/usr/local/lib/python2.7/dist-packages/spritemapper-1.0.0-py2.7.egg/spritecss/css/parser.py", line 431, in evaluate
    raise RuntimeError("invalid transition from %r" % (st,))
RuntimeError: invalid transition from <CSSParseState handler=<bound method CSSParser._handle_whitespace of <spritecss.css.parser.CSSParser object at 0x136fa50>>, prev=<CSSParseState handler=None, prev=None, counter=147, tokens=<generator object _css_tokenizer_lineno at 0x1368c30>, token=Token('comment_end', '*/', line_no=74, col_no=57), selector='.x-hide-nosize,\n.x-hide-nosize *     Emulate display:none for children ', declaration='', at_rule='', comment='', whitespace=''>, counter=146, tokens=<generator object _css_tokenizer_lineno at 0x1368c30>, token=Token('char', ' ', line_no=74, col_no=22), selector='', declaration='', at_rule='', comment='', whitespace=''>

Unable to run >> Using Python 3.3 on Windows

Hey,

I am wondering if this project is still active and does it support python 3.3. I have installed the Spritemapper using the .msi files downloaded from the link provided and added the scripts as well as python directory in path.

The spritemapper is installed in C:\Python33\Scripts .. I have edited the spritemapper-script to update the version of python on line1 : #!C:\Python33\python.exe

While I am using spritemapper using command line, I am getting this following error
error

Can somebody help? This tool seems to be best option available.

I am using spritemapper in Windows 7 Ultimate with Python 3.3

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.