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 🙏

© 2026 – Pkg Stats / Ryan Hefner

seamless-texture

v0.2.0

Published

Join opposite texture edges without mirroring or blended pixels.

Readme

seamless-texture

Join the opposite edges of a texture without mirroring or blended pixels.

Features

  • materialRepeat joins a square RGB texture through low-error seams.
  • seamlessMaterialTile feathers the opposite edges of an image into each other.
  • batchMaterialTiles tiles many PNG buffers in one call with bounded concurrency.
  • normalMapFromTile builds a tangent-space normal map from the luminance height field.
  • roughnessMapFromTile builds a grayscale roughness map from the luminance.
  • displaceMaterialSurface offsets texture pixels along a blurred height field.
  • Tile presets (fabric, leather, wood) bundle the real tile options.
  • The seamless-texture CLI tiles files from the command line.
  • materialRepeat never mirrors, rotates, or blends pixels. seamlessMaterialTile feathers only the edge overlap.

Install

npm install seamless-texture

Node.js 22 or later is required. The sharp helpers need sharp:

npm install sharp

Usage

import { materialRepeat } from "seamless-texture";

const tiled = materialRepeat(pixels, 512);
import { seamlessMaterialTile, displaceMaterialSurface } from "seamless-texture/sharp";

const tile = await seamlessMaterialTile(sourcePNG);
const relief = await displaceMaterialSurface(tile, sourcePNG, 512, 512);

Tile options and presets

seamlessMaterialTile(texture, options) accepts:

  • preset: fabric, leather or wood. The preset loads its bundle. An explicit option overrides the bundle value.
  • feather: the fraction of each axis folded at the edges, between 0 and 1. The default is 1/8.
  • size: the square output size in pixels. The tile is stretched to that size. The default keeps the feathered source size.

| Preset | feather | | --- | --- | | fabric | 1/5 | | leather | 1/8 | | wood | 1/12 |

Every preset sets the feather style only; the output size stays caller-controlled.

const fabric = await seamlessMaterialTile(sourcePNG, { preset: "fabric" });
const narrow = await seamlessMaterialTile(sourcePNG, { preset: "fabric", feather: 1 / 12 });

Batch mode

import { batchMaterialTiles } from "seamless-texture/sharp";

const results = await batchMaterialTiles([firstPNG, secondPNG], { preset: "leather", concurrency: 4 });
for (const result of results) {
  if (result.error) console.error(result.error);
  else if (result.output) console.log(result.output.length);
}

batchMaterialTiles(sources, options) resolves to one entry per source in input order:

  • { index, output } with the tiled PNG buffer on success.
  • { index, error } with a message on failure.

One bad source never rejects the whole batch. The options carry every seamlessMaterialTile option plus concurrency, the number of sources tiled at once. The default is 2. The options are validated before processing, so a bad preset or concurrency rejects the call.

Normal and roughness maps

import { normalMapFromTile, roughnessMapFromTile } from "seamless-texture/sharp";

const normals = await normalMapFromTile(tilePNG, { strength: 1 });
const roughness = await roughnessMapFromTile(tilePNG, { floor: 0, ceiling: 255 });

normalMapFromTile(texture, options):

  • The sharp greyscale value of each pixel is the height.
  • Horizontal and vertical sobel gradients sample with wraparound, so a seamless tile stays seamless.
  • The unit normal is encoded as R = 128 + nx * 127.5, G = 128 + ny * 127.5 and B = 128 + nz * 127.5. Flat input gives (128, 128, 255).
  • strength scales both slopes before normalization. The default is 1.

roughnessMapFromTile(texture, options):

  • Bright pixels become smooth and dark pixels become rough.
  • The output value is floor + (ceiling - floor) * (1 - height / 255), written as a grayscale PNG.
  • floor and ceiling are integers between 0 and 255. The defaults are 0 and 255.

CLI

npx seamless-texture tile <inputs...> --out-dir <dir> [--preset <name>] [--concurrency <n>]
  • Every input name.png is written as name.tile.png in the output directory.
  • A status line per file goes to stderr. A JSON summary goes to stdout.
  • The exit code is 1 when any file fails.

Notes

  • materialRepeat reads and writes raw RGB buffers. The size must be a multiple of eight and at least 32.
  • The helpers read and write PNG buffers.
  • sharp is an optional peer dependency. The core function has no dependencies.

Development

npm ci
npm test

License

MIT. See LICENSE.