image-edit-tools 1.0.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.
Files changed (176) hide show
  1. package/.gitattributes +2 -0
  2. package/README.md +41 -0
  3. package/dist/index.d.ts +24 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +24 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/mcp/index.d.ts +3 -0
  8. package/dist/mcp/index.d.ts.map +1 -0
  9. package/dist/mcp/index.js +3 -0
  10. package/dist/mcp/index.js.map +1 -0
  11. package/dist/mcp/server.d.ts +3 -0
  12. package/dist/mcp/server.d.ts.map +1 -0
  13. package/dist/mcp/server.js +15 -0
  14. package/dist/mcp/server.js.map +1 -0
  15. package/dist/mcp/tools.d.ts +4 -0
  16. package/dist/mcp/tools.d.ts.map +1 -0
  17. package/dist/mcp/tools.js +285 -0
  18. package/dist/mcp/tools.js.map +1 -0
  19. package/dist/ops/add-text.d.ts +5 -0
  20. package/dist/ops/add-text.d.ts.map +1 -0
  21. package/dist/ops/add-text.js +129 -0
  22. package/dist/ops/add-text.js.map +1 -0
  23. package/dist/ops/adjust.d.ts +3 -0
  24. package/dist/ops/adjust.d.ts.map +1 -0
  25. package/dist/ops/adjust.js +71 -0
  26. package/dist/ops/adjust.js.map +1 -0
  27. package/dist/ops/batch.d.ts +3 -0
  28. package/dist/ops/batch.d.ts.map +1 -0
  29. package/dist/ops/batch.js +35 -0
  30. package/dist/ops/batch.js.map +1 -0
  31. package/dist/ops/blur-region.d.ts +5 -0
  32. package/dist/ops/blur-region.d.ts.map +1 -0
  33. package/dist/ops/blur-region.js +54 -0
  34. package/dist/ops/blur-region.js.map +1 -0
  35. package/dist/ops/composite.d.ts +5 -0
  36. package/dist/ops/composite.d.ts.map +1 -0
  37. package/dist/ops/composite.js +53 -0
  38. package/dist/ops/composite.js.map +1 -0
  39. package/dist/ops/convert.d.ts +3 -0
  40. package/dist/ops/convert.d.ts.map +1 -0
  41. package/dist/ops/convert.js +45 -0
  42. package/dist/ops/convert.js.map +1 -0
  43. package/dist/ops/crop.d.ts +3 -0
  44. package/dist/ops/crop.d.ts.map +1 -0
  45. package/dist/ops/crop.js +105 -0
  46. package/dist/ops/crop.js.map +1 -0
  47. package/dist/ops/detect-faces.d.ts +3 -0
  48. package/dist/ops/detect-faces.d.ts.map +1 -0
  49. package/dist/ops/detect-faces.js +41 -0
  50. package/dist/ops/detect-faces.js.map +1 -0
  51. package/dist/ops/detect-subject.d.ts +3 -0
  52. package/dist/ops/detect-subject.d.ts.map +1 -0
  53. package/dist/ops/detect-subject.js +78 -0
  54. package/dist/ops/detect-subject.js.map +1 -0
  55. package/dist/ops/extract-text.d.ts +5 -0
  56. package/dist/ops/extract-text.d.ts.map +1 -0
  57. package/dist/ops/extract-text.js +21 -0
  58. package/dist/ops/extract-text.js.map +1 -0
  59. package/dist/ops/filter.d.ts +3 -0
  60. package/dist/ops/filter.d.ts.map +1 -0
  61. package/dist/ops/filter.js +53 -0
  62. package/dist/ops/filter.js.map +1 -0
  63. package/dist/ops/get-dominant-colors.d.ts +3 -0
  64. package/dist/ops/get-dominant-colors.d.ts.map +1 -0
  65. package/dist/ops/get-dominant-colors.js +48 -0
  66. package/dist/ops/get-dominant-colors.js.map +1 -0
  67. package/dist/ops/get-metadata.d.ts +3 -0
  68. package/dist/ops/get-metadata.d.ts.map +1 -0
  69. package/dist/ops/get-metadata.js +30 -0
  70. package/dist/ops/get-metadata.js.map +1 -0
  71. package/dist/ops/optimize.d.ts +3 -0
  72. package/dist/ops/optimize.d.ts.map +1 -0
  73. package/dist/ops/optimize.js +78 -0
  74. package/dist/ops/optimize.js.map +1 -0
  75. package/dist/ops/overlay.d.ts +3 -0
  76. package/dist/ops/overlay.d.ts.map +1 -0
  77. package/dist/ops/overlay.js +52 -0
  78. package/dist/ops/overlay.js.map +1 -0
  79. package/dist/ops/pad.d.ts +3 -0
  80. package/dist/ops/pad.d.ts.map +1 -0
  81. package/dist/ops/pad.js +62 -0
  82. package/dist/ops/pad.js.map +1 -0
  83. package/dist/ops/pipeline.d.ts +5 -0
  84. package/dist/ops/pipeline.d.ts.map +1 -0
  85. package/dist/ops/pipeline.js +81 -0
  86. package/dist/ops/pipeline.js.map +1 -0
  87. package/dist/ops/remove-bg.d.ts +3 -0
  88. package/dist/ops/remove-bg.d.ts.map +1 -0
  89. package/dist/ops/remove-bg.js +79 -0
  90. package/dist/ops/remove-bg.js.map +1 -0
  91. package/dist/ops/resize.d.ts +3 -0
  92. package/dist/ops/resize.d.ts.map +1 -0
  93. package/dist/ops/resize.js +54 -0
  94. package/dist/ops/resize.js.map +1 -0
  95. package/dist/ops/watermark.d.ts +3 -0
  96. package/dist/ops/watermark.d.ts.map +1 -0
  97. package/dist/ops/watermark.js +142 -0
  98. package/dist/ops/watermark.js.map +1 -0
  99. package/dist/types.d.ts +233 -0
  100. package/dist/types.d.ts.map +1 -0
  101. package/dist/types.js +12 -0
  102. package/dist/types.js.map +1 -0
  103. package/dist/utils/load-image.d.ts +9 -0
  104. package/dist/utils/load-image.d.ts.map +1 -0
  105. package/dist/utils/load-image.js +22 -0
  106. package/dist/utils/load-image.js.map +1 -0
  107. package/dist/utils/result.d.ts +4 -0
  108. package/dist/utils/result.d.ts.map +1 -0
  109. package/dist/utils/result.js +3 -0
  110. package/dist/utils/result.js.map +1 -0
  111. package/dist/utils/validate.d.ts +16 -0
  112. package/dist/utils/validate.d.ts.map +1 -0
  113. package/dist/utils/validate.js +20 -0
  114. package/dist/utils/validate.js.map +1 -0
  115. package/docs/AGENTS.md +18 -0
  116. package/docs/MCP.md +106 -0
  117. package/package.json +52 -0
  118. package/scripts/generate-fixtures.js +33 -0
  119. package/src/index.ts +24 -0
  120. package/src/mcp/index.ts +2 -0
  121. package/src/mcp/server.ts +21 -0
  122. package/src/mcp/tools.ts +276 -0
  123. package/src/ops/add-text.ts +139 -0
  124. package/src/ops/adjust.ts +68 -0
  125. package/src/ops/batch.ts +41 -0
  126. package/src/ops/blur-region.ts +58 -0
  127. package/src/ops/composite.ts +56 -0
  128. package/src/ops/convert.ts +46 -0
  129. package/src/ops/crop.ts +101 -0
  130. package/src/ops/detect-faces.ts +41 -0
  131. package/src/ops/detect-subject.ts +80 -0
  132. package/src/ops/extract-text.ts +19 -0
  133. package/src/ops/filter.ts +51 -0
  134. package/src/ops/get-dominant-colors.ts +41 -0
  135. package/src/ops/get-metadata.ts +28 -0
  136. package/src/ops/optimize.ts +77 -0
  137. package/src/ops/overlay.ts +51 -0
  138. package/src/ops/pad.ts +63 -0
  139. package/src/ops/pipeline.ts +61 -0
  140. package/src/ops/remove-bg.ts +82 -0
  141. package/src/ops/resize.ts +54 -0
  142. package/src/ops/watermark.ts +141 -0
  143. package/src/types/color-thief-node.d.ts +4 -0
  144. package/src/types.ts +267 -0
  145. package/src/utils/load-image.ts +21 -0
  146. package/src/utils/result.ts +4 -0
  147. package/src/utils/validate.ts +21 -0
  148. package/tests/fixtures/logo.png +0 -0
  149. package/tests/fixtures/sample.jpg +0 -0
  150. package/tests/fixtures/sample.png +0 -0
  151. package/tests/fixtures/sample.webp +0 -0
  152. package/tests/integration/error-handling.test.ts +22 -0
  153. package/tests/integration/load-image.test.ts +45 -0
  154. package/tests/unit/add-text.test.ts +56 -0
  155. package/tests/unit/adjust.test.ts +81 -0
  156. package/tests/unit/batch.test.ts +38 -0
  157. package/tests/unit/blur-region.test.ts +52 -0
  158. package/tests/unit/composite.test.ts +58 -0
  159. package/tests/unit/convert.test.ts +55 -0
  160. package/tests/unit/crop.test.ts +100 -0
  161. package/tests/unit/detect-faces.test.ts +32 -0
  162. package/tests/unit/detect-subject.test.ts +37 -0
  163. package/tests/unit/extract-text.test.ts +34 -0
  164. package/tests/unit/filter.test.ts +39 -0
  165. package/tests/unit/get-dominant-colors.test.ts +25 -0
  166. package/tests/unit/get-metadata.test.ts +36 -0
  167. package/tests/unit/mcp.test.ts +104 -0
  168. package/tests/unit/optimize.test.ts +47 -0
  169. package/tests/unit/overlay.test.ts +39 -0
  170. package/tests/unit/pad.test.ts +56 -0
  171. package/tests/unit/pipeline.test.ts +48 -0
  172. package/tests/unit/remove-bg.test.ts +42 -0
  173. package/tests/unit/resize.test.ts +70 -0
  174. package/tests/unit/watermark.test.ts +54 -0
  175. package/tsconfig.json +15 -0
  176. package/vitest.config.ts +27 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-bg.js","sourceRoot":"","sources":["../../src/ops/remove-bg.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { ResizeOptions, ImageInput, ImageResult } from '../types.js';
