Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
@thi.ng/imago
Advanced tools
JSON & API-based declarative and extensible image processing trees/pipelines
[!NOTE] This is one of 199 standalone projects, maintained as part of the @thi.ng/umbrella monorepo and anti-framework.
🚀 Please help me to work full-time on these projects by sponsoring me on GitHub. Thank you! ❤️
JSON & API-based declarative and extensible image processing trees/pipelines.
Spiritual successor of an eponymous, yet never fully published CLojure/Java-based image processor from 2014...
In this new TypeScript version all image I/O and processing is delegated to sharp and @thi.ng/pixel.
Transformation trees/pipelines are simple JSON objects (but can be programmatically created):
The following pipeline performs these steps (in sequence):
[
{ "op": "rotate" },
{ "op": "extend", "border": 5, "unit": "%", "ref": "min", "bg": "#fff" },
{ "op": "resize", "size": 1920 },
{
"op": "composite",
"layers": [
{
"type": "img",
"path": "logo-128.png",
"pos": { "l": 45, "b": 5 },
"unit": "%",
"blend": "screen"
}
]
},
{
"op": "exif",
"tags": {
"IFD0": {
"Copyright": "Karsten Schmidt",
"Software": "@thi.ng/imago"
}
}
},
{
"op": "output",
"id": "hires",
"path": "{name}-{sha256}-{w}x{h}.avif",
"avif": { "quality": 80 }
},
{ "op": "crop", "size": [240, 240], "gravity": "c" },
{ "op": "output", "id": "thumb", "path": "{name}-thumb.jpg" },
{ "op": "output", "id": "hash", "blurhash": 4 }
]
Then to process an image using above JSON spec (there're also API wrappers to create these operator specs programmatically):
import { processImage } from "@thi.ng/imago";
import { readJSON } from "@thi.ng/file-io";
await processImage(
"test.jpg",
readJSON("readme-example1.json"),
{ outDir: "." }
);
TODO write docs
Gaussian blur
Compositing multiple layers. The following layer types are available, and custom
layer types can be registered via the polymorphic
defLayer()
function.
Cropping a part of the image
Supported dither modes from thi.ng/pixel-dither:
Set custom EXIF metadata (can be given multiple times, will be merged)
Add pixels on all sides of the image
Perform gamma correction (forward or reverse)
Grayscale conversion
Hue, saturation, brightness and lightness adjustments
Assign ICC profile (from preset: p3
, srgb
, cmyk
or from file). Can only be
given directly prior to output, overrides input ICC (if any) and only
used if output format actually supports it.
Performing nested branches/pipelines of operations with no effect on image state of current/parent pipeline...
File output in any of these formats:
Alternatively, a blurhash of the image can be computed and stored in the outputs. In this case, no file will be written.
For all other formats, if no output path is provided in the spec, no file will be written, but the encoded image buffer itself will be recorded in the outputs.
Output paths can contain {id}
-templated parts which will be replaced/expanded.
The following built-in IDs are supported and custom IDs will be looked up via
the
pathParts
options provided to
processImage().
Any others will remain as is. Custom IDs take precedence over built-in ones.
name
: original base filename (w/o ext)sha1
/sha224
/sha256
/sha384
/sha512
: truncated hash of output (8 chars)w
: current image widthh
: current image heightaspect
: "p" (portrait), "l" (landscape) or "sq" (square)date
: yyyyMMdd date format, e.g. 20240223time
: HHmmss time format, e.g. 234459year
: 4-digit yearmonth
: 2-digit monthweek
: 2-digit weekday
: 2-digit day in monthhour
: 2-digit hour (24h system)minute
: 2-digit minutesecond
: 2-digit secondOutput paths can contain sub-directories which will be automatically created
(relative to the configured output
dir).
For example, the path template {year}/{month}/{day}/{name}-{sha1}.jpg
might
get replaced to: 2024/02/22/test-123cafe4.jpg
...
Resizing image
Auto-rotate, rotate by angle and/or flip image along x/y
ALPHA - bleeding edge / work-in-progress
Search or submit any issues for this package
Border sizes, general dimensions, and positions can be specified in pixels
(default) or as percentages (using unit: "%"
). For the latter case, an
additional reference side (ref
option) can be provided. The default ref is
min
, referring to whatever is the smaller side of an image.
The ref
option/reference side can take the following values (default: both
):
both
: image width for horizontal uses, image height for vertical usesmin
: smaller side of an image (aka min(width,height)
)max
: larger side of an image (aka min(width,height)
)w
: image widthh
: image heightIn some operations positioning or alignment can be abstractly stated via one of the following gravity values:
By default all input metadata will be lost in the outputs. The keepEXIF
and
keepICC
options can be used to retain EXIF and/or ICC profile information
(only if also supported in the output format).
Important: Retaining EXIF and merging it with custom additions is still WIP...
yarn add @thi.ng/imago
ESM import:
import * as imago from "@thi.ng/imago";
For Node.js REPL:
const imago = await import("@thi.ng/imago");
Package sizes (brotli'd, pre-treeshake): ESM: 4.94 KB
Note: @thi.ng/api is in most cases a type-only import (not used at runtime)
import {
colorLayer,
composite,
crop,
extend,
imageLayer,
nest,
output,
processImage,
rawLayer,
resize,
rotate,
} from "@thi.ng/imago";
import { ConsoleLogger } from "@thi.ng/logger";
const res = await processImage(
"test.jpg",
// operator pipeline (i.e. a nested array of operator spec objects)
// the functions used here are merely syntax sugar for generating
// the spec objects to provide an anchor point for docs
// (ongoing effort, but since still a new project, mostly still forthcoming...)
[
// auto-rotate (EXIF orientation)
rotate({}),
// composite w/ semi-transparent color layer (screen)
composite({
layers: [
colorLayer({
// magenta with 50% opacity
bg: "#f0f8",
blend: "screen",
// layer size is 50x100% of image
size: [50, 100],
// aligned left (west)
gravity: "w",
// size given in percent
unit: "%",
}),
// diagonal hairline pattern overlay (with tiling) from raw
// pixel data in ABGR format, i.e. 0xAABBGGRR
rawLayer({
// prettier-ignore
buffer: new Uint32Array([
0x00000000, 0x00000000, 0x00000000, 0x80ffffff,
0x00000000, 0x00000000, 0x80ffffff, 0x00000000,
0x00000000, 0x80ffffff, 0x00000000, 0x00000000,
0x80ffffff, 0x00000000, 0x00000000, 0x00000000,
]),
channels: 4,
size: [4, 4],
tile: true,
}),
],
}),
// nested operations each operate on a clone of the current (already
// semi-transformed) image, they have no impact on the processing pipeline
// of their parent(s)
// multiple child pipelines can be spawned, here only a single one
nest({
procs: [
// this pipeline only creates blurhash (stored in `outputs` of result)
[resize({ size: 100 }), output({ id: "hash", blurhash: true })],
],
}),
// crop to 3:2 aspect ratio (always based on longest side)
crop({ size: 100, aspect: 3 / 2, unit: "%" }),
// back in the main pipleline, add 5% white border (based on smallest side)
extend({ border: 5, unit: "%", bg: "white", ref: "min" }),
// resize image to 1920 (largest side)
resize({ size: 1920 }),
// add logo watermark centered horizontally and near the bottom
composite({
layers: [
imageLayer({
path: "logo-128.png",
unit: "%",
origin: "s",
pos: { l: 50, b: 5 },
ref: "both",
blend: "screen",
}),
],
}),
output({ id: "main", path: "{date}-1920-frame.jpg" }),
],
{
logger: new ConsoleLogger("img"),
}
);
console.log(res.outputs);
// {
// hash: "UVKmR.^SIVR$_NRiM{jupLRjjEWC%goxofoM",
// main: "...../20240301-144948-1920-frame.jpg",
// }
If this project contributes to an academic publication, please cite it as:
@misc{thing-imago,
title = "@thi.ng/imago",
author = "Karsten Schmidt",
note = "https://thi.ng/imago",
year = 2024
}
© 2024 Karsten Schmidt // Apache License 2.0
FAQs
JSON & API-based declarative and extensible image processing trees/pipelines
The npm package @thi.ng/imago receives a total of 9 weekly downloads. As such, @thi.ng/imago popularity was classified as not popular.
We found that @thi.ng/imago demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.