Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Powerful and expressive image processing library for TypeScript that compiles to SVG filters.
An easy to use, powerful and expressive image processing library for TypeScript that compiles to SVG filters, letting you apply complex visual effects to your HTML and SVG elements.
SVG filters provide an extremely powerful node-based effect system that can be used across HTML and SVG, but they are held back by the fact that it is impossible to express function composition in XML in a natural way, making them very hard to write, compose and reuse. Hypercomp fixes this by providing a functional API for composing effects in TypeScript, and compiling them down to an equivalent SVG filter.
npm install hypercomp
The following example creates a squiggly line around the source image by extracting the source image from a slightly dilated version of itself, and then displacing it using fractal noise.
import { Effect, css } from "hypercomp";
const radius = 2;
const width = 2;
const freq = 0.01;
const octaves = 1;
const scale = 15;
const effects =
// Create a flood
Effect.flood("#30597E")
// and composite it into the source image dilated by radius and width
.in(Effect.source.dilate(radius + width))
// from which we subtract the source image dilated by radius
// (the difference between the two dilated versions will form the stroke)
.out(Effect.source.dilate(radius))
// which we finally displace using fractal noise.
.displace(fractalNoise(freq, { octaves }), scale)
// and draw it over the source image.
.over(Effect.source);
const style = {
filter: css(effects),
};
return <div style={style}>hello world</div>;
The following example takes the source, extracts sharp edges, applies a dilation effect, and adds a blue shadow.
import { Effect, css } from "hypercomp";
const withEdges = Effect.merge([
Effect.source,
// sobel
Effect.source.convolve([1, 0, -1, 2, 0, -2, 1, 0, -1]), // x direction
Effect.source.convolve([1, 2, 1, 0, 0, 0, -1, -2, -1]), // y direction
])
.dilate(2)
.shadow(1, { color: "blue" });
const style = {
filter: css(withEdges),
};
return <div style={style}>hello world</div>;
The following example blurs the source image, uses it as the bump map for lighting, and then composites the lighting onto a black background using screen blending.
import { Effect, Light, css } from "hypercomp";
const withLight = Effect.flood("black").screen(
Effect.sourceAlpha
.blur(1)
.specular(Light.pointLight({ x: 460, y: 110, z: 680 }), {
strength: 4,
shininess: 20,
})
);
const style = {
filter: css(withLight),
};
return <div style={style}>hello world</div>;
Knowledge of image manipulation functions or SVG filter effects is helpful. Study the examples to get an intuition for how certain effects can be achieved.
.normal(input, config?)
.screen(input, config?)
.multiply(input, config?)
.overlay(input, config?)
.darken(input, config?)
.lighten(input, config?)
.colorDodge(input, config?)
.colorBurn(input, config?)
.hardLight(input, config?)
.softLight(input, config?)
.difference(input, config?)
.exclusion(input, config?)
.hue(input, config?)
.saturation(input, config?)
.color(input, config?)
.luminosity(input, config?)
css(filter, key?)
Compiles the filter and returns a CSS filter
property value.
When key is present, the filter is rendered to the dom. Subsequent calls with the same key will return the same data URL, and update the rendered filter. When key is omitted, the effect is rendered to a data URL.
IMPORTANT:
Currently, using the keyless version and rendering to a data url is not recommended.
.image()
function won't work in Chrome.It is thus recommended to always use the key
parameter, or to use the useFilter
hook from hypercomp/react
which will create and unmount filters automatically.
unmount()
to unmount the filter from the dom.string
suitable for use in CSS filter
property.unmount(key)
Unmounts the filter with the given key from the DOM.
compile(filter)
Returns the compiled filter as a a string. If you pass the result of an effect function directly, it will only return the equivalent effects without the outer <filter>
tag. If you wrap it in a filter()
call, it will return the full SVG filter including the <filter>
tag.
For example, compile(Effect.source.blur(2))
will return <feGaussianBlur stdDeviation="2"/>
, while compile(filter(Effect.source.blur(2)))
will return <filter><feGaussianBlur stdDeviation="2"/></filter>
.
The hypercomp/react
module provides the useFilter
hook, which you can use to tie the lifetime of a dom-rendered filter to the lifetime of a component. Recommended for React projects.
import { Effect, useFilter } from "hypercomp/react";
const MyComponent = () => {
return (
<div style={{ filter: useFilter(Effect.source.dilate(2)) }}>
hello world
</div>
);
};
You create filters by composing effects. They can be arbitrarily chained, provided as inputs to other effects, saved, reused, or compiled to an output using the css
or compile
functions.
Effect functions usually take 0-2 effect inputs, 0-1 effect arguments and an optional configuration object. Each configuration object takes at the minimum the x
, y
, width
, and height
properties to define the region of the filter effect, which is not documented individually here.
When you are done composing your filter, you can compile it or render it by passing it to the compile
or css
functions.
Optionally, you can call .filter()
on your effect, which lets you specify the attributes of the rendered filter tag.
.filter(attributes?)
Lets you specify attributes of the rendered filter tag. This is optional, if you don't call .filter()
, the behavior will depend on the render function you use.
string
- Filter ID.number
- X coordinate.number
- Y coordinate.number
- Width.number
- Height."userSpaceOnUse" | "objectBoundingBox"
- Filter units."userSpaceOnUse" | "objectBoundingBox"
- Primitive units."auto" | "sRGB" | "linearRGB" | "inherit"
- Color interpolation filters.Constants are available as static properties on the Effect
class and can be used as inputs or starting points to effect chains.
Example:
Effect.flood("red").in(Effect.source.blur(2)); // Floods a blurred source graphic with red.
Effect.source
: Represents SourceGraphic
.Effect.sourceAlpha
: Represents SourceAlpha
.Effect.background
: Represents BackgroundImage
.Effect.backgroundAlpha
: Represents BackgroundAlpha
.Effect.fill
: Represents FillPaint
.Effect.stroke
: Represents StrokePaint
.In addition to constants, the following functions are available as static methods on the Effect
class and can be used as inputs or starting points to effects.
Effect.flood(color, config?)
Applies a flood effect with the given color and opacity.
string
(optional) - The flood color.number
- Opacity of the flood effect.Compiles to: <feFlood>
Effect.image(href, config?)
Creates an image.
string
- URL of the image.string
- Aspect ratio handling."anonymous" | "use-credentials"
- Cross-origin settings.Compiles to: <feImage>
Effect.merge(inputs, config?)
Merges an array of inputs with the last element as the topmost layer.
Effect[]
- Array of inputs to merge.Compiles to: <feMerge>
Effect.turbulence(frequency, config?)
Creates turbulence noise.
number
- Base frequency.number
- Number of octaves.number
- Random seed value."noStitch" | "stitch"
- Tile stitching mode.Compiles to: <feTurbulence>
Effect.fractalNoise(frequency, config?)
Creates fractal noise.
number
- Base frequency.number
- Number of octaves.number
- Random seed value."noStitch" | "stitch"
- Tile stitching mode..over(input, config?)
Composites the input using the "over" operator.
Compiles to: <feComposite>
.inside(input, config?)
Composites the input using the "in" operator.
Compiles to: <feComposite>
.out(input, config?)
Composites the input using the "out" operator.
Compiles to: <feComposite>
.xor(input, config?)
Composites the input using the "xor" operator.
Compiles to: <feComposite>
.atop(input, config?)
Composites the input using the "atop" operator.
Compiles to: <feComposite>
.arithmetic(input, config?)
Composites the input using the "arithmetic" operator.
number
- Coefficients for the arithmetic operation.Compiles to: <feComposite>
.blur(stdDeviation, config?)
Applies a Gaussian blur.
number
- Standard deviation of the blur."duplicate" | "wrap" | "none"
- Edge handling mode.Compiles to: <feGaussianBlur>
.convolve(kernel, config?)
Applies a convolution matrix.
number[]
- Kernel matrix values."duplicate" | "wrap" | "none"
- Edge handling mode.number | number[]
- Kernel size. If a single number is provided, it is assumed to be a square kernel. When an array is provided, the first element is the width and the second element is the height.number
- Bias value.number
- Divisor value.number
- Target X coordinate.number
- Target Y coordinate.boolean
- Preserve alpha channel.Compiles to: <feConvolveMatrix>
.displace(scale, config?)
Applies a displacement map.
number
- Scale factor for displacement."R" | "G" | "B" | "A"
- X channel."R" | "G" | "B" | "A"
- Y channel.Compiles to: <feDisplacementMap>
.offset(config?)
Applies an offset.
number
- Horizontal offset.number
- Vertical offset.Compiles to: <feOffset>
.shadow(stdDeviation?, config?)
Adds a drop shadow.
number
(optional) - Standard deviation for the blur. Defaults to 2.number
- Horizontal offset.number
- Vertical offset.string
- Shadow color.number
- Shadow opacity.Compiles to: <feDropShadow>
.tile(config?)
Applies a tile effect.
Compiles to: <feTile>
.normal(input, config?)
Blends the input using the "normal" mode.
.screen(input, config?)
Blends the input using the screen mode.
.multiply(input, config?)
Blends the input using the multiply mode.
.overlay(input, config?)
Blends the input using the overlay mode.
.darken(input, config?)
Blends the input using the darken mode.
.lighten(input, config?)
Blends the input using the lighten mode.
.colorDodge(input, config?)
Blends the input using the color dodge mode.
.colorBurn(input, config?)
Blends the input using the color burn mode.
.hardLight(input, config?)
Blends
the input using the hard light mode.
.softLight(input, config?)
Blends the input using the soft light mode.
.difference(input, config?)
Blends the input using the difference mode.
.exclusion(input, config?)
Blends the input using the exclusion mode.
.hue(input, config?)
Blends the input using the hue mode.
.saturation(input, config?)
Blends the input using the saturation mode.
.color(input, config?)
Blends the input using the color mode.
.luminosity(input, config?)
Blends the input using the luminosity mode.
.dilate(radius, config?)
Applies a dilation effect.
number
- Radius for the effect.Compiles to: <feMorphology>
.erode(radius, config?)
Applies an erosion effect.
number
- Radius for the effect.Compiles to: <feMorphology>
.colorMatrix(matrix, config?)
Applies a color matrix. The matrix is a 4x5 matrix, where the last column is the offset. The matrix can be provided either as an array of 20 numbers, or as a ColorMatrix
object where the default values are 1 for the diagonal and 0 for the rest.
type ColorMatrixRow = {
r?: number;
g?: number;
b?: number;
a?: number;
o?: number; // Offset
};
type ColorMatrix = {
r?: ColorMatrixRow;
g?: ColorMatrixRow;
b?: ColorMatrixRow;
a?: ColorMatrixRow;
};
number[] | ColorMatrix
- Matrix values.Compiles to: <feColorMatrix>
.componentTransfer(config?)
Applies component transfer.
Compiles to: <feComponentTransfer>
.hueRotate(angle, config?)
Rotates the hue.
number
- Angle of rotation.Compiles to: <feColorMatrix>
.luminanceToAlpha(config?)
Converts luminance to alpha.
Compiles to: <feColorMatrix>
.saturate(amount, config?)
Changes the saturation.
number
- Saturation amount.Compiles to: <feColorMatrix>
Lighting functions take a light source, and create a lighting effect using their input as height map.
Example:
Effect.sourceAlpha.blur(1).specular(pointLight({ x: 460, y: 110, z: 680 }), {
strength: 4,
shininess: 20,
});
.specular(light, config?)
Creates a specular lighting effect. You should composite it using additive blending.
number
- Specular strength.number
- Specular exponent.number
- Surface scale.string
- Lighting color.Compiles to: <feSpecularLighting>
.diffuse(light, config?)
Applies a diffuse lighting effect to the input. You should composite it using the multiply
blending mode.
number
- Diffuse strength.number
- Surface scale.string
- Lighting color.Compiles to: <feDiffuseLighting>
Light sources are available on the Light
export and can be used as inputs to lighting functions.
Light.pointLight(config?)
Creates a point light source.
number
- X coordinate.number
- Y coordinate.number
- Z coordinate.Light.distantLight(config?)
Creates a distant light source.
number
- Azimuth angle.number
- Elevation angle.Light.spotlight(config?)
Creates a spot light source.
number
- X coordinate.number
- Y coordinate.number
- Z coordinate.number
- X coordinate to point at.number
- Y coordinate to point at.number
- Z coordinate to point at.number
- The falloff of the spotlight.Component transfer functions are available on the Transfer
export and are used in combination with the componentTransfer
effect.
Example:
// Increase the contrast of the alpha channel.
Effect.source.componentTransfer({
a: Transfer.linear(18, -9),
});
Transfer.gamma(amplitude, exponent, offset)
Creates a gamma transfer function.
number
- Amplitude.number
- Exponent.number
- Offset.Transfer.linear(slope, intercept)
Creates a linear transfer function.
number
- Slope.number
- Intercept.Transfer.table(values)
Creates a table transfer function.
number[]
- Table values.Transfer.discrete(values)
Creates a discrete transfer function.
number[]
- Table values.Feel free to contribute by submitting issues or pull requests. For major changes, please open an issue first to discuss what you would like to change.
This project is licensed under the MIT License - see the LICENSE file for details.
FAQs
Powerful and expressive image processing library for TypeScript that compiles to SVG filters.
We found that hypercomp 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
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.