2
+ export declare function resize(input: ImageInput, options: ResizeOptions): Promise<ImageResult>;
3
+ //# sourceMappingURL=resize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resize.d.ts","sourceRoot":"","sources":["../../src/ops/resize.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAa,MAAM,aAAa,CAAC;AAKhF,wBAAsB,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CA+C5F"}
@@ -0,0 +1,54 @@
1
+ import sharp from 'sharp';
2
+ import { ErrorCode } from '../types.js';
3
+ import { loadImage } from '../utils/load-image.js';
4
+ import { err, ok } from '../utils/result.js';
5
+ import { getImageMetadata, isPositiveInt } from '../utils/validate.js';
6
+ export async function resize(input, options) {
7
+ try {
8
+ const buffer = await loadImage(input);
9
+ let width = options.width;
10
+ let height = options.height;
11
+ if (options.scale) {
12
+ if (options.scale <= 0)
13
+ return err('Scale must be positive', ErrorCode.INVALID_INPUT);
14
+ const meta = await getImageMetadata(buffer);
15
+ width = Math.round(meta.width * options.scale);
16
+ height = Math.round(meta.height * options.scale);
17
+ }
18
+ if (width !== undefined && !isPositiveInt(width)) {
19
+ return err('Width must be a positive integer', ErrorCode.INVALID_INPUT);
20
+ }
21
+ if (height !== undefined && !isPositiveInt(height)) {
22
+ return err('Height must be a positive integer', ErrorCode.INVALID_INPUT);
23
+ }
24
+ if (width === undefined && height === undefined) {
25
+ return err('Must provide width, height, or scale', ErrorCode.INVALID_INPUT);
26
+ }
27
+ let kernel;
28
+ if (options.kernel === 'linear')
29
+ kernel = 'mitchell';
30
+ else if (options.kernel)
31
+ kernel = options.kernel;
32
+ const output = await sharp(buffer)
33
+ .resize({
34
+ width,
35
+ height,
36
+ fit: options.fit,
37
+ kernel,
38
+ withoutEnlargement: options.withoutEnlargement
39
+ })
40
+ .toBuffer();
41
+ return ok(output);
42
+ }
43
+ catch (e) {
44
+ const msg = e.message || '';
45
+ if (msg.includes('HTTP'))
46
+ return err(msg, ErrorCode.FETCH_FAILED);
47
+ if (msg.includes('ENOENT'))
48
+ return err('File not found', ErrorCode.INVALID_INPUT);
49
+ if (msg.includes('unsupported image format'))
50
+ return err('Corrupt or unsupported input', ErrorCode.INVALID_INPUT);
51
+ return err(msg, ErrorCode.PROCESSING_FAILED);
52
+ }
53
+ }
54
+ //# sourceMappingURL=resize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resize.js","sourceRoot":"","sources":["../../src/ops/resize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAA0C,SAAS,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEvE,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,KAAiB,EAAE,OAAsB;IACpE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;QAEtC,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC1B,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAE5B,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC;gBAAE,OAAO,GAAG,CAAC,wBAAwB,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC;YACtF,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAC5C,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YAC/C,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,OAAO,GAAG,CAAC,kCAAkC,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,OAAO,GAAG,CAAC,mCAAmC,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC;QAC3E,CAAC;QAED,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAChD,OAAO,GAAG,CAAC,sCAAsC,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC;QAC9E,CAAC;QAED,IAAI,MAA0C,CAAC;QAC/C,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ;YAAE,MAAM,GAAG,UAAU,CAAC;aAChD,IAAI,OAAO,CAAC,MAAM;YAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAEjD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC;aAC/B,MAAM,CAAC;YACN,KAAK;YACL,MAAM;YACN,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,MAAM;YACN,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;SAC/C,CAAC;aACD,QAAQ,EAAE,CAAC;QAEd,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;QAC5B,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;QAClE,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,OAAO,GAAG,CAAC,gBAAgB,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC;QAClF,IAAI,GAAG,CAAC,QAAQ,CAAC,0BAA0B,CAAC;YAAE,OAAO,GAAG,CAAC,8BAA8B,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC;QAClH,OAAO,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { WatermarkOptions, ImageInput, ImageResult } from '../types.js';
2
+ export declare function watermark(input: ImageInput, options: WatermarkOptions): Promise<ImageResult>;
3
+ //# sourceMappingURL=watermark.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watermark.d.ts","sourceRoot":"","sources":["../../src/ops/watermark.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,WAAW,EAAyB,MAAM,aAAa,CAAC;AA2B/F,wBAAsB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAgHlG"}
@@ -0,0 +1,142 @@
1
+ import sharp from 'sharp';
2
+ import { ErrorCode } from '../types.js';
3
+ import { loadImage } from '../utils/load-image.js';
4
+ import { err, ok } from '../utils/result.js';
5
+ import { getImageMetadata } from '../utils/validate.js';
6
+ import { addText } from './add-text.js';
7
+ import { resize } from './resize.js';
8
+ const posToGravity = {
9
+ 'top-left': 'northwest',
10
+ 'top-center': 'north',
11
+ 'top-right': 'northeast',
12
+ 'center': 'center',
13
+ 'bottom-left': 'southwest',
14
+ 'bottom-center': 'south',
15
+ 'bottom-right': 'southeast'
16
+ };
17
+ const posToAnchor = {
18
+ 'top-left': 'top-left',
19
+ 'top-center': 'top-center',
20
+ 'top-right': 'top-right',
21
+ 'center': 'center',
22
+ 'bottom-left': 'bottom-left',
23
+ 'bottom-center': 'bottom-center',
24
+ 'bottom-right': 'bottom-right'
25
+ };
26
+ export async function watermark(input, options) {
27
+ try {
28
+ const buffer = await loadImage(input);
29
+ const meta = await getImageMetadata(buffer);
30
+ const position = options.position || 'bottom-right';
31
+ if (options.type === 'text') {
32
+ if (position === 'tile') {
33
+ const spacing = options.tileSpacing ?? 50;
34
+ const fontSize = options.fontSize ?? 24;
35
+ const color = options.color ?? '#ffffff';
36
+ const opacity = options.opacity ?? 0.5;
37
+ const charWidth = fontSize * 0.6;
38
+ const w = options.text.length * charWidth;
39
+ const h = fontSize;
40
+ const cols = Math.ceil(meta.width / Math.max(1, (w + spacing)));
41
+ const rows = Math.ceil(meta.height / Math.max(1, (h + spacing)));
42
+ const layers = [];
43
+ for (let r = 0; r < rows; r++) {
44
+ for (let c = 0; c < cols; c++) {
45
+ layers.push({
46
+ text: options.text,
47
+ x: c * (w + spacing),
48
+ y: r * (h + spacing),
49
+ fontSize,
50
+ color,
51
+ opacity,
52
+ anchor: 'top-left'
53
+ });
54
+ }
55
+ }
56
+ return addText(buffer, { layers });
57
+ }
58
+ else {
59
+ const anchor = posToAnchor[position] || 'bottom-right';
60
+ let x = 0, y = 0;
61
+ const pad = 10;
62
+ const fontSize = options.fontSize ?? 24;
63
+ if (position.includes('left'))
64
+ x = pad;
65
+ else if (position.includes('right'))
66
+ x = meta.width - pad;
67
+ else
68
+ x = meta.width / 2;
69
+ if (position.includes('top'))
70
+ y = pad;
71
+ else if (position.includes('bottom'))
72
+ y = meta.height - pad;
73
+ else
74
+ y = meta.height / 2;
75
+ return addText(buffer, {
76
+ layers: [{
77
+ text: options.text,
78
+ x, y, anchor,
79
+ fontSize,
80
+ color: options.color ?? '#ffffff',
81
+ opacity: options.opacity ?? 0.5
82
+ }]
83
+ });
84
+ }
85
+ }
86
+ else if (options.type === 'image') {
87
+ let wmBuf = await loadImage(options.image);
88
+ const wmMeta = await getImageMetadata(wmBuf);
89
+ if (options.scale && options.scale !== 1.0) {
90
+ const r = await resize(wmBuf, { scale: options.scale });
91
+ if (!r.ok)
92
+ return r;
93
+ wmBuf = r.data;
94
+ }
95
+ if (options.opacity !== undefined && options.opacity >= 0 && options.opacity < 1) {
96
+ wmBuf = await sharp(wmBuf)
97
+ .ensureAlpha()
98
+ .composite([
99
+ {
100
+ input: Buffer.from([255, 255, 255, Math.round(options.opacity * 255)]),
101
+ raw: { width: 1, height: 1, channels: 4 },
102
+ tile: true,
103
+ blend: 'dest-in'
104
+ }
105
+ ])
106
+ .toBuffer();
107
+ }
108
+ if (position === 'tile') {
109
+ const spacing = options.tileSpacing ?? 0;
110
+ if (spacing > 0) {
111
+ wmBuf = await sharp(wmBuf)
112
+ .ensureAlpha()
113
+ .extend({ bottom: spacing, right: spacing, background: { r: 0, g: 0, b: 0, alpha: 0 } })
114
+ .toBuffer();
115
+ }
116
+ const output = await sharp(buffer)
117
+ .composite([{ input: wmBuf, tile: true, blend: 'over' }])
118
+ .toBuffer();
119
+ return ok(output);
120
+ }
121
+ else {
122
+ const gravity = posToGravity[position] || 'southeast';
123
+ const output = await sharp(buffer)
124
+ .composite([{ input: wmBuf, gravity, blend: 'over' }])
125
+ .toBuffer();
126
+ return ok(output);
127
+ }
128
+ }
129
+ return err('Invalid watermark type', ErrorCode.INVALID_INPUT);
130
+ }
131
+ catch (e) {
132
+ const msg = e.message || '';
133
+ if (msg.includes('HTTP'))
134
+ return err(msg, ErrorCode.FETCH_FAILED);
135
+ if (msg.includes('ENOENT'))
136
+ return err('File not found', ErrorCode.INVALID_INPUT);
137
+ if (msg.includes('unsupported image format'))
138
+ return err('Corrupt or unsupported input', ErrorCode.INVALID_INPUT);
139
+ return err(msg, ErrorCode.PROCESSING_FAILED);
140
+ }
141
+ }
142
+ //# sourceMappingURL=watermark.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watermark.js","sourceRoot":"","sources":["../../src/ops/watermark.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,233 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ /// <reference types="node" resolution-mode="require"/>
3
+ /**
4
+ * Accepted image input formats.
5
+ * - Buffer: raw image bytes
6
+ * - string starting with 'http': fetched via HTTP
7
+ * - string starting with 'data:': base64 data URI
8
+ * - string (other): treated as filesystem path
9
+ */
10
+ export type ImageInput = Buffer | string;
11
+ export type Ok<T> = {
12
+ ok: true;
13
+ data: T;
14
+ };
15
+ export type Err = {
16
+ ok: false;
17
+ error: string;
18
+ code: ErrorCode;
19
+ };
20
+ export type Result<T> = Ok<T> | Err;
21
+ export type ImageResult = Result<Buffer>;
22
+ export declare enum ErrorCode {
23
+ INVALID_INPUT = "INVALID_INPUT",
24
+ UNSUPPORTED_FORMAT = "UNSUPPORTED_FORMAT",
25
+ OUT_OF_BOUNDS = "OUT_OF_BOUNDS",
26
+ FETCH_FAILED = "FETCH_FAILED",
27
+ PROCESSING_FAILED = "PROCESSING_FAILED",
28
+ MODEL_NOT_FOUND = "MODEL_NOT_FOUND",
29
+ TIMEOUT = "TIMEOUT"
30
+ }
31
+ export type CropOptions = {
32
+ mode?: 'absolute';
33
+ x: number;
34
+ y: number;
35
+ width: number;
36
+ height: number;
37
+ } | {
38
+ mode: 'ratio';
39
+ left: number;
40
+ top: number;
41
+ right: number;
42
+ bottom: number;
43
+ } | {
44
+ mode: 'aspect';
45
+ aspectRatio: string;
46
+ anchor?: 'center' | 'top' | 'bottom' | 'face';
47
+ } | {
48
+ mode: 'subject';
49
+ };
50
+ export type ResizeFit = 'cover' | 'contain' | 'fill' | 'inside' | 'outside';
51
+ export type ResizeKernel = 'lanczos3' | 'nearest' | 'linear';
52
+ export interface ResizeOptions {
53
+ width?: number;
54
+ height?: number;
55
+ scale?: number;
56
+ fit?: ResizeFit;
57
+ kernel?: ResizeKernel;
58
+ /** Preserve aspect ratio when only one dimension is given. Default: true */
59
+ withoutEnlargement?: boolean;
60
+ }
61
+ export interface PadOptions {
62
+ top?: number;
63
+ right?: number;
64
+ bottom?: number;
65
+ left?: number;
66
+ /** Square canvas shorthand: centers image and pads to this size */
67
+ size?: number;
68
+ /** CSS hex color or 'transparent'. Default: '#ffffff' */
69
+ color?: string;
70
+ }
71
+ export interface AdjustOptions {
72
+ /** -100 to +100 */
73
+ brightness?: number;
74
+ /** -100 to +100 */
75
+ contrast?: number;
76
+ /** -100 to +100 */
77
+ saturation?: number;
78
+ /** 0 to 360 degrees */
79
+ hue?: number;
80
+ /** 0 to 100 */
81
+ sharpness?: number;
82
+ /** -100 (cool) to +100 (warm) */
83
+ temperature?: number;
84
+ }
85
+ export type FilterPreset = 'grayscale' | 'sepia' | 'invert' | 'vintage' | 'unsharp';
86
+ export type FilterOptions = {
87
+ preset: Exclude<FilterPreset, 'blur'>;
88
+ } | {
89
+ preset: 'blur';
90
+ radius: number;
91
+ };
92
+ export interface BlurRegion {
93
+ x: number;
94
+ y: number;
95
+ width: number;
96
+ height: number;
97
+ /** Blur strength (sigma). Default: 10 */
98
+ radius?: number;
99
+ }
100
+ export type TextAnchor = 'top-left' | 'top-center' | 'top-right' | 'middle-left' | 'center' | 'middle-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
101
+ export interface TextBackground {
102
+ color: string;
103
+ padding?: number;
104
+ opacity?: number;
105
+ borderRadius?: number;
106
+ }
107
+ export interface TextLayer {
108
+ text: string;
109
+ x: number;
110
+ y: number;
111
+ anchor?: TextAnchor;
112
+ fontSize?: number;
113
+ fontFamily?: string;
114
+ /** Google Fonts URL or local file path */
115
+ fontUrl?: string;
116
+ color?: string;
117
+ opacity?: number;
118
+ align?: 'left' | 'center' | 'right';
119
+ /** Wrap text at this pixel width */
120
+ maxWidth?: number;
121
+ lineHeight?: number;
122
+ background?: TextBackground;
123
+ }
124
+ export type BlendMode = 'over' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten';
125
+ export interface CompositeLayer {
126
+ image: ImageInput;
127
+ x?: number;
128
+ y?: number;
129
+ blend?: BlendMode;
130
+ opacity?: number;
131
+ }
132
+ export type WatermarkPosition = 'top-left' | 'top-center' | 'top-right' | 'center' | 'bottom-left' | 'bottom-center' | 'bottom-right' | 'tile';
133
+ export type WatermarkOptions = {
134
+ type: 'text';
135
+ text: string;
136
+ position?: WatermarkPosition;
137
+ fontSize?: number;
138
+ color?: string;
139
+ opacity?: number;
140
+ tileSpacing?: number;
141
+ } | {
142
+ type: 'image';
143
+ image: ImageInput;
144
+ position?: WatermarkPosition;
145
+ opacity?: number;
146
+ scale?: number;
147
+ tileSpacing?: number;
148
+ };
149
+ export type Gravity = 'NorthWest' | 'North' | 'NorthEast' | 'West' | 'Center' | 'East' | 'SouthWest' | 'South' | 'SouthEast';
150
+ export interface OverlayOptions {
151
+ gravity?: Gravity;
152
+ offsetX?: number;
153
+ offsetY?: number;
154
+ opacity?: number;
155
+ blend?: BlendMode;
156
+ }
157
+ export type RemoveBgEngine = 'onnx' | 'webai';
158
+ export interface RemoveBgOptions {
159
+ engine?: RemoveBgEngine;
160
+ /** Replace transparency with this solid color instead */
161
+ replaceColor?: string;
162
+ /** Replace background with this image */
163
+ replaceImage?: ImageInput;
164
+ }
165
+ export interface BoundingBox {
166
+ x: number;
167
+ y: number;
168
+ width: number;
169
+ height: number;
170
+ confidence: number;
171
+ }
172
+ export type OutputFormat = 'jpeg' | 'png' | 'webp' | 'avif' | 'gif';
173
+ export interface ConvertOptions {
174
+ format: OutputFormat;
175
+ /** 0–100. Default: 80 */
176
+ quality?: number;
177
+ /** PNG only. 0–9. Default: 6 */
178
+ compressionLevel?: number;
179
+ /** Strip all metadata. Default: true */
180
+ stripMetadata?: boolean;
181
+ }
182
+ export interface OptimizeOptions {
183
+ /** Target file size in KB. Quality is adjusted automatically */
184
+ maxSizeKB?: number;
185
+ /** Resize so the longest dimension does not exceed this value */
186
+ maxDimension?: number;
187
+ /** Auto-select format (WebP if alpha, JPEG otherwise). Default: true */
188
+ autoFormat?: boolean;
189
+ }
190
+ export interface ImageMetadata {
191
+ width: number;
192
+ height: number;
193
+ format: string;
194
+ fileSize: number;
195
+ colorSpace?: string;
196
+ hasAlpha: boolean;
197
+ channels: number;
198
+ density?: number;
199
+ exif?: Record<string, unknown>;
200
+ }
201
+ export type PipelineOperation = ({
202
+ op: 'crop';
203
+ } & CropOptions) | ({
204
+ op: 'resize';
205
+ } & ResizeOptions) | ({
206
+ op: 'pad';
207
+ } & PadOptions) | ({
208
+ op: 'adjust';
209
+ } & AdjustOptions) | ({
210
+ op: 'filter';
211
+ } & FilterOptions) | ({
212
+ op: 'blurRegion';
213
+ regions: BlurRegion[];
214
+ }) | ({
215
+ op: 'addText';
216
+ layers: TextLayer[];
217
+ }) | ({
218
+ op: 'composite';
219
+ layers: CompositeLayer[];
220
+ }) | ({
221
+ op: 'watermark';
222
+ } & WatermarkOptions) | ({
223
+ op: 'convert';
224
+ } & ConvertOptions) | ({
225
+ op: 'optimize';
226
+ } & OptimizeOptions) | ({
227
+ op: 'removeBg';
228
+ } & RemoveBgOptions);
229
+ export interface BatchOptions {
230
+ concurrency?: number;
231
+ onProgress?: (done: number, total: number) => void;
232
+ }
233
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,12 @@
1
+ // ─── Input ────────────────────────────────────────────────────────────────────
2
+ export var ErrorCode;
3
+ (function (ErrorCode) {
4
+ ErrorCode["INVALID_INPUT"] = "INVALID_INPUT";
5
+ ErrorCode["UNSUPPORTED_FORMAT"] = "UNSUPPORTED_FORMAT";
6
+ ErrorCode["OUT_OF_BOUNDS"] = "OUT_OF_BOUNDS";
7
+ ErrorCode["FETCH_FAILED"] = "FETCH_FAILED";
8
+ ErrorCode["PROCESSING_FAILED"] = "PROCESSING_FAILED";
9
+ ErrorCode["MODEL_NOT_FOUND"] = "MODEL_NOT_FOUND";
10
+ ErrorCode["TIMEOUT"] = "TIMEOUT";
11
+ })(ErrorCode || (ErrorCode = {}));
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,iFAAiF;AAkBjF,MAAM,CAAN,IAAY,SAQX;AARD,WAAY,SAAS;IACnB,4CAA+B,CAAA;IAC/B,sDAAyC,CAAA;IACzC,4CAA+B,CAAA;IAC/B,0CAA6B,CAAA;IAC7B,oDAAuC,CAAA;IACvC,gDAAmC,CAAA;IACnC,gCAAmB,CAAA;AACrB,CAAC,EARW,SAAS,KAAT,SAAS,QAQpB"}
@@ -0,0 +1,9 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ /// <reference types="node" resolution-mode="require"/>
3
+ import { ImageInput } from '../types.js';
4
+ /**
5
+ * Resolves any ImageInput variant to a Buffer.
6
+ * Handles: Buffer (passthrough), URL (fetch), base64 data URI (decode), file path (readFile).
7
+ */
8
+ export declare function loadImage(input: ImageInput): Promise<Buffer>;
9
+ //# sourceMappingURL=load-image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-image.d.ts","sourceRoot":"","sources":["../../src/utils/load-image.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC;;;GAGG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAYlE"}
@@ -0,0 +1,22 @@
1
+ import { readFile } from 'fs/promises';
2
+ import fetch from 'node-fetch';
3
+ /**
4
+ * Resolves any ImageInput variant to a Buffer.
5
+ * Handles: Buffer (passthrough), URL (fetch), base64 data URI (decode), file path (readFile).
6
+ */
7
+ export async function loadImage(input) {
8
+ if (Buffer.isBuffer(input))
9
+ return input;
10
+ if (input.startsWith('data:')) {
11
+ const base64 = input.split(',')[1];
12
+ return Buffer.from(base64, 'base64');
13
+ }
14
+ if (input.startsWith('http://') || input.startsWith('https://')) {
15
+ const res = await fetch(input);
16
+ if (!res.ok)
17
+ throw new Error(`HTTP ${res.status}`);
18
+ return Buffer.from(await res.arrayBuffer());
19
+ }
20
+ return readFile(input);
21
+ }
22
+ //# sourceMappingURL=load-image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-image.js","sourceRoot":"","sources":["../../src/utils/load-image.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAiB;IAC/C,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAChE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACnD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Ok, Err, ErrorCode } from '../types.js';
2
+ export declare const ok: <T>(data: T) => Ok<T>;
3
+ export declare const err: (error: string, code: ErrorCode) => Err;
4
+ //# sourceMappingURL=result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/utils/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEhD,eAAO,MAAM,EAAE,YAAa,CAAC,KAAG,GAAG,CAAC,CAAyB,CAAA;AAC7D,eAAO,MAAM,GAAG,UAAW,MAAM,QAAQ,SAAS,KAAG,GAAmC,CAAA"}
@@ -0,0 +1,3 @@
1
+ export const ok = (data) => ({ ok: true, data });
2
+ export const err = (error, code) => ({ ok: false, error, code });
3
+ //# sourceMappingURL=result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/utils/result.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,EAAE,GAAG,CAAI,IAAO,EAAS,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;AAC7D,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,KAAa,EAAE,IAAe,EAAO,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA"}
@@ -0,0 +1,16 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ /// <reference types="node" resolution-mode="require"/>
3
+ /**
4
+ * Helper to ensure a value is a positive integer.
5
+ */
6
+ export declare function isPositiveInt(val: any): boolean;
7
+ /**
8
+ * Helper to get basic dimensions securely via sharp metadata
9
+ */
10
+ export declare function getImageMetadata(buffer: Buffer): Promise<{
11
+ width: number;
12
+ height: number;
13
+ hasAlpha: boolean;
14
+ format: string;
15
+ }>;
16
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/utils/validate.ts"],"names":[],"mappings":";;AAEA;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAE/C;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM;;;;;GAQpD"}
@@ -0,0 +1,20 @@
1
+ import sharp from 'sharp';
2
+ /**
3
+ * Helper to ensure a value is a positive integer.
4
+ */
5
+ export function isPositiveInt(val) {
6
+ return typeof val === 'number' && Number.isInteger(val) && val > 0;
7
+ }
8
+ /**
9
+ * Helper to get basic dimensions securely via sharp metadata
10
+ */
11
+ export async function getImageMetadata(buffer) {
12
+ const metadata = await sharp(buffer).metadata();
13
+ return {
14
+ width: metadata.width ?? 0,
15
+ height: metadata.height ?? 0,
16
+ hasAlpha: metadata.hasAlpha ?? false,
17
+ format: metadata.format ?? 'unknown'
18
+ };
19
+ }
20
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/utils/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,GAAQ;IACpC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;AACrE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc;IACnD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IAChD,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,CAAC;QAC1B,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,CAAC;QAC5B,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IAAI,KAAK;QACpC,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,SAAS;KACrC,CAAC;AACJ,CAAC"}
package/docs/AGENTS.md ADDED
@@ -0,0 +1,18 @@
1
+ # Guide for AI Agents
2
+
3
+ Welcome, fellow AI agent! `image-edit-tools` is designed specifically for you to perform robust, deterministic image edits without writing custom scripts.
4
+
5
+ ## Core Tenets
6
+ 1. **Never Throw**: All tools return a guaranteed structured JSON response with either `{ ok: true, data: ... }` or `{ ok: false, error: ... }`. You don't need to wrap in `try/catch`.
7
+ 2. **Flexible Input**: For the `image` parameter, you can pass a URL, local file path, or Base64 data URI (e.g. `data:image/png;base64,...`).
8
+ 3. **Data URIs**: Results containing an image buffer are automatically encoded as Base64 Data URIs in the output `data` field, so you can immediate use them in downstream vision models or HTML.
9
+
10
+ ## Best Practices
11
+ - **Pipelines**: Instead of calling `image_crop`, then `image_resize`, then `image_convert` using three separate tool calls (which transfers images back and forth 3 times), use the `image_pipeline` tool! Pass an array of operations. It is dramatically faster and avoids memory overhead.
12
+ - **Analysis First**: When instructed to edit an image based on its content (e.g. "Blur the person's face"), first call `image_detect_faces`. Parse the coordinates, then construct an `image_blur_region` payload using exactly those coordinates.
13
+ - **No Side Effects**: All tools are pure functions. They compute and return the image. If the user asks you to modify a file, you must take the data URI returned by the tool and write it back to the file system using your filesystem tools.
14
+
15
+ ## Example Chain (Watermarking)
16
+ 1. **Goal**: Add a bottom-right watermark.
17
+ 2. **Action**: Call `image_watermark` with `image: "/path/to/source.jpg"`, `type: "text"`, `text: "Draft"`, `position: "bottom-right"`.
18
+ 3. **Save**: Take `result.data` (Base64), decode it using standard encoding logic, and save it to the requested location.