apexify.js 5.1.1 → 5.2.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 (236) hide show
  1. package/CHANGELOG.md +240 -0
  2. package/README.md +248 -1105
  3. package/dist/cjs/Canvas/ApexPainter.d.ts +182 -204
  4. package/dist/cjs/Canvas/ApexPainter.d.ts.map +1 -1
  5. package/dist/cjs/Canvas/ApexPainter.js +482 -1286
  6. package/dist/cjs/Canvas/ApexPainter.js.map +1 -1
  7. package/dist/cjs/Canvas/extended/CanvasCreator.d.ts +33 -0
  8. package/dist/cjs/Canvas/extended/CanvasCreator.d.ts.map +1 -0
  9. package/dist/cjs/Canvas/extended/CanvasCreator.js +223 -0
  10. package/dist/cjs/Canvas/extended/CanvasCreator.js.map +1 -0
  11. package/dist/cjs/Canvas/extended/ChartCreator.d.ts +26 -0
  12. package/dist/cjs/Canvas/extended/ChartCreator.d.ts.map +1 -0
  13. package/dist/cjs/Canvas/extended/ChartCreator.js +50 -0
  14. package/dist/cjs/Canvas/extended/ChartCreator.js.map +1 -0
  15. package/dist/cjs/Canvas/extended/GIFCreator.d.ts +43 -0
  16. package/dist/cjs/Canvas/extended/GIFCreator.d.ts.map +1 -0
  17. package/dist/cjs/Canvas/extended/GIFCreator.js +157 -0
  18. package/dist/cjs/Canvas/extended/GIFCreator.js.map +1 -0
  19. package/dist/cjs/Canvas/extended/ImageCreator.d.ts +83 -0
  20. package/dist/cjs/Canvas/extended/ImageCreator.d.ts.map +1 -0
  21. package/dist/cjs/Canvas/extended/ImageCreator.js +479 -0
  22. package/dist/cjs/Canvas/extended/ImageCreator.js.map +1 -0
  23. package/dist/cjs/Canvas/extended/TextCreator.d.ts +35 -0
  24. package/dist/cjs/Canvas/extended/TextCreator.d.ts.map +1 -0
  25. package/dist/cjs/Canvas/extended/TextCreator.js +98 -0
  26. package/dist/cjs/Canvas/extended/TextCreator.js.map +1 -0
  27. package/dist/cjs/Canvas/extended/VideoCreator.d.ts +370 -0
  28. package/dist/cjs/Canvas/extended/VideoCreator.d.ts.map +1 -0
  29. package/dist/cjs/Canvas/extended/VideoCreator.js +478 -0
  30. package/dist/cjs/Canvas/extended/VideoCreator.js.map +1 -0
  31. package/dist/cjs/Canvas/utils/Background/bg.d.ts +1 -1
  32. package/dist/cjs/Canvas/utils/Background/bg.d.ts.map +1 -1
  33. package/dist/cjs/Canvas/utils/Background/bg.js +43 -7
  34. package/dist/cjs/Canvas/utils/Background/bg.js.map +1 -1
  35. package/dist/cjs/Canvas/utils/Charts/barchart.d.ts +230 -0
  36. package/dist/cjs/Canvas/utils/Charts/barchart.d.ts.map +1 -0
  37. package/dist/cjs/Canvas/utils/Charts/barchart.js +1891 -0
  38. package/dist/cjs/Canvas/utils/Charts/barchart.js.map +1 -0
  39. package/dist/cjs/Canvas/utils/Charts/comparisonchart.d.ts +103 -0
  40. package/dist/cjs/Canvas/utils/Charts/comparisonchart.d.ts.map +1 -0
  41. package/dist/cjs/Canvas/utils/Charts/comparisonchart.js +368 -0
  42. package/dist/cjs/Canvas/utils/Charts/comparisonchart.js.map +1 -0
  43. package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.d.ts +178 -0
  44. package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.d.ts.map +1 -0
  45. package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.js +1389 -0
  46. package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.js.map +1 -0
  47. package/dist/cjs/Canvas/utils/Charts/index.d.ts +45 -0
  48. package/dist/cjs/Canvas/utils/Charts/index.d.ts.map +1 -0
  49. package/dist/cjs/Canvas/utils/Charts/index.js +17 -0
  50. package/dist/cjs/Canvas/utils/Charts/index.js.map +1 -0
  51. package/dist/cjs/Canvas/utils/Charts/linechart.d.ts +216 -0
  52. package/dist/cjs/Canvas/utils/Charts/linechart.d.ts.map +1 -0
  53. package/dist/cjs/Canvas/utils/Charts/linechart.js +1761 -0
  54. package/dist/cjs/Canvas/utils/Charts/linechart.js.map +1 -0
  55. package/dist/cjs/Canvas/utils/Charts/piechart.d.ts +167 -0
  56. package/dist/cjs/Canvas/utils/Charts/piechart.d.ts.map +1 -0
  57. package/dist/cjs/Canvas/utils/Charts/piechart.js +794 -0
  58. package/dist/cjs/Canvas/utils/Charts/piechart.js.map +1 -0
  59. package/dist/cjs/Canvas/utils/General/batchOperations.d.ts.map +1 -1
  60. package/dist/cjs/Canvas/utils/General/batchOperations.js +3 -4
  61. package/dist/cjs/Canvas/utils/General/batchOperations.js.map +1 -1
  62. package/dist/cjs/Canvas/utils/General/general functions.d.ts.map +1 -1
  63. package/dist/cjs/Canvas/utils/General/general functions.js +62 -33
  64. package/dist/cjs/Canvas/utils/General/general functions.js.map +1 -1
  65. package/dist/cjs/Canvas/utils/General/imageStitching.d.ts.map +1 -1
  66. package/dist/cjs/Canvas/utils/General/imageStitching.js +3 -6
  67. package/dist/cjs/Canvas/utils/General/imageStitching.js.map +1 -1
  68. package/dist/cjs/Canvas/utils/Image/imageMasking.d.ts.map +1 -1
  69. package/dist/cjs/Canvas/utils/Image/imageMasking.js +5 -12
  70. package/dist/cjs/Canvas/utils/Image/imageMasking.js.map +1 -1
  71. package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts +4 -4
  72. package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
  73. package/dist/cjs/Canvas/utils/Image/imageProperties.js +44 -9
  74. package/dist/cjs/Canvas/utils/Image/imageProperties.js.map +1 -1
  75. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts +5 -0
  76. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -1
  77. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js +48 -5
  78. package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -1
  79. package/dist/cjs/Canvas/utils/Texts/textProperties.d.ts +1 -1
  80. package/dist/cjs/Canvas/utils/Texts/textProperties.d.ts.map +1 -1
  81. package/dist/cjs/Canvas/utils/Texts/textProperties.js +48 -5
  82. package/dist/cjs/Canvas/utils/Texts/textProperties.js.map +1 -1
  83. package/dist/cjs/Canvas/utils/Video/videoHelpers.d.ts +489 -0
  84. package/dist/cjs/Canvas/utils/Video/videoHelpers.d.ts.map +1 -0
  85. package/dist/cjs/Canvas/utils/Video/videoHelpers.js +1835 -0
  86. package/dist/cjs/Canvas/utils/Video/videoHelpers.js.map +1 -0
  87. package/dist/cjs/Canvas/utils/errorUtils.d.ts +15 -0
  88. package/dist/cjs/Canvas/utils/errorUtils.d.ts.map +1 -0
  89. package/dist/cjs/Canvas/utils/errorUtils.js +26 -0
  90. package/dist/cjs/Canvas/utils/errorUtils.js.map +1 -0
  91. package/dist/cjs/Canvas/utils/types.d.ts +17 -178
  92. package/dist/cjs/Canvas/utils/types.d.ts.map +1 -1
  93. package/dist/cjs/Canvas/utils/types.js.map +1 -1
  94. package/dist/cjs/Canvas/utils/utils.d.ts +4 -3
  95. package/dist/cjs/Canvas/utils/utils.d.ts.map +1 -1
  96. package/dist/cjs/Canvas/utils/utils.js +40 -6
  97. package/dist/cjs/Canvas/utils/utils.js.map +1 -1
  98. package/dist/cjs/index.d.ts +1 -8
  99. package/dist/cjs/index.d.ts.map +1 -1
  100. package/dist/cjs/index.js +14 -45
  101. package/dist/cjs/index.js.map +1 -1
  102. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  103. package/dist/esm/Canvas/ApexPainter.d.ts +182 -204
  104. package/dist/esm/Canvas/ApexPainter.d.ts.map +1 -1
  105. package/dist/esm/Canvas/ApexPainter.js +482 -1286
  106. package/dist/esm/Canvas/ApexPainter.js.map +1 -1
  107. package/dist/esm/Canvas/extended/CanvasCreator.d.ts +33 -0
  108. package/dist/esm/Canvas/extended/CanvasCreator.d.ts.map +1 -0
  109. package/dist/esm/Canvas/extended/CanvasCreator.js +223 -0
  110. package/dist/esm/Canvas/extended/CanvasCreator.js.map +1 -0
  111. package/dist/esm/Canvas/extended/ChartCreator.d.ts +26 -0
  112. package/dist/esm/Canvas/extended/ChartCreator.d.ts.map +1 -0
  113. package/dist/esm/Canvas/extended/ChartCreator.js +50 -0
  114. package/dist/esm/Canvas/extended/ChartCreator.js.map +1 -0
  115. package/dist/esm/Canvas/extended/GIFCreator.d.ts +43 -0
  116. package/dist/esm/Canvas/extended/GIFCreator.d.ts.map +1 -0
  117. package/dist/esm/Canvas/extended/GIFCreator.js +157 -0
  118. package/dist/esm/Canvas/extended/GIFCreator.js.map +1 -0
  119. package/dist/esm/Canvas/extended/ImageCreator.d.ts +83 -0
  120. package/dist/esm/Canvas/extended/ImageCreator.d.ts.map +1 -0
  121. package/dist/esm/Canvas/extended/ImageCreator.js +479 -0
  122. package/dist/esm/Canvas/extended/ImageCreator.js.map +1 -0
  123. package/dist/esm/Canvas/extended/TextCreator.d.ts +35 -0
  124. package/dist/esm/Canvas/extended/TextCreator.d.ts.map +1 -0
  125. package/dist/esm/Canvas/extended/TextCreator.js +98 -0
  126. package/dist/esm/Canvas/extended/TextCreator.js.map +1 -0
  127. package/dist/esm/Canvas/extended/VideoCreator.d.ts +370 -0
  128. package/dist/esm/Canvas/extended/VideoCreator.d.ts.map +1 -0
  129. package/dist/esm/Canvas/extended/VideoCreator.js +478 -0
  130. package/dist/esm/Canvas/extended/VideoCreator.js.map +1 -0
  131. package/dist/esm/Canvas/utils/Background/bg.d.ts +1 -1
  132. package/dist/esm/Canvas/utils/Background/bg.d.ts.map +1 -1
  133. package/dist/esm/Canvas/utils/Background/bg.js +43 -7
  134. package/dist/esm/Canvas/utils/Background/bg.js.map +1 -1
  135. package/dist/esm/Canvas/utils/Charts/barchart.d.ts +230 -0
  136. package/dist/esm/Canvas/utils/Charts/barchart.d.ts.map +1 -0
  137. package/dist/esm/Canvas/utils/Charts/barchart.js +1891 -0
  138. package/dist/esm/Canvas/utils/Charts/barchart.js.map +1 -0
  139. package/dist/esm/Canvas/utils/Charts/comparisonchart.d.ts +103 -0
  140. package/dist/esm/Canvas/utils/Charts/comparisonchart.d.ts.map +1 -0
  141. package/dist/esm/Canvas/utils/Charts/comparisonchart.js +368 -0
  142. package/dist/esm/Canvas/utils/Charts/comparisonchart.js.map +1 -0
  143. package/dist/esm/Canvas/utils/Charts/horizontalbarchart.d.ts +178 -0
  144. package/dist/esm/Canvas/utils/Charts/horizontalbarchart.d.ts.map +1 -0
  145. package/dist/esm/Canvas/utils/Charts/horizontalbarchart.js +1389 -0
  146. package/dist/esm/Canvas/utils/Charts/horizontalbarchart.js.map +1 -0
  147. package/dist/esm/Canvas/utils/Charts/index.d.ts +45 -0
  148. package/dist/esm/Canvas/utils/Charts/index.d.ts.map +1 -0
  149. package/dist/esm/Canvas/utils/Charts/index.js +17 -0
  150. package/dist/esm/Canvas/utils/Charts/index.js.map +1 -0
  151. package/dist/esm/Canvas/utils/Charts/linechart.d.ts +216 -0
  152. package/dist/esm/Canvas/utils/Charts/linechart.d.ts.map +1 -0
  153. package/dist/esm/Canvas/utils/Charts/linechart.js +1761 -0
  154. package/dist/esm/Canvas/utils/Charts/linechart.js.map +1 -0
  155. package/dist/esm/Canvas/utils/Charts/piechart.d.ts +167 -0
  156. package/dist/esm/Canvas/utils/Charts/piechart.d.ts.map +1 -0
  157. package/dist/esm/Canvas/utils/Charts/piechart.js +794 -0
  158. package/dist/esm/Canvas/utils/Charts/piechart.js.map +1 -0
  159. package/dist/esm/Canvas/utils/General/batchOperations.d.ts.map +1 -1
  160. package/dist/esm/Canvas/utils/General/batchOperations.js +3 -4
  161. package/dist/esm/Canvas/utils/General/batchOperations.js.map +1 -1
  162. package/dist/esm/Canvas/utils/General/general functions.d.ts.map +1 -1
  163. package/dist/esm/Canvas/utils/General/general functions.js +62 -33
  164. package/dist/esm/Canvas/utils/General/general functions.js.map +1 -1
  165. package/dist/esm/Canvas/utils/General/imageStitching.d.ts.map +1 -1
  166. package/dist/esm/Canvas/utils/General/imageStitching.js +3 -6
  167. package/dist/esm/Canvas/utils/General/imageStitching.js.map +1 -1
  168. package/dist/esm/Canvas/utils/Image/imageMasking.d.ts.map +1 -1
  169. package/dist/esm/Canvas/utils/Image/imageMasking.js +5 -12
  170. package/dist/esm/Canvas/utils/Image/imageMasking.js.map +1 -1
  171. package/dist/esm/Canvas/utils/Image/imageProperties.d.ts +4 -4
  172. package/dist/esm/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
  173. package/dist/esm/Canvas/utils/Image/imageProperties.js +44 -9
  174. package/dist/esm/Canvas/utils/Image/imageProperties.js.map +1 -1
  175. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts +5 -0
  176. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -1
  177. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js +48 -5
  178. package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -1
  179. package/dist/esm/Canvas/utils/Texts/textProperties.d.ts +1 -1
  180. package/dist/esm/Canvas/utils/Texts/textProperties.d.ts.map +1 -1
  181. package/dist/esm/Canvas/utils/Texts/textProperties.js +48 -5
  182. package/dist/esm/Canvas/utils/Texts/textProperties.js.map +1 -1
  183. package/dist/esm/Canvas/utils/Video/videoHelpers.d.ts +489 -0
  184. package/dist/esm/Canvas/utils/Video/videoHelpers.d.ts.map +1 -0
  185. package/dist/esm/Canvas/utils/Video/videoHelpers.js +1835 -0
  186. package/dist/esm/Canvas/utils/Video/videoHelpers.js.map +1 -0
  187. package/dist/esm/Canvas/utils/errorUtils.d.ts +15 -0
  188. package/dist/esm/Canvas/utils/errorUtils.d.ts.map +1 -0
  189. package/dist/esm/Canvas/utils/errorUtils.js +26 -0
  190. package/dist/esm/Canvas/utils/errorUtils.js.map +1 -0
  191. package/dist/esm/Canvas/utils/types.d.ts +17 -178
  192. package/dist/esm/Canvas/utils/types.d.ts.map +1 -1
  193. package/dist/esm/Canvas/utils/types.js.map +1 -1
  194. package/dist/esm/Canvas/utils/utils.d.ts +4 -3
  195. package/dist/esm/Canvas/utils/utils.d.ts.map +1 -1
  196. package/dist/esm/Canvas/utils/utils.js +40 -6
  197. package/dist/esm/Canvas/utils/utils.js.map +1 -1
  198. package/dist/esm/index.d.ts +1 -8
  199. package/dist/esm/index.d.ts.map +1 -1
  200. package/dist/esm/index.js +14 -45
  201. package/dist/esm/index.js.map +1 -1
  202. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  203. package/package.json +234 -198
  204. package/dist/cjs/Canvas/utils/Charts/charts.d.ts +0 -13
  205. package/dist/cjs/Canvas/utils/Charts/charts.d.ts.map +0 -1
  206. package/dist/cjs/Canvas/utils/Charts/charts.js +0 -466
  207. package/dist/cjs/Canvas/utils/Charts/charts.js.map +0 -1
  208. package/dist/esm/Canvas/utils/Charts/charts.d.ts +0 -13
  209. package/dist/esm/Canvas/utils/Charts/charts.d.ts.map +0 -1
  210. package/dist/esm/Canvas/utils/Charts/charts.js +0 -466
  211. package/dist/esm/Canvas/utils/Charts/charts.js.map +0 -1
  212. package/lib/Canvas/ApexPainter.ts +0 -5414
  213. package/lib/Canvas/utils/Background/bg.ts +0 -285
  214. package/lib/Canvas/utils/Charts/charts.ts +0 -548
  215. package/lib/Canvas/utils/Custom/advancedLines.ts +0 -387
  216. package/lib/Canvas/utils/Custom/customLines.ts +0 -206
  217. package/lib/Canvas/utils/General/batchOperations.ts +0 -103
  218. package/lib/Canvas/utils/General/conversion.ts +0 -34
  219. package/lib/Canvas/utils/General/general functions.ts +0 -726
  220. package/lib/Canvas/utils/General/imageCompression.ts +0 -316
  221. package/lib/Canvas/utils/General/imageStitching.ts +0 -252
  222. package/lib/Canvas/utils/Image/imageEffects.ts +0 -175
  223. package/lib/Canvas/utils/Image/imageFilters.ts +0 -356
  224. package/lib/Canvas/utils/Image/imageMasking.ts +0 -335
  225. package/lib/Canvas/utils/Image/imageProperties.ts +0 -587
  226. package/lib/Canvas/utils/Image/professionalImageFilters.ts +0 -391
  227. package/lib/Canvas/utils/Image/simpleProfessionalFilters.ts +0 -229
  228. package/lib/Canvas/utils/Patterns/enhancedPatternRenderer.ts +0 -455
  229. package/lib/Canvas/utils/Shapes/shapes.ts +0 -528
  230. package/lib/Canvas/utils/Texts/enhancedTextRenderer.ts +0 -716
  231. package/lib/Canvas/utils/Texts/textPathRenderer.ts +0 -320
  232. package/lib/Canvas/utils/Texts/textProperties.ts +0 -231
  233. package/lib/Canvas/utils/types.ts +0 -983
  234. package/lib/Canvas/utils/utils.ts +0 -135
  235. package/lib/index.ts +0 -81
  236. package/lib/utils.ts +0 -5
