npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

groups-finder

v1.0.0

Published

Micro JS lib for finding groups in 2D grid and extracting sprites from textures atlas.

Downloads

2

Readme

groups-finder-js

A small JS utility to locate groups of common values in a 2D grid. For example you can use this to find sprites boundaries in a texture atlas (by finding "islands" of opaque pixels and treating transparent pixels as separators).

This module is geared toward textures and locating groups of pixels in them, but built with a generic design that allows it to operate on any 2D grid of values.

How it works

The groups finder uses a flood-fill algorithm to iterate and arrange values (or pixels) into groups. Each group may contain the value indices themselves (its configurable, since it requires a lot of memory to store) and the axis-aligned rectangle containing the group.

The result of the groups search is a list of Group objects, with the following fields:

  • topLeft: A point (x,y) with the top-left corner of the rectangle containing this group.
  • bottomRight: A point (x,y) with the bottom-right corner of the rectangle containing this group.
  • boundingRectangle: A minimal axis-aligned rectangle (x, y, width, height) containing the group.
  • positionsCount: How many positions were found in the group.
  • positions: List of positions found in this group, only if configured to return this value.

Install

To use this module either take the src/groups_finder.js JavaScript file and include it in your browser (everything is in a single file), or use npm install groups-finder to use it from NodeJS.

Examples

Lets show few quick examples on how to use this library.

Unpack Texture Atlas

This example show how to unpack sprites from a texture atlas, by finding groups of opaque pixels between transparent pixels which are the background. We set storePositions = false so we won't store the pixels themselves in the result, as we only care about the bounding rectangle and not all the indices.

Important to remember: since we must extract the pixels data from the image, this module will not work on cross-domain assets or files served from local filesystem directly (when you load an HTML file by clicking it instead of serving it via a server). This is due to browsers security limitations, but shouldn't be an issue for any usual use cases.

// unpack texture atlas
const groupsFinder = new GroupsFinder.GroupsFinder();
groupsFinder.storePositions = false;
const groups = groupsFinder.unpackTextureAtlas(sourceImg);

// print sprites found in texture
for (let group of groups) {
    console.log("Sprite found with source rectangle: ", group.boundingRectangle);
}

Find Color Groups

This example find groups of the same color in a texture.

// find colors groups
const groupsFinder = new GroupsFinder.GroupsFinder();
groupsFinder.storePositions = false;
const groups = groupsFinder.findColorGroups(sourceImg);

// print sprites found in texture
for (let group of groups) {
    console.log("Color groups found in texture: ", group.boundingRectangle);
}

Advanced Topics

After viewing some basic examples, lets dive into the API to learn more about this library and what we can do with it.

GroupsFinder

The main object in this library is the GroupsFinder class. This object provides the main methods to find groups + some basic configuration.

You create an instance of it like this:

const groupsFinder = new GroupsFinder.GroupsFinder();

Now lets see the configurations it supports:

  • storePositions: If true (default), result groups will also contain a list with all the indices in group. If you don't need this data, its best to set this to false (will save time and memory).
  • walkDiagonally: If true (default), will also consider diagonal neighbors in the grouping process.
  • limitResultsCount: If defined with a value > 0, will limit max results returned to this value. If exceed the limit, an exception will be thrown (with the results we already found attached as 'results').

And to actually use this object, there are 3 main public methods to call:

  • unpackTextureAtlas(image, opacityThreshold = 10): Find groups of pixels in a texture atlas (unpack it to sprites data).
  • findColorGroups(image, opacityThreshold = 10): Find groups of the same color in a texture.
  • findGroups(grid): A generic method to find groups in any type of 2D grid, not necessarily images. To understand how it works, lets continue and read about the IGrid interface (which is the grid param this method gets) and how to use it.

IGrid

Most of this library logic is implemented inside findGroups(grid), which relies on an IGrid object to provide information about the 2D grid and how we compare and extract values from it.

The other main methods unpackTextureAtlas() and findColorGroups() actually use findGroups(grid) internally, with a built-in IGrid implementation that support images as input for the 2D grid.

Now lets take a look at the IGrid interface and what we need to implement in it:

  • get width(): A getter that return your grid width. Must not change mid-execution.
  • get height(): A getter that return your grid height. Must not change mid-execution.
  • getValue(x, y): A method that returns a value from grid in a given x,y index, or null to represent out-of-bounds or "holes" in the grid that you don't want to group with anything.
  • sameGroup(a, b): A method that receive two values from grid and decide if they should be in the same group or not. Default implementation is a === b, but you can override this to add more sophisticated logic (for example consider similar values as the same group, instead of strict equal values).

To use images with the algorithm this module provides a built-in grid implementation called TextureGrid, that knows how to handle images and extract their pixels data.

As you can see, by implementing your own IGrid type you can define your own comparison logic and a way to extract values, making this library flexible and useable for many purposes.

License

This library is distributed with the free MIT license.