{"id":15547302,"url":"https://github.com/uhop/tight-sprite","last_synced_at":"2025-07-30T05:33:14.472Z","repository":{"id":12363656,"uuid":"15012950","full_name":"uhop/tight-sprite","owner":"uhop","description":"Tight 2D rectangle packer suitable for sprites.","archived":false,"fork":false,"pushed_at":"2019-01-28T16:57:25.000Z","size":64,"stargazers_count":15,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-19T05:36:48.706Z","etag":null,"topics":["css-sprites"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uhop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-12-07T21:10:21.000Z","updated_at":"2023-06-27T18:34:03.000Z","dependencies_parsed_at":"2022-08-30T21:22:43.445Z","dependency_job_id":null,"html_url":"https://github.com/uhop/tight-sprite","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/uhop/tight-sprite","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uhop%2Ftight-sprite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uhop%2Ftight-sprite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uhop%2Ftight-sprite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uhop%2Ftight-sprite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uhop","download_url":"https://codeload.github.com/uhop/tight-sprite/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uhop%2Ftight-sprite/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267815187,"owners_count":24148356,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["css-sprites"],"created_at":"2024-10-02T13:08:35.624Z","updated_at":"2025-07-30T05:33:14.432Z","avatar_url":"https://github.com/uhop.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tight-sprite\n\n[![Build status][travis-image]][travis-url]\n[![Dependencies][deps-image]][deps-url]\n[![devDependencies][dev-deps-image]][dev-deps-url]\n[![NPM version][npm-image]][npm-url]\n\n\n\u003e Tight 2D rectangle packer suitable for sprites.\n\nThis package implements a  2D rectangle packing. It is conceived to serve as a foundation for producing CSS sprites.\nIf you are interested in efficient image asset management for your web projects, please visit our sister project:\n[grunt-tight-sprite](https://github.com/uhop/grunt-tight-sprite).\n\n## Introduction\n\n[CSS sprites][] is a techniques designed to replace multiple images with one, which combines all of them.\nThe goal is to increase the overall performance of a web application by:\n\n* Minimizing number of downloads, which is important in a high-latency scenarios.\n* Minimizing amount of data transferred, which is important for low-speed connections.\n* Optimizing memory management on a client (one vs. many objects to keep), which is important for low-powered clients.\n\nAll three points have the biggest impact on mobile platform, but are generic enough to improve all web application targets.\n\nWhile modern compression tools can produce small files even from naively made sprites, e.g.,\nall images are vertically stacked padded with a static color, this padding is essentially a wasted\nspace, but usually it can be efficiently compressed. Nevertheless at some point such sprite will reach\nits destination and will be unpacked spending 3-4 bytes per pixel regardless of how well it was\ncompressed before. Browsers retain images as long as they are visible, so typically sprites are\nlive during the life span of their web application reducing the available memory, forcing more\nfrequent runs of a garbage collector, and even forcing some applications into swapping.\n\nAssuming that all images in a sprite are necessary, the only part, which can be reduced, is a wasted\narea. The way to reduce waste is to use an efficient packing algorithm. This is the purpose of this library.\n\n##  Motivation\n\n[Packing problems](http://en.wikipedia.org/wiki/Packing_problem) are an old well-studied area of math.\nIt is fueled by real world problems: optimization of finite resources, storage, transportation, and, yes, packing.\nTypical problems are: how to minimize a number of pallets to hold a given set of objects, or how to cut\na sheet of paper into smaller pieces reducing waste and maximizing profit.\n\nSometimes real world collides with a virtual world of CSS sprites. For example, technologically certain\nmaterials can be  cut only with guillotine scissors: straight line from edge to edge. Obviously this restriction\nis not applicable for images. Or in majority of cases producers deal with predefined pallet sizes. We can make\nimages of any size for CSS sprites.\n\nIt is proven that the problem is NP-complete. In practice it means that the only way to solve it exactly is by\ntrying all possible permutations, which is possible only for a small number of rectangles, or in special\ncircumstances (e.g., all of them are of equal size). For example, *Huang and Korf* (see References below)\nreport on finding an exact solution for packing of 32 squares from 1x1 to 32x32 using their state of the art\nsolver in 33 days, 11 hours, 36 minutes, and 23 seconds. The previous record was 27 squares.\n\nGiven all that practical solutions usually use some kind of heuristics, which are not perfect, and can produce\nhilariously sub-par solutions, but relatively fast, and usually close enough to an optimal solution. Obviously\nmany heuristics were proposed since invention of computers.\n\nWhile there are plenty of tools available to produce sprites, hardly any of them are concerned with efficient\npacking. There are many variants of a naive stacking, or their variations, like a shelf packing (essentially horizontal\nstack of vertical stacks). They are clearly suboptimal. Very popular are various tree-based algorithms based\non guillotine splits. Because we don't require guillotine cuts, this built-in restriction prohibits certain\noptimizations. And of course there are some home-grown algorithms, which do not perform better than\nexisting techniques proposed by mathematicians specializing in this area, and typically inferior.\n\nThis package implements two well-known algorithms:\n\n* Maximal rectangles algorithm as described by *Jylänki* (see References below).\n  It is the main algorithm of the package.\n* Envelope algorithm as described by *Martello, Pisinger, Vigo* (see References below).\n  It is similar to what *Jylänki* calls \"Skyline\" algorithm. While this algorithm can be used on its own,\n  it is primary there to provide estimates for the maximal rectangles algorithm.\n\nBoth algorithms determine an optimal bounding rectangle size automatically.\n\n## Installation\n\n```\nnpm install tight-sprite\n```\n\n## Documentation\n\n### palletizing(rectangles, options)\n\nThis function implements the maximal rectangles algorithm. It takes an array of rectangles\n(objects with `w` and `h` positive integer properties), and an optional options object. It\nreturns a result object, which includes the achieved area size, an array of rectangles\n(similar to the input but can be rearranged), and an array of rectangle positions.\n\nExample:\n\n```js\nvar palletizing = require(\"tight-sprite/palletizing\");\n\n// let's solve 1-to-32 square problem\nvar rectangles = [];\nfor(var i = 1; i \u003c= 32; ++i){\n  rectangles.push({w: i, h: i});\n}\n\nvar result = palletizing(rectangles);\nconsole.log(\"found area: \", result.area);\nresult.layout.forEach(function(pos){\n  var rect = result.rectangles[pos.n];\n  console.log(pos.x, pos.y, rect.w, rect.h);\n});\n```\n\nArguments of `palletizing()` are:\n\n* **rectangles** -- an array of objects. You can keep anything you want in those objects,\n  but the algorithm assumes that it has positive integer properties `w` and `h` for \"width\"\n  and \"height\" correspondingly. The algorithm may add additional properties: `i`, `group`,\n  `area`. Everything else should be safe.\n* **options** -- an optional object. If present it may specify following properties:\n  * **silent** -- a boolean value. If truthy, it suppresses all console-bound output. Default: `false`.\n\nThe returned object has following properties:\n\n* **area** -- a positive integer, which indicates what area was achieved. The whole point of\n  the algorithm is to pack all rectangles minimizing this value.\n* **w** -- a positive integer, indicating the width of the resulting area.\n* **h** -- a positive integer, indicating the height of the resulting area.\n* **rectangles** -- an array of objects similar to the corresponding input argument. It points\n  to the same objects, but they order can be different.\n* **layout** -- an array of position objects with following properties:\n  * **n** -- an integer. It is an index of a rectangle in **rectangles**, which corresponds to\n    this position.\n  * **x** -- a positive integer, which is a horizontal coordinate of a rectangle's left.\n  * **y** -- a positive integer, which is a vertical coordinate of a rectangle's top.\n\n## Demo\n\nThe 32 squares problem, which was described above, is included as a test,\nbut in a slightly different form. This is how it looks when it runs:\n\n```\n$ time node tests/test_squares.js\nPacking 32 rectangles using the maximal rectangles algorithm.\nFound rectangle 469 by 32 wasting 1616 pixels.\nFound rectangle 407 by 33 wasting 1496 pixels.\nFound rectangle 317 by 43 wasting 1331 pixels.\nFound rectangle 296 by 45 wasting 935 pixels.\nFound rectangle 274 by 47 wasting 404 pixels.\nFound rectangle 236 by 51 wasting 392 pixels.\nFound rectangle 231 by 51 wasting 341 pixels.\nThe best solution with the maximal rectangles algorithm wasted 341 pixels.\nBEST:  width: 231, height: 51, waste: 341 (2.89%)\nIDEAL: width: 135, height: 85, waste: 35 (0.31%)\n\nreal  0m0.309s\nuser  0m0.295s\nsys 0m0.016s\n```\n\nYou can see the trade-off: it runs in a sub-second time instead of 33+ days, but it wastes slightly more pixels.\n\n## References\n\nEric Huang and Richard E. Korf. New improvements in optimal rectangle packing.\nIJCAI'09 Proceedings of the 21st international jont conference on Artifical intelligence. Pages 511-516.\n\nSilvano Martello, David Pisinger, Daniele Vigo. The Three-Dimensional Bin Packing Problem.\nOperations Research, Volume 48 Issue 2, March 2000. Pages 256-267.\n\nJukka Jylänki. A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing.\nOnline resource at http://clb.demon.fi/files/RectangleBinPack.pdf.\n\n[CSS sprites]: http://en.wikipedia.org/wiki/Sprite_(computer_graphics)#Sprites_by_CSS\n\n[npm-image]:      https://img.shields.io/npm/v/tight-sprite.svg\n[npm-url]:        https://npmjs.org/package/tight-sprite\n[deps-image]:     https://img.shields.io/david/uhop/tight-sprite.svg\n[deps-url]:       https://david-dm.org/uhop/tight-sprite\n[dev-deps-image]: https://img.shields.io/david/dev/uhop/tight-sprite.svg\n[dev-deps-url]:   https://david-dm.org/uhop/tight-sprite#info=devDependencies\n[travis-image]:   https://img.shields.io/travis/uhop/tight-sprite.svg\n[travis-url]:     https://travis-ci.org/uhop/tight-sprite\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuhop%2Ftight-sprite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuhop%2Ftight-sprite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuhop%2Ftight-sprite/lists"}