@@ -1,316 +0,0 @@
1
- import sharp from 'sharp';
2
- import path from 'path';
3
- import { CompressionOptions, PaletteOptions } from '../types';
4
-
5
- /**
6
- * Compresses an image with quality control
7
- * @param image - Image source (path, URL, or Buffer)
8
- * @param options - Compression options
9
- * @returns Compressed image buffer
10
- */
11
- export async function compressImage(
12
- image: string | Buffer,
13
- options: CompressionOptions = {}
14
- ): Promise<Buffer> {
15
- const {
16
- quality = 90,
17
- format = 'jpeg',
18
- maxWidth,
19
- maxHeight,
20
- progressive = false
21
- } = options;
22
-
23
- let sharpImage: sharp.Sharp;
24
-
25
- if (Buffer.isBuffer(image)) {
26
- sharpImage = sharp(image);
27
- } else if (typeof image === 'string' && image.startsWith('http')) {
28
- const response = await fetch(image);
29
- const buffer = await response.arrayBuffer();
30
- sharpImage = sharp(Buffer.from(buffer));
31
- } else {
32
- const imagePath = path.join(process.cwd(), image);
33
- sharpImage = sharp(imagePath);
34
- }
35
-
36
- // Resize if needed
37
- if (maxWidth || maxHeight) {
38
- sharpImage = sharpImage.resize(maxWidth, maxHeight, {
39
- fit: 'inside',
40
- withoutEnlargement: true
41
- });
42
- }
43
-
44
- // Convert and compress
45
- switch (format) {
46
- case 'jpeg':
47
- return await sharpImage
48
- .jpeg({ quality, progressive })
49
- .toBuffer();
50
-
51
- case 'webp':
52
- return await sharpImage
53
- .webp({ quality })
54
- .toBuffer();
55
-
56
- case 'avif':
57
- return await sharpImage
58
- .avif({ quality })
59
- .toBuffer();
60
-
61
- default:
62
- return await sharpImage
63
- .jpeg({ quality, progressive })
64
- .toBuffer();
65
- }
66
- }
67
-
68
- /**
69
- * Extracts color palette from an image
70
- * @param image - Image source (path, URL, or Buffer)
71
- * @param options - Palette extraction options
72
- * @returns Array of colors with percentages
73
- */
74
- export async function extractPalette(
75
- image: string | Buffer,
76
- options: PaletteOptions = {}
77
- ): Promise<Array<{ color: string; percentage: number }>> {
78
- const {
79
- count = 10,
80
- method = 'kmeans',
81
- format = 'hex'
82
- } = options;
83
-
84
- let sharpImage: sharp.Sharp;
85
-
86
- if (Buffer.isBuffer(image)) {
87
- sharpImage = sharp(image);
88
- } else if (typeof image === 'string' && image.startsWith('http')) {
89
- const response = await fetch(image);
90
- const buffer = await response.arrayBuffer();
91
- sharpImage = sharp(Buffer.from(buffer));
92
- } else {
93
- const imagePath = path.join(process.cwd(), image);
94
- sharpImage = sharp(imagePath);
95
- }
96
-
97
- // Resize for faster processing
98
- const { data, info } = await sharpImage
99
- .resize(200, 200, { fit: 'inside' })
100
- .raw()
101
- .toBuffer({ resolveWithObject: true });
102
-
103
- const pixels: Array<{ r: number; g: number; b: number }> = [];
104
- for (let i = 0; i < data.length; i += info.channels) {
105
- pixels.push({
106
- r: data[i],
107
- g: data[i + 1],
108
- b: data[i + 2]
109
- });
110
- }
111
-
112
- // Extract colors based on method
113
- let colors: Array<{ r: number; g: number; b: number; count: number }> = [];
114
-
115
- if (method === 'median-cut') {
116
- colors = medianCut(pixels, count);
117
- } else if (method === 'octree') {
118
- colors = octreeQuantization(pixels, count);
119
- } else {
120
- // kmeans (default)
121
- colors = kmeansClustering(pixels, count);
122
- }
123
-
124
- // Convert to requested format and calculate percentages
125
- const totalPixels = pixels.length;
126
- const palette = colors.map(color => {
127
- let colorString: string;
128
-
129
- if (format === 'hex') {
130
- colorString = `#${[color.r, color.g, color.b].map(c =>
131
- c.toString(16).padStart(2, '0')
132
- ).join('')}`;
133
- } else if (format === 'rgb') {
134
- colorString = `rgb(${color.r}, ${color.g}, ${color.b})`;
135
- } else {
136
- // hsl
137
- const hsl = rgbToHsl(color.r, color.g, color.b);
138
- colorString = `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`;
139
- }
140
-
141
- return {
142
- color: colorString,
143
- percentage: (color.count / totalPixels) * 100
144
- };
145
- });
146
-
147
- // Sort by percentage descending
148
- return palette.sort((a, b) => b.percentage - a.percentage);
149
- }
150
-
151
- /**
152
- * K-means clustering for color extraction
153
- */
154
- function kmeansClustering(
155
- pixels: Array<{ r: number; g: number; b: number }>,
156
- k: number
157
- ): Array<{ r: number; g: number; b: number; count: number }> {
158
- // Initialize centroids randomly
159
- const centroids: Array<{ r: number; g: number; b: number }> = [];
160
- for (let i = 0; i < k; i++) {
161
- const randomPixel = pixels[Math.floor(Math.random() * pixels.length)];
162
- centroids.push({ r: randomPixel.r, g: randomPixel.g, b: randomPixel.b });
163
- }
164
-
165
- // Iterate
166
- for (let iter = 0; iter < 10; iter++) {
167
- const clusters: Array<Array<{ r: number; g: number; b: number }>> =
168
- new Array(k).fill(null).map(() => []);
169
-
170
- // Assign pixels to nearest centroid
171
- for (const pixel of pixels) {
172
- let minDist = Infinity;
173
- let nearestCluster = 0;
174
-
175
- for (let i = 0; i < centroids.length; i++) {
176
- const dist = Math.sqrt(
177
- Math.pow(pixel.r - centroids[i].r, 2) +
178
- Math.pow(pixel.g - centroids[i].g, 2) +
179
- Math.pow(pixel.b - centroids[i].b, 2)
180
- );
181
- if (dist < minDist) {
182
- minDist = dist;
183
- nearestCluster = i;
184
- }
185
- }
186
- clusters[nearestCluster].push(pixel);
187
- }
188
-
189
- // Update centroids
190
- for (let i = 0; i < k; i++) {
191
- if (clusters[i].length > 0) {
192
- const avgR = clusters[i].reduce((sum, p) => sum + p.r, 0) / clusters[i].length;
193
- const avgG = clusters[i].reduce((sum, p) => sum + p.g, 0) / clusters[i].length;
194
- const avgB = clusters[i].reduce((sum, p) => sum + p.b, 0) / clusters[i].length;
195
- centroids[i] = { r: Math.round(avgR), g: Math.round(avgG), b: Math.round(avgB) };
196
- }
197
- }
198
- }
199
-
200
- // Count pixels in each cluster
201
- const counts: number[] = new Array(k).fill(0);
202
- for (const pixel of pixels) {
203
- let minDist = Infinity;
204
- let nearestCluster = 0;
205
-
206
- for (let i = 0; i < centroids.length; i++) {
207
- const dist = Math.sqrt(
208
- Math.pow(pixel.r - centroids[i].r, 2) +
209
- Math.pow(pixel.g - centroids[i].g, 2) +
210
- Math.pow(pixel.b - centroids[i].b, 2)
211
- );
212
- if (dist < minDist) {
213
- minDist = dist;
214
- nearestCluster = i;
215
- }
216
- }
217
- counts[nearestCluster]++;
218
- }
219
-
220
- return centroids.map((centroid, i) => ({
221
- ...centroid,
222
- count: counts[i]
223
- })).filter(c => c.count > 0);
224
- }
225
-
226
- /**
227
- * Median cut algorithm for color extraction
228
- */
229
- function medianCut(
230
- pixels: Array<{ r: number; g: number; b: number }>,
231
- count: number
232
- ): Array<{ r: number; g: number; b: number; count: number }> {
233
- // Simplified median cut - divide color space
234
- const buckets: Array<Array<{ r: number; g: number; b: number }>> = [pixels];
235
-
236
- while (buckets.length < count && buckets.length < 8) {
237
- const largestBucket = buckets.reduce((max, bucket, i) =>
238
- bucket.length > buckets[max].length ? i : max, 0
239
- );
240
-
241
- const bucket = buckets[largestBucket];
242
- if (bucket.length <= 1) break;
243
-
244
- // Find color channel with largest range
245
- const ranges = {
246
- r: Math.max(...bucket.map(p => p.r)) - Math.min(...bucket.map(p => p.r)),
247
- g: Math.max(...bucket.map(p => p.g)) - Math.min(...bucket.map(p => p.g)),
248
- b: Math.max(...bucket.map(p => p.b)) - Math.min(...bucket.map(p => p.b))
249
- };
250
-
251
- const channel = ranges.r > ranges.g && ranges.r > ranges.b ? 'r' :
252
- ranges.g > ranges.b ? 'g' : 'b';
253
-
254
- // Sort by channel and split at median
255
- bucket.sort((a, b) => a[channel] - b[channel]);
256
- const median = Math.floor(bucket.length / 2);
257
-
258
- buckets.splice(largestBucket, 1, bucket.slice(0, median), bucket.slice(median));
259
- }
260
-
261
- // Calculate average color for each bucket
262
- return buckets.map(bucket => {
263
- const avgR = Math.round(bucket.reduce((sum, p) => sum + p.r, 0) / bucket.length);
264
- const avgG = Math.round(bucket.reduce((sum, p) => sum + p.g, 0) / bucket.length);
265
- const avgB = Math.round(bucket.reduce((sum, p) => sum + p.b, 0) / bucket.length);
266
- return {
267
- r: avgR,
268
- g: avgG,
269
- b: avgB,
270
- count: bucket.length
271
- };
272
- });
273
- }
274
-
275
- /**
276
- * Octree quantization (simplified)
277
- */
278
- function octreeQuantization(
279
- pixels: Array<{ r: number; g: number; b: number }>,
280
- count: number
281
- ): Array<{ r: number; g: number; b: number; count: number }> {
282
- // Simplified octree - use kmeans as fallback
283
- return kmeansClustering(pixels, count);
284
- }
285
-
286
- /**
287
- * Converts RGB to HSL
288
- */
289
- function rgbToHsl(r: number, g: number, b: number): { h: number; s: number; l: number } {
290
- r /= 255;
291
- g /= 255;
292
- b /= 255;
293
-
294
- const max = Math.max(r, g, b);
295
- const min = Math.min(r, g, b);
296
- let h = 0, s = 0;
297
- const l = (max + min) / 2;
298
-
299
- if (max !== min) {
300
- const d = max - min;
301
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
302
-
303
- switch (max) {
304
- case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
305
- case g: h = ((b - r) / d + 2) / 6; break;
306
- case b: h = ((r - g) / d + 4) / 6; break;
307
- }
308
- }
309
-
310
- return {
311
- h: Math.round(h * 360),
312
- s: Math.round(s * 100),
313
- l: Math.round(l * 100)
314
- };
315
- }
316
-
@@ -1,252 +0,0 @@
1
- import { createCanvas, loadImage, SKRSContext2D, Image } from '@napi-rs/canvas';
2
- import path from 'path';
3
- import fs from 'fs';
4
- import { StitchOptions, CollageLayout } from '../types';
5
-
6
- /**
7
- * Stitches multiple images together
8
- * @param images - Array of image sources
9
- * @param options - Stitching options
10
- * @returns Stitched image buffer
11
- */
12
- export async function stitchImages(
13
- images: Array<string | Buffer>,
14
- options: StitchOptions = {}
15
- ): Promise<Buffer> {
16
- if (!images || images.length === 0) {
17
- throw new Error('stitchImages: images array is required');
18
- }
19
-
20
- const {
21
- direction = 'horizontal',
22
- overlap = 0,
23
- blend = false,
24
- spacing = 0
25
- } = options;
26
-
27
- // Load all images
28
- const loadedImages: Image[] = [];
29
- for (const imgSource of images) {
30
- let img: Image;
31
- if (Buffer.isBuffer(imgSource)) {
32
- img = await loadImage(imgSource);
33
- } else if (imgSource.startsWith('http')) {
34
- img = await loadImage(imgSource);
35
- } else {
36
- const imgPath = path.join(process.cwd(), imgSource);
37
- img = await loadImage(fs.readFileSync(imgPath));
38
- }
39
- loadedImages.push(img);
40
- }
41
-
42
- if (loadedImages.length === 0) {
43
- throw new Error('stitchImages: No valid images loaded');
44
- }
45
-
46
- // Calculate canvas dimensions
47
- let canvasWidth = 0;
48
- let canvasHeight = 0;
49
- let maxWidth = 0;
50
- let maxHeight = 0;
51
-
52
- for (const img of loadedImages) {
53
- maxWidth = Math.max(maxWidth, img.width);
54
- maxHeight = Math.max(maxHeight, img.height);
55
- }
56
-
57
- if (direction === 'horizontal') {
58
- canvasWidth = loadedImages.reduce((sum, img) => sum + img.width, 0);
59
- canvasWidth -= overlap * (loadedImages.length - 1);
60
- canvasWidth += spacing * (loadedImages.length - 1);
61
- canvasHeight = maxHeight;
62
- } else if (direction === 'vertical') {
63
- canvasWidth = maxWidth;
64
- canvasHeight = loadedImages.reduce((sum, img) => sum + img.height, 0);
65
- canvasHeight -= overlap * (loadedImages.length - 1);
66
- canvasHeight += spacing * (loadedImages.length - 1);
67
- } else if (direction === 'grid') {
68
- const cols = Math.ceil(Math.sqrt(loadedImages.length));
69
- const rows = Math.ceil(loadedImages.length / cols);
70
- canvasWidth = maxWidth * cols + spacing * (cols - 1);
71
- canvasHeight = maxHeight * rows + spacing * (rows - 1);
72
- }
73
-
74
- // Create canvas
75
- const canvas = createCanvas(canvasWidth, canvasHeight);
76
- const ctx = canvas.getContext('2d') as SKRSContext2D;
77
- if (!ctx) throw new Error("Unable to get 2D context");
78
-
79
- // Draw images
80
- let currentX = 0;
81
- let currentY = 0;
82
-
83
- for (let i = 0; i < loadedImages.length; i++) {
84
- const img = loadedImages[i];
85
-
86
- if (direction === 'horizontal') {
87
- if (i > 0) {
88
- currentX -= overlap;
89
- currentX += spacing;
90
- }
91
- ctx.drawImage(img, currentX, 0, img.width, img.height);
92
- currentX += img.width;
93
- } else if (direction === 'vertical') {
94
- if (i > 0) {
95
- currentY -= overlap;
96
- currentY += spacing;
97
- }
98
- ctx.drawImage(img, 0, currentY, img.width, img.height);
99
- currentY += img.height;
100
- } else if (direction === 'grid') {
101
- const cols = Math.ceil(Math.sqrt(loadedImages.length));
102
- const col = i % cols;
103
- const row = Math.floor(i / cols);
104
- const x = col * (maxWidth + spacing);
105
- const y = row * (maxHeight + spacing);
106
- ctx.drawImage(img, x, y, img.width, img.height);
107
- }
108
-
109
- // Apply blending if enabled and not first image
110
- if (blend && i > 0 && overlap > 0) {
111
- ctx.globalCompositeOperation = 'multiply';
112
- ctx.globalAlpha = 0.5;
113
- if (direction === 'horizontal') {
114
- ctx.drawImage(img, currentX - img.width - spacing + overlap, 0, img.width, img.height);
115
- } else if (direction === 'vertical') {
116
- ctx.drawImage(img, 0, currentY - img.height - spacing + overlap, img.width, img.height);
117
- }
118
- ctx.globalAlpha = 1;
119
- ctx.globalCompositeOperation = 'source-over';
120
- }
121
- }
122
-
123
- return canvas.toBuffer('image/png');
124
- }
125
-
126
- /**
127
- * Creates an image collage
128
- * @param images - Array of image sources with optional dimensions
129
- * @param layout - Collage layout configuration
130
- * @returns Collage image buffer
131
- */
132
- export async function createCollage(
133
- images: Array<{ source: string | Buffer; width?: number; height?: number }>,
134
- layout: CollageLayout
135
- ): Promise<Buffer> {
136
- if (!images || images.length === 0) {
137
- throw new Error('createCollage: images array is required');
138
- }
139
-
140
- const {
141
- type = 'grid',
142
- columns = 3,
143
- rows = 3,
144
- spacing = 10,
145
- background = '#ffffff',
146
- borderRadius = 0
147
- } = layout;
148
-
149
- // Load all images
150
- const loadedImages: Array<{ image: Image; width: number; height: number }> = [];
151
- for (const imgConfig of images) {
152
- let img: Image;
153
- if (Buffer.isBuffer(imgConfig.source)) {
154
- img = await loadImage(imgConfig.source);
155
- } else if (typeof imgConfig.source === 'string' && imgConfig.source.startsWith('http')) {
156
- img = await loadImage(imgConfig.source);
157
- } else {
158
- const imgPath = path.join(process.cwd(), imgConfig.source as string);
159
- img = await loadImage(fs.readFileSync(imgPath));
160
- }
161
-
162
- loadedImages.push({
163
- image: img,
164
- width: imgConfig.width || img.width,
165
- height: imgConfig.height || img.height
166
- });
167
- }
168
-
169
- // Calculate canvas dimensions
170
- let canvasWidth = 0;
171
- let canvasHeight = 0;
172
-
173
- if (type === 'grid') {
174
- const cellWidth = Math.max(...loadedImages.map(img => img.width));
175
- const cellHeight = Math.max(...loadedImages.map(img => img.height));
176
- canvasWidth = cellWidth * columns + spacing * (columns - 1);
177
- canvasHeight = cellHeight * rows + spacing * (rows - 1);
178
- } else if (type === 'masonry') {
179
- // Masonry layout - columns with varying heights
180
- const colWidths: number[] = new Array(columns).fill(0);
181
- const colHeights: number[] = new Array(columns).fill(0);
182
-
183
- for (let i = 0; i < loadedImages.length; i++) {
184
- const col = i % columns;
185
- colWidths[col] = Math.max(colWidths[col], loadedImages[i].width);
186
- colHeights[col] += loadedImages[i].height + (i >= columns ? spacing : 0);
187
- }
188
-
189
- canvasWidth = Math.max(...colWidths) * columns + spacing * (columns - 1);
190
- canvasHeight = Math.max(...colHeights);
191
- } else if (type === 'carousel') {
192
- // Horizontal carousel
193
- canvasWidth = loadedImages.reduce((sum, img) => sum + img.width, 0) + spacing * (loadedImages.length - 1);
194
- canvasHeight = Math.max(...loadedImages.map(img => img.height));
195
- } else {
196
- // Custom - use provided dimensions or calculate
197
- canvasWidth = 800;
198
- canvasHeight = 600;
199
- }
200
-
201
- // Create canvas
202
- const canvas = createCanvas(canvasWidth, canvasHeight);
203
- const ctx = canvas.getContext('2d') as SKRSContext2D;
204
- if (!ctx) throw new Error("Unable to get 2D context");
205
-
206
- // Draw background
207
- ctx.fillStyle = background;
208
- ctx.fillRect(0, 0, canvasWidth, canvasHeight);
209
-
210
- // Draw images
211
- let currentX = 0;
212
- let currentY = 0;
213
- const colHeights: number[] = new Array(columns).fill(0);
214
-
215
- for (let i = 0; i < loadedImages.length; i++) {
216
- const imgData = loadedImages[i];
217
-
218
- if (type === 'grid') {
219
- const col = i % columns;
220
- const row = Math.floor(i / columns);
221
- const cellWidth = Math.max(...loadedImages.map(img => img.width));
222
- const cellHeight = Math.max(...loadedImages.map(img => img.height));
223
- currentX = col * (cellWidth + spacing);
224
- currentY = row * (cellHeight + spacing);
225
- } else if (type === 'masonry') {
226
- const col = i % columns;
227
- currentX = col * (Math.max(...loadedImages.map(img => img.width)) + spacing);
228
- currentY = colHeights[col];
229
- colHeights[col] += imgData.height + spacing;
230
- } else if (type === 'carousel') {
231
- if (i > 0) currentX += spacing;
232
- currentY = (canvasHeight - imgData.height) / 2;
233
- }
234
-
235
- // Apply border radius if specified
236
- if (borderRadius > 0) {
237
- ctx.save();
238
- ctx.beginPath();
239
- ctx.roundRect(currentX, currentY, imgData.width, imgData.height, borderRadius);
240
- ctx.clip();
241
- }
242
-
243
- ctx.drawImage(imgData.image, currentX, currentY, imgData.width, imgData.height);
244
-
245
- if (borderRadius > 0) {
246
- ctx.restore();
247
- }
248
- }
249
-
250
- return canvas.toBuffer('image/png');
251
- }
252
-