peasy-image 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Peasy Tools
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,287 @@
1
+ # peasy-image
2
+
3
+ [![npm](https://img.shields.io/npm/v/peasy-image)](https://www.npmjs.com/package/peasy-image)
4
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue)](https://www.typescriptlang.org/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ Image processing library for Node.js powered by [sharp](https://sharp.pixelplumbing.com/) -- resize, crop, convert, compress, rotate, blur, sharpen, and 8 more operations. TypeScript-first with full type definitions.
8
+
9
+ All functions accept a `Buffer` and return a `Promise<ImageResult>` with the processed image data, dimensions, format, and byte size.
10
+
11
+ > **Try the interactive tools at [peasyimage.com](https://peasyimage.com)** -- [Image Resizer](https://peasyimage.com/tools/resize/), [Image Converter](https://peasyimage.com/tools/convert/), [Image Compressor](https://peasyimage.com/tools/compress/)
12
+
13
+ ## Table of Contents
14
+
15
+ - [Install](#install)
16
+ - [Quick Start](#quick-start)
17
+ - [What You Can Do](#what-you-can-do)
18
+ - [Resize and Crop](#resize-and-crop)
19
+ - [Format Conversion](#format-conversion)
20
+ - [Compression](#compression)
21
+ - [Rotation and Flipping](#rotation-and-flipping)
22
+ - [Filters and Effects](#filters-and-effects)
23
+ - [Compositing](#compositing)
24
+ - [Thumbnails](#thumbnails)
25
+ - [API Reference](#api-reference)
26
+ - [TypeScript Types](#typescript-types)
27
+ - [Also Available for Python](#also-available-for-python)
28
+ - [Peasy Developer Tools](#peasy-developer-tools)
29
+ - [License](#license)
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ npm install peasy-image
35
+ ```
36
+
37
+ Requires Node.js 18+ and includes [sharp](https://sharp.pixelplumbing.com/) as a dependency for high-performance, native image processing.
38
+
39
+ ## Quick Start
40
+
41
+ ```typescript
42
+ import { readFileSync, writeFileSync } from "fs";
43
+ import { info, resize, compress, convert } from "peasy-image";
44
+
45
+ const source = readFileSync("photo.jpg");
46
+
47
+ // Get image metadata
48
+ const meta = await info(source);
49
+ console.log(`${meta.width}x${meta.height} ${meta.format} (${meta.size} bytes)`);
50
+
51
+ // Resize to 800px wide, maintaining aspect ratio
52
+ const resized = await resize(source, { width: 800, fit: "contain" });
53
+ writeFileSync("resized.jpg", resized.data);
54
+
55
+ // Compress to WebP at quality 60
56
+ const compressed = await compress(source, { quality: 60, format: "webp" });
57
+ writeFileSync("compressed.webp", compressed.data);
58
+
59
+ // Convert PNG to AVIF
60
+ const avif = await convert(readFileSync("image.png"), "avif");
61
+ writeFileSync("image.avif", avif.data);
62
+ ```
63
+
64
+ ## What You Can Do
65
+
66
+ ### Resize and Crop
67
+
68
+ Resize images to exact dimensions or proportionally by width/height. Sharp supports 5 fit modes that control how the image fills the target area: `cover` (crop to fill), `contain` (letterbox), `fill` (stretch), `inside`, and `outside`.
69
+
70
+ | Fit Mode | Behavior |
71
+ |----------|----------|
72
+ | `cover` | Crop to fill the target dimensions (default) |
73
+ | `contain` | Resize to fit within bounds, preserving aspect ratio |
74
+ | `fill` | Stretch to exact dimensions, ignoring aspect ratio |
75
+ | `inside` | Resize to fit inside, never enlarging |
76
+ | `outside` | Resize to cover, never shrinking |
77
+
78
+ ```typescript
79
+ import { resize, crop } from "peasy-image";
80
+
81
+ // Resize to fit within 800x600, preserving aspect ratio
82
+ const fitted = await resize(source, { width: 800, height: 600, fit: "contain" });
83
+
84
+ // Resize by width only — height calculated automatically
85
+ const wide = await resize(source, { width: 1200, fit: "contain" });
86
+
87
+ // Crop a 300x300 region starting at (50, 100)
88
+ const cropped = await crop(source, { left: 50, top: 100, width: 300, height: 300 });
89
+ ```
90
+
91
+ Learn more: [Image Resizer Tool](https://peasyimage.com/tools/resize/) -- [Image Cropper Tool](https://peasyimage.com/tools/crop/)
92
+
93
+ ### Format Conversion
94
+
95
+ Convert between 6 image formats. Modern formats like WebP and AVIF provide significantly better compression than JPEG and PNG while maintaining visual quality.
96
+
97
+ | Format | Best For | Alpha Support |
98
+ |--------|----------|---------------|
99
+ | `png` | Lossless graphics, screenshots | Yes |
100
+ | `jpeg` | Photos, continuous tones | No |
101
+ | `webp` | Web images (25-35% smaller than JPEG) | Yes |
102
+ | `avif` | Next-gen web (50% smaller than JPEG) | Yes |
103
+ | `tiff` | Print, archival | Yes |
104
+ | `gif` | Simple animations | Limited |
105
+
106
+ ```typescript
107
+ import { convert } from "peasy-image";
108
+
109
+ // Convert to WebP for smaller web assets
110
+ const webp = await convert(source, "webp");
111
+
112
+ // Convert to AVIF for maximum compression
113
+ const avif = await convert(source, "avif");
114
+ ```
115
+
116
+ Learn more: [Image Converter Tool](https://peasyimage.com/tools/convert/) -- [WebP vs AVIF Guide](https://peasyimage.com/blog/webp-vs-avif/)
117
+
118
+ ### Compression
119
+
120
+ Reduce file size by adjusting quality. The `compress` function defaults to JPEG at quality 60, which typically reduces file size by 70-80% with acceptable visual quality.
121
+
122
+ ```typescript
123
+ import { compress } from "peasy-image";
124
+
125
+ // Compress to JPEG at quality 60 (default)
126
+ const small = await compress(source);
127
+
128
+ // Compress to WebP at quality 80 for higher fidelity
129
+ const webp = await compress(source, { quality: 80, format: "webp" });
130
+ ```
131
+
132
+ Learn more: [Image Compressor Tool](https://peasyimage.com/tools/compress/)
133
+
134
+ ### Rotation and Flipping
135
+
136
+ Rotate images by any angle (90, 180, 270 for lossless, or arbitrary degrees). Flip vertically or mirror horizontally.
137
+
138
+ ```typescript
139
+ import { rotate, flip, flop } from "peasy-image";
140
+
141
+ // Rotate 90 degrees clockwise
142
+ const rotated = await rotate(source, 90);
143
+
144
+ // Flip vertically (top to bottom)
145
+ const flipped = await flip(source);
146
+
147
+ // Mirror horizontally (left to right)
148
+ const mirrored = await flop(source);
149
+ ```
150
+
151
+ ### Filters and Effects
152
+
153
+ Apply visual effects: grayscale conversion, Gaussian blur, Laplacian sharpening, color inversion, and color tinting.
154
+
155
+ | Filter | Description | Key Parameter |
156
+ |--------|-------------|---------------|
157
+ | `grayscale` | Convert to grayscale | -- |
158
+ | `blur` | Gaussian blur | `sigma` (0.3-1000, default 2.0) |
159
+ | `sharpen` | Laplacian sharpening | `sigma` (default 1.0) |
160
+ | `negate` | Invert all colors | -- |
161
+ | `tint` | Apply RGB color tint | `{ r, g, b }` values |
162
+
163
+ ```typescript
164
+ import { grayscale, blur, sharpen, negate, tint } from "peasy-image";
165
+
166
+ // Convert to black and white
167
+ const bw = await grayscale(source);
168
+
169
+ // Apply soft Gaussian blur (sigma 3.0)
170
+ const blurred = await blur(source, 3.0);
171
+
172
+ // Sharpen a slightly out-of-focus image
173
+ const sharp = await sharpen(source, 1.5);
174
+
175
+ // Invert colors for a negative effect
176
+ const inverted = await negate(source);
177
+
178
+ // Apply a warm sepia-like tint
179
+ const warm = await tint(source, { r: 180, g: 130, b: 80 });
180
+ ```
181
+
182
+ ### Compositing
183
+
184
+ Overlay one image on top of another with position control and opacity. Useful for watermarks, badges, and image collages.
185
+
186
+ ```typescript
187
+ import { composite } from "peasy-image";
188
+
189
+ // Place a watermark at position (10, 10)
190
+ const watermarked = await composite(photo, watermarkPng, { left: 10, top: 10 });
191
+
192
+ // Overlay with 50% opacity
193
+ const blended = await composite(background, foreground, {
194
+ left: 100,
195
+ top: 50,
196
+ opacity: 0.5,
197
+ });
198
+ ```
199
+
200
+ ### Thumbnails
201
+
202
+ Create square thumbnails by center-cropping and resizing in a single operation. Ideal for profile pictures, gallery previews, and social media icons.
203
+
204
+ ```typescript
205
+ import { thumbnail } from "peasy-image";
206
+
207
+ // 64x64 square thumbnail for avatars
208
+ const avatar = await thumbnail(source, 64);
209
+
210
+ // 256x256 thumbnail for gallery grid
211
+ const preview = await thumbnail(source, 256);
212
+ ```
213
+
214
+ ## API Reference
215
+
216
+ | Function | Signature | Description |
217
+ |----------|-----------|-------------|
218
+ | `info` | `(source: Buffer) => Promise<ImageInfo>` | Get image metadata (dimensions, format, channels) |
219
+ | `resize` | `(source: Buffer, options: ResizeOptions) => Promise<ImageResult>` | Resize with fit mode control |
220
+ | `crop` | `(source: Buffer, options: CropOptions) => Promise<ImageResult>` | Extract a rectangular region |
221
+ | `convert` | `(source: Buffer, format: ImageFormat) => Promise<ImageResult>` | Convert between 6 formats |
222
+ | `compress` | `(source: Buffer, options?: CompressOptions) => Promise<ImageResult>` | Reduce file size via quality |
223
+ | `rotate` | `(source: Buffer, angle: number) => Promise<ImageResult>` | Rotate by degrees |
224
+ | `flip` | `(source: Buffer) => Promise<ImageResult>` | Flip vertically |
225
+ | `flop` | `(source: Buffer) => Promise<ImageResult>` | Mirror horizontally |
226
+ | `grayscale` | `(source: Buffer) => Promise<ImageResult>` | Convert to grayscale |
227
+ | `blur` | `(source: Buffer, sigma?: number) => Promise<ImageResult>` | Gaussian blur |
228
+ | `sharpen` | `(source: Buffer, sigma?: number) => Promise<ImageResult>` | Laplacian sharpening |
229
+ | `negate` | `(source: Buffer) => Promise<ImageResult>` | Invert colors |
230
+ | `tint` | `(source: Buffer, color: {r,g,b}) => Promise<ImageResult>` | Apply color tint |
231
+ | `composite` | `(base: Buffer, overlay: Buffer, options?) => Promise<ImageResult>` | Overlay images |
232
+ | `thumbnail` | `(source: Buffer, size: number) => Promise<ImageResult>` | Square center-crop thumbnail |
233
+
234
+ ## TypeScript Types
235
+
236
+ ```typescript
237
+ interface ImageInfo {
238
+ width: number;
239
+ height: number;
240
+ format: string;
241
+ channels: number;
242
+ size: number;
243
+ hasAlpha: boolean;
244
+ space: string;
245
+ }
246
+
247
+ interface ImageResult {
248
+ data: Buffer;
249
+ width: number;
250
+ height: number;
251
+ format: string;
252
+ size: number;
253
+ }
254
+
255
+ type ImageFormat = "png" | "jpeg" | "webp" | "avif" | "tiff" | "gif";
256
+ type FitMode = "cover" | "contain" | "fill" | "inside" | "outside";
257
+
258
+ interface ResizeOptions { width?: number; height?: number; fit?: FitMode; }
259
+ interface CropOptions { left: number; top: number; width: number; height: number; }
260
+ interface CompressOptions { quality?: number; format?: ImageFormat; }
261
+ ```
262
+
263
+ ## Also Available for Python
264
+
265
+ | Platform | Package | Install |
266
+ |----------|---------|---------|
267
+ | **PyPI** | [peasy-image](https://pypi.org/project/peasy-image/) | `pip install peasy-image` |
268
+
269
+ The Python version provides 20 operations powered by Pillow, including watermark, border, round corners, pad, and EXIF extraction.
270
+
271
+ ## Peasy Developer Tools
272
+
273
+ | Package | npm | PyPI | Description |
274
+ |---------|-----|------|-------------|
275
+ | **peasy-image** | **[npm](https://www.npmjs.com/package/peasy-image)** | [PyPI](https://pypi.org/project/peasy-image/) | **Image processing — resize, crop, convert, compress** |
276
+ | peasy-pdf | [npm](https://www.npmjs.com/package/peasy-pdf) | [PyPI](https://pypi.org/project/peasy-pdf/) | PDF manipulation -- merge, split, rotate, extract |
277
+ | peasy-css | [npm](https://www.npmjs.com/package/peasy-css) | [PyPI](https://pypi.org/project/peasy-css/) | CSS processing -- minify, format, analyze |
278
+ | peasy-compress | -- | [PyPI](https://pypi.org/project/peasy-compress/) | File compression -- gzip, brotli, zstd |
279
+ | peasy-audio | -- | [PyPI](https://pypi.org/project/peasy-audio/) | Audio processing -- convert, trim, metadata |
280
+ | peasy-video | -- | [PyPI](https://pypi.org/project/peasy-video/) | Video processing -- convert, trim, thumbnail |
281
+ | peasy-document | [npm](https://www.npmjs.com/package/peasy-document) | [PyPI](https://pypi.org/project/peasy-document/) | Document conversion -- DOCX, HTML, Markdown |
282
+
283
+ Part of the [Peasy Tools](https://peasytools.com) developer tools ecosystem.
284
+
285
+ ## License
286
+
287
+ MIT
@@ -0,0 +1,188 @@
1
+ /**
2
+ * peasy-image types — interfaces for image processing operations.
3
+ */
4
+ /** Basic image metadata returned by `info()`. */
5
+ interface ImageInfo {
6
+ width: number;
7
+ height: number;
8
+ format: string;
9
+ channels: number;
10
+ size: number;
11
+ hasAlpha: boolean;
12
+ space: string;
13
+ }
14
+ /** Result of an image processing operation. */
15
+ interface ImageResult {
16
+ data: Buffer;
17
+ width: number;
18
+ height: number;
19
+ format: string;
20
+ size: number;
21
+ }
22
+ /** Supported output image formats. */
23
+ type ImageFormat = "png" | "jpeg" | "webp" | "avif" | "tiff" | "gif";
24
+ /** Resize fit mode — how the image should fit within the target dimensions. */
25
+ type FitMode = "cover" | "contain" | "fill" | "inside" | "outside";
26
+ /** Options for resizing an image. */
27
+ interface ResizeOptions {
28
+ width?: number;
29
+ height?: number;
30
+ fit?: FitMode;
31
+ }
32
+ /** Options for cropping a region from an image. */
33
+ interface CropOptions {
34
+ left: number;
35
+ top: number;
36
+ width: number;
37
+ height: number;
38
+ }
39
+ /** Options for compressing an image. */
40
+ interface CompressOptions {
41
+ quality?: number;
42
+ format?: ImageFormat;
43
+ }
44
+
45
+ /**
46
+ * peasy-image engine — image processing functions powered by sharp.
47
+ *
48
+ * 15 operations: info, resize, crop, convert, compress, rotate, flip, flop,
49
+ * grayscale, blur, sharpen, negate, tint, composite, thumbnail.
50
+ */
51
+
52
+ /**
53
+ * Get image metadata — dimensions, format, channels, color space.
54
+ *
55
+ * @param source - Image data as a Buffer
56
+ * @returns Image metadata
57
+ */
58
+ declare function info(source: Buffer): Promise<ImageInfo>;
59
+ /**
60
+ * Resize an image to the given dimensions.
61
+ *
62
+ * If only width or height is provided, the other dimension is
63
+ * calculated to maintain aspect ratio (default fit: "cover").
64
+ *
65
+ * @param source - Image data as a Buffer
66
+ * @param options - Resize options (width, height, fit)
67
+ * @returns Resized image result
68
+ */
69
+ declare function resize(source: Buffer, options: ResizeOptions): Promise<ImageResult>;
70
+ /**
71
+ * Crop a rectangular region from an image.
72
+ *
73
+ * @param source - Image data as a Buffer
74
+ * @param options - Crop region (left, top, width, height)
75
+ * @returns Cropped image result
76
+ */
77
+ declare function crop(source: Buffer, options: CropOptions): Promise<ImageResult>;
78
+ /**
79
+ * Convert an image to a different format.
80
+ *
81
+ * @param source - Image data as a Buffer
82
+ * @param format - Target format (png, jpeg, webp, avif, tiff, gif)
83
+ * @returns Converted image result
84
+ */
85
+ declare function convert(source: Buffer, format: ImageFormat): Promise<ImageResult>;
86
+ /**
87
+ * Compress an image by reducing quality.
88
+ *
89
+ * Defaults to JPEG format at quality 60 for maximum compression.
90
+ *
91
+ * @param source - Image data as a Buffer
92
+ * @param options - Compression options (quality, format)
93
+ * @returns Compressed image result
94
+ */
95
+ declare function compress(source: Buffer, options?: CompressOptions): Promise<ImageResult>;
96
+ /**
97
+ * Rotate an image by the given angle in degrees.
98
+ *
99
+ * Common angles (90, 180, 270) produce lossless rotation.
100
+ * Arbitrary angles expand the canvas to fit the rotated image.
101
+ *
102
+ * @param source - Image data as a Buffer
103
+ * @param angle - Rotation angle in degrees (clockwise)
104
+ * @returns Rotated image result
105
+ */
106
+ declare function rotate(source: Buffer, angle: number): Promise<ImageResult>;
107
+ /**
108
+ * Flip an image vertically (top to bottom).
109
+ *
110
+ * @param source - Image data as a Buffer
111
+ * @returns Flipped image result
112
+ */
113
+ declare function flip(source: Buffer): Promise<ImageResult>;
114
+ /**
115
+ * Flop an image horizontally (mirror, left to right).
116
+ *
117
+ * @param source - Image data as a Buffer
118
+ * @returns Flopped image result
119
+ */
120
+ declare function flop(source: Buffer): Promise<ImageResult>;
121
+ /**
122
+ * Convert an image to grayscale.
123
+ *
124
+ * @param source - Image data as a Buffer
125
+ * @returns Grayscale image result
126
+ */
127
+ declare function grayscale(source: Buffer): Promise<ImageResult>;
128
+ /**
129
+ * Apply Gaussian blur to an image.
130
+ *
131
+ * @param source - Image data as a Buffer
132
+ * @param sigma - Blur intensity (0.3 to 1000, default 2.0)
133
+ * @returns Blurred image result
134
+ */
135
+ declare function blur(source: Buffer, sigma?: number): Promise<ImageResult>;
136
+ /**
137
+ * Sharpen an image using Laplacian sharpening.
138
+ *
139
+ * @param source - Image data as a Buffer
140
+ * @param sigma - Sharpening intensity (default 1.0)
141
+ * @returns Sharpened image result
142
+ */
143
+ declare function sharpen(source: Buffer, sigma?: number): Promise<ImageResult>;
144
+ /**
145
+ * Negate (invert) the colors of an image.
146
+ *
147
+ * @param source - Image data as a Buffer
148
+ * @returns Negated image result
149
+ */
150
+ declare function negate(source: Buffer): Promise<ImageResult>;
151
+ /**
152
+ * Apply a color tint to an image.
153
+ *
154
+ * @param source - Image data as a Buffer
155
+ * @param color - RGB color to tint with
156
+ * @returns Tinted image result
157
+ */
158
+ declare function tint(source: Buffer, color: {
159
+ r: number;
160
+ g: number;
161
+ b: number;
162
+ }): Promise<ImageResult>;
163
+ /**
164
+ * Overlay one image on top of another (composite).
165
+ *
166
+ * @param base - Base image data as a Buffer
167
+ * @param overlay - Overlay image data as a Buffer
168
+ * @param options - Position and opacity options
169
+ * @returns Composited image result
170
+ */
171
+ declare function composite(base: Buffer, overlay: Buffer, options?: {
172
+ left?: number;
173
+ top?: number;
174
+ opacity?: number;
175
+ }): Promise<ImageResult>;
176
+ /**
177
+ * Create a square thumbnail by center-cropping and resizing.
178
+ *
179
+ * The image is resized to cover the target size, then center-cropped
180
+ * to produce a square output.
181
+ *
182
+ * @param source - Image data as a Buffer
183
+ * @param size - Target thumbnail size in pixels (width = height)
184
+ * @returns Square thumbnail image result
185
+ */
186
+ declare function thumbnail(source: Buffer, size: number): Promise<ImageResult>;
187
+
188
+ export { type CompressOptions, type CropOptions, type FitMode, type ImageFormat, type ImageInfo, type ImageResult, type ResizeOptions, blur, composite, compress, convert, crop, flip, flop, grayscale, info, negate, resize, rotate, sharpen, thumbnail, tint };
package/dist/index.js ADDED
@@ -0,0 +1,121 @@
1
+ // src/engine.ts
2
+ import sharp from "sharp";
3
+ async function toResult(pipeline, format) {
4
+ const { data, info: info2 } = await pipeline.toBuffer({ resolveWithObject: true });
5
+ return {
6
+ data,
7
+ width: info2.width,
8
+ height: info2.height,
9
+ format: info2.format || format || "unknown",
10
+ size: data.length
11
+ };
12
+ }
13
+ async function info(source) {
14
+ const meta = await sharp(source).metadata();
15
+ return {
16
+ width: meta.width ?? 0,
17
+ height: meta.height ?? 0,
18
+ format: meta.format ?? "unknown",
19
+ channels: meta.channels ?? 0,
20
+ size: source.length,
21
+ hasAlpha: meta.hasAlpha ?? false,
22
+ space: meta.space ?? "unknown"
23
+ };
24
+ }
25
+ async function resize(source, options) {
26
+ const pipeline = sharp(source).resize({
27
+ width: options.width,
28
+ height: options.height,
29
+ fit: options.fit ?? "cover"
30
+ });
31
+ return toResult(pipeline);
32
+ }
33
+ async function crop(source, options) {
34
+ const pipeline = sharp(source).extract({
35
+ left: options.left,
36
+ top: options.top,
37
+ width: options.width,
38
+ height: options.height
39
+ });
40
+ return toResult(pipeline);
41
+ }
42
+ async function convert(source, format) {
43
+ const pipeline = sharp(source).toFormat(format);
44
+ return toResult(pipeline, format);
45
+ }
46
+ async function compress(source, options) {
47
+ const quality = options?.quality ?? 60;
48
+ const format = options?.format ?? "jpeg";
49
+ const pipeline = sharp(source).toFormat(format, { quality });
50
+ return toResult(pipeline, format);
51
+ }
52
+ async function rotate(source, angle) {
53
+ const pipeline = sharp(source).rotate(angle);
54
+ return toResult(pipeline);
55
+ }
56
+ async function flip(source) {
57
+ const pipeline = sharp(source).flip();
58
+ return toResult(pipeline);
59
+ }
60
+ async function flop(source) {
61
+ const pipeline = sharp(source).flop();
62
+ return toResult(pipeline);
63
+ }
64
+ async function grayscale(source) {
65
+ const pipeline = sharp(source).grayscale();
66
+ return toResult(pipeline);
67
+ }
68
+ async function blur(source, sigma = 2) {
69
+ const pipeline = sharp(source).blur(sigma);
70
+ return toResult(pipeline);
71
+ }
72
+ async function sharpen(source, sigma = 1) {
73
+ const pipeline = sharp(source).sharpen(sigma);
74
+ return toResult(pipeline);
75
+ }
76
+ async function negate(source) {
77
+ const pipeline = sharp(source).negate();
78
+ return toResult(pipeline);
79
+ }
80
+ async function tint(source, color) {
81
+ const pipeline = sharp(source).tint(color);
82
+ return toResult(pipeline);
83
+ }
84
+ async function composite(base, overlay, options) {
85
+ let overlayInput = overlay;
86
+ if (options?.opacity !== void 0 && options.opacity < 1) {
87
+ overlayInput = await sharp(overlay).ensureAlpha(options.opacity).toBuffer();
88
+ }
89
+ const pipeline = sharp(base).composite([
90
+ {
91
+ input: overlayInput,
92
+ left: options?.left ?? 0,
93
+ top: options?.top ?? 0
94
+ }
95
+ ]);
96
+ return toResult(pipeline);
97
+ }
98
+ async function thumbnail(source, size) {
99
+ const pipeline = sharp(source).resize(size, size, {
100
+ fit: "cover",
101
+ position: "centre"
102
+ });
103
+ return toResult(pipeline);
104
+ }
105
+ export {
106
+ blur,
107
+ composite,
108
+ compress,
109
+ convert,
110
+ crop,
111
+ flip,
112
+ flop,
113
+ grayscale,
114
+ info,
115
+ negate,
116
+ resize,
117
+ rotate,
118
+ sharpen,
119
+ thumbnail,
120
+ tint
121
+ };
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "peasy-image",
3
+ "version": "0.1.0",
4
+ "description": "Image processing library for Node.js — resize, crop, convert, compress, filter. Powered by sharp.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsup src/index.ts --format esm --dts",
19
+ "test": "vitest run",
20
+ "typecheck": "tsc --noEmit"
21
+ },
22
+ "keywords": [
23
+ "image",
24
+ "resize",
25
+ "crop",
26
+ "convert",
27
+ "compress",
28
+ "sharp",
29
+ "peasy"
30
+ ],
31
+ "author": "Peasy Tools",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "url": "https://github.com/peasytools/peasy-image-js.git"
35
+ },
36
+ "homepage": "https://peasyimage.com",
37
+ "dependencies": {
38
+ "sharp": "^0.33"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^25.4.0",
42
+ "tsup": "^8.0",
43
+ "typescript": "^5.7",
44
+ "vitest": "^3.0"
45
+ }
46
+ }