vuedit-image-editor 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 +21 -0
- package/dist/index.d.ts +663 -0
- package/dist/vuedit-image-editor.css +1 -0
- package/dist/vuedit-image-editor.es.js +3412 -0
- package/dist/vuedit-image-editor.es.js.map +1 -0
- package/dist/vuedit-image-editor.umd.js +36 -0
- package/dist/vuedit-image-editor.umd.js.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Mahjoz
|
|
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/dist/index.d.ts
ADDED
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
import { App } from 'vue';
|
|
2
|
+
import { Component } from 'vue';
|
|
3
|
+
import { ComponentOptionsMixin } from 'vue';
|
|
4
|
+
import { ComponentProvideOptions } from 'vue';
|
|
5
|
+
import { DeepReadonly } from 'vue';
|
|
6
|
+
import { DefineComponent } from 'vue';
|
|
7
|
+
import { ExtractPropTypes } from 'vue';
|
|
8
|
+
import { InjectionKey } from 'vue';
|
|
9
|
+
import { PropType } from 'vue';
|
|
10
|
+
import { PublicProps } from 'vue';
|
|
11
|
+
import { Ref } from 'vue';
|
|
12
|
+
|
|
13
|
+
declare type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
|
14
|
+
|
|
15
|
+
declare type __VLS_NonUndefinedable_2<T> = T extends undefined ? never : T;
|
|
16
|
+
|
|
17
|
+
declare type __VLS_Prettify<T> = {
|
|
18
|
+
[K in keyof T]: T[K];
|
|
19
|
+
} & {};
|
|
20
|
+
|
|
21
|
+
declare type __VLS_TypePropsToRuntimeProps<T> = {
|
|
22
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
|
23
|
+
type: PropType<__VLS_NonUndefinedable<T[K]>>;
|
|
24
|
+
} : {
|
|
25
|
+
type: PropType<T[K]>;
|
|
26
|
+
required: true;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
declare type __VLS_TypePropsToRuntimeProps_2<T> = {
|
|
31
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
|
32
|
+
type: PropType<__VLS_NonUndefinedable_2<T[K]>>;
|
|
33
|
+
} : {
|
|
34
|
+
type: PropType<T[K]>;
|
|
35
|
+
required: true;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
declare type __VLS_WithDefaults<P, D> = {
|
|
40
|
+
[K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
|
|
41
|
+
default: D[K];
|
|
42
|
+
}> : P[K];
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Apply clarity (local contrast / unsharp mask) to ImageData in-place.
|
|
47
|
+
* strength: -0.25 to 0.25, base 0. Positive sharpens, negative softens.
|
|
48
|
+
* Uses a 3x3 Laplacian kernel blended with the original.
|
|
49
|
+
*/
|
|
50
|
+
export declare function applyClarity(imageData: ImageData, strength: number): void;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Apply a 5x4 color matrix to ImageData in-place.
|
|
54
|
+
* Offsets (m4, m9, m14, m19) are in 0-1 range and scaled to 0-255 internally.
|
|
55
|
+
*/
|
|
56
|
+
export declare function applyColorMatrix(imageData: ImageData, matrix: number[]): void;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Apply gamma correction to ImageData in-place.
|
|
60
|
+
* gamma: 0.2 to 5.0, base 1.0 (1 = no change)
|
|
61
|
+
*/
|
|
62
|
+
export declare function applyGamma(imageData: ImageData, gamma: number): void;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Apply vignette effect to ImageData in-place.
|
|
66
|
+
* strength: -1 to 1 (negative = lighten edges, positive = darken edges)
|
|
67
|
+
*/
|
|
68
|
+
export declare function applyVignette(imageData: ImageData, strength: number, width: number, height: number): void;
|
|
69
|
+
|
|
70
|
+
export declare const ar: LocaleStrings;
|
|
71
|
+
|
|
72
|
+
/** Brightness adjustment matrix. v: -0.25 to 0.25 */
|
|
73
|
+
export declare function brightnessMatrix(v: number): number[];
|
|
74
|
+
|
|
75
|
+
export declare class CanvasRenderer {
|
|
76
|
+
private canvas;
|
|
77
|
+
private ctx;
|
|
78
|
+
private sourceImage;
|
|
79
|
+
private animFrameId;
|
|
80
|
+
private needsRender;
|
|
81
|
+
/** Viewport transform */
|
|
82
|
+
viewport: ViewportTransform;
|
|
83
|
+
/** Active plugin ID — used to determine whether to show cropped preview */
|
|
84
|
+
activePluginId: string | null;
|
|
85
|
+
/**
|
|
86
|
+
* The full image display rect in CSS pixels.
|
|
87
|
+
* Used by the crop overlay to position handles on top of the image.
|
|
88
|
+
*/
|
|
89
|
+
private fullImageRect;
|
|
90
|
+
/** Cached offscreen canvas for color-adjusted preview */
|
|
91
|
+
private previewCanvas;
|
|
92
|
+
private previewCtx;
|
|
93
|
+
private previewCacheKey;
|
|
94
|
+
/** Max preview dimension for color processing performance */
|
|
95
|
+
private readonly previewMaxSize;
|
|
96
|
+
/** Cache for image-based sticker elements */
|
|
97
|
+
private stickerImageCache;
|
|
98
|
+
constructor(canvas: HTMLCanvasElement);
|
|
99
|
+
setSource(image: HTMLImageElement | null): void;
|
|
100
|
+
/** Resize canvas to match container (handles DPR) */
|
|
101
|
+
resize(width: number, height: number): void;
|
|
102
|
+
/** Request a render on the next animation frame */
|
|
103
|
+
requestRender(): void;
|
|
104
|
+
/** Callback called after each render with context for plugin drawing */
|
|
105
|
+
afterRender: ((ctx: CanvasRenderingContext2D, state: ImageState, imageRect: {
|
|
106
|
+
x: number;
|
|
107
|
+
y: number;
|
|
108
|
+
width: number;
|
|
109
|
+
height: number;
|
|
110
|
+
}) => void) | null;
|
|
111
|
+
/** Cached getState function for render loop */
|
|
112
|
+
private getState;
|
|
113
|
+
/** Start the render loop */
|
|
114
|
+
startRenderLoop(getState: () => ImageState): void;
|
|
115
|
+
/** Schedule a single render frame (only when needed) */
|
|
116
|
+
private scheduleRender;
|
|
117
|
+
/** Stop the render loop */
|
|
118
|
+
stopRenderLoop(): void;
|
|
119
|
+
/**
|
|
120
|
+
* Build a cache key from the finetune + filter state.
|
|
121
|
+
* Only regenerates the preview canvas when these values change.
|
|
122
|
+
*/
|
|
123
|
+
private buildEffectsCacheKey;
|
|
124
|
+
/**
|
|
125
|
+
* Check if any color effects are active.
|
|
126
|
+
*/
|
|
127
|
+
private hasColorEffects;
|
|
128
|
+
/**
|
|
129
|
+
* Get a color-adjusted preview image.
|
|
130
|
+
* Returns the source image if no effects are active,
|
|
131
|
+
* otherwise returns a cached offscreen canvas with effects applied.
|
|
132
|
+
*/
|
|
133
|
+
private getPreviewSource;
|
|
134
|
+
/** Check if crop is not at full-image defaults */
|
|
135
|
+
private isCropActive;
|
|
136
|
+
/**
|
|
137
|
+
* Main render method.
|
|
138
|
+
* Draws the image with color adjustments fitted to the canvas.
|
|
139
|
+
* On crop tab: renders full image (CropOverlay handles crop visualization).
|
|
140
|
+
* On other tabs: renders only the cropped region fitted to canvas.
|
|
141
|
+
*/
|
|
142
|
+
render(state: ImageState): void;
|
|
143
|
+
/**
|
|
144
|
+
* Render full image view (used on the crop tab).
|
|
145
|
+
*/
|
|
146
|
+
private renderFullView;
|
|
147
|
+
/**
|
|
148
|
+
* Render cropped view (used on non-crop tabs).
|
|
149
|
+
* Shows only the crop region fitted to the canvas.
|
|
150
|
+
*/
|
|
151
|
+
private renderCroppedView;
|
|
152
|
+
/**
|
|
153
|
+
* Render frame preview overlay on the canvas.
|
|
154
|
+
*/
|
|
155
|
+
private renderFramePreview;
|
|
156
|
+
/**
|
|
157
|
+
* Get the full image display rect in CSS pixels.
|
|
158
|
+
* The CropOverlay uses this to position crop handles correctly.
|
|
159
|
+
*/
|
|
160
|
+
getImageRect(): {
|
|
161
|
+
x: number;
|
|
162
|
+
y: number;
|
|
163
|
+
width: number;
|
|
164
|
+
height: number;
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* Render stickers on the canvas viewport.
|
|
168
|
+
*/
|
|
169
|
+
private renderStickers;
|
|
170
|
+
/**
|
|
171
|
+
* Render stickers with positions remapped relative to the crop region.
|
|
172
|
+
*/
|
|
173
|
+
private renderStickersInCrop;
|
|
174
|
+
destroy(): void;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Compose multiple matrices into one (left to right application order) */
|
|
178
|
+
export declare function composeMatrices(...matrices: number[][]): number[];
|
|
179
|
+
|
|
180
|
+
/** Contrast adjustment matrix. v: -0.25 to 0.25 */
|
|
181
|
+
export declare function contrastMatrix(v: number): number[];
|
|
182
|
+
|
|
183
|
+
export declare function createDefaultImageState(): ImageState;
|
|
184
|
+
|
|
185
|
+
export declare function createEditorEngine(options: EditorOptions): EditorEngine;
|
|
186
|
+
|
|
187
|
+
export declare function CropPlugin(): EditorPlugin;
|
|
188
|
+
|
|
189
|
+
export declare interface CropState {
|
|
190
|
+
/** Normalized 0-1 X position of crop region */
|
|
191
|
+
x: number;
|
|
192
|
+
/** Normalized 0-1 Y position of crop region */
|
|
193
|
+
y: number;
|
|
194
|
+
/** Normalized 0-1 width of crop region */
|
|
195
|
+
width: number;
|
|
196
|
+
/** Normalized 0-1 height of crop region */
|
|
197
|
+
height: number;
|
|
198
|
+
/** Locked aspect ratio (width/height), null = free */
|
|
199
|
+
aspectRatio: number | null;
|
|
200
|
+
/** Rotation in radians, -PI/4 to PI/4 for free rotation */
|
|
201
|
+
rotation: number;
|
|
202
|
+
/** Flip horizontally */
|
|
203
|
+
flipX: boolean;
|
|
204
|
+
/** Flip vertically */
|
|
205
|
+
flipY: boolean;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
declare const _default: {
|
|
209
|
+
install: typeof install;
|
|
210
|
+
};
|
|
211
|
+
export default _default;
|
|
212
|
+
|
|
213
|
+
export declare const defaultStickerCategories: StickerCategory[];
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Deserialize a JSON string back to an ImageState.
|
|
217
|
+
* Validates the basic structure before returning.
|
|
218
|
+
*/
|
|
219
|
+
export declare function deserializeState(json: string): Partial<ImageState>;
|
|
220
|
+
|
|
221
|
+
export declare interface EditorEngine {
|
|
222
|
+
/** Reactive editor state */
|
|
223
|
+
state: ImageState;
|
|
224
|
+
/** Read-only reactive state for consumers */
|
|
225
|
+
readonlyState: DeepReadonly<ImageState>;
|
|
226
|
+
/** Source image element */
|
|
227
|
+
sourceImage: Ref<HTMLImageElement | null>;
|
|
228
|
+
/** Whether the source image is loading */
|
|
229
|
+
loading: Ref<boolean>;
|
|
230
|
+
/** Error message if loading fails */
|
|
231
|
+
error: Ref<string | null>;
|
|
232
|
+
/** Registered plugins */
|
|
233
|
+
plugins: Ref<EditorPlugin[]>;
|
|
234
|
+
/** Currently active plugin ID */
|
|
235
|
+
activePluginId: Ref<string | null>;
|
|
236
|
+
/** Currently active plugin */
|
|
237
|
+
activePlugin: Ref<EditorPlugin | null>;
|
|
238
|
+
/** Whether any edits have been made */
|
|
239
|
+
hasEdits: Ref<boolean>;
|
|
240
|
+
/** History */
|
|
241
|
+
canUndo: Ref<boolean>;
|
|
242
|
+
canRedo: Ref<boolean>;
|
|
243
|
+
/** Zoom level (1 = fit to container) */
|
|
244
|
+
zoom: Ref<number>;
|
|
245
|
+
/** Editor options */
|
|
246
|
+
options: EditorOptions;
|
|
247
|
+
/** Load the source image */
|
|
248
|
+
load: (src: string | File | Blob) => Promise<void>;
|
|
249
|
+
/** Register a plugin */
|
|
250
|
+
registerPlugin: (plugin: EditorPlugin) => void;
|
|
251
|
+
/** Unregister a plugin by ID */
|
|
252
|
+
unregisterPlugin: (id: string) => void;
|
|
253
|
+
/** Set active plugin by ID */
|
|
254
|
+
setActivePlugin: (id: string) => void;
|
|
255
|
+
/** Update state and push to history */
|
|
256
|
+
updateState: (updater: (state: ImageState) => void) => void;
|
|
257
|
+
/** Undo last change */
|
|
258
|
+
undo: () => void;
|
|
259
|
+
/** Redo last undone change */
|
|
260
|
+
redo: () => void;
|
|
261
|
+
/** Revert to initial state */
|
|
262
|
+
revert: () => void;
|
|
263
|
+
/** Set zoom level */
|
|
264
|
+
setZoom: (level: number) => void;
|
|
265
|
+
/** Request a re-render of the canvas */
|
|
266
|
+
requestRender: () => void;
|
|
267
|
+
/** Render callback — set by EditorCanvas */
|
|
268
|
+
onRender: Ref<(() => void) | null>;
|
|
269
|
+
/** Temporary viewport pan during crop drag (pixels) */
|
|
270
|
+
cropDragPan: Ref<{
|
|
271
|
+
x: number;
|
|
272
|
+
y: number;
|
|
273
|
+
}>;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export declare interface EditorOptions {
|
|
277
|
+
/** Image source: URL, File, or Blob */
|
|
278
|
+
src: string | File | Blob;
|
|
279
|
+
/** List of plugin IDs to enable (e.g., ['crop', 'filter', 'finetune']) */
|
|
280
|
+
plugins?: string[];
|
|
281
|
+
/** Locale code */
|
|
282
|
+
locale?: 'en' | 'ar';
|
|
283
|
+
/** Text direction */
|
|
284
|
+
dir?: 'ltr' | 'rtl';
|
|
285
|
+
/** Theme: 'light' (default) or 'dark' */
|
|
286
|
+
theme?: 'dark' | 'light';
|
|
287
|
+
/** Output format */
|
|
288
|
+
outputMimeType?: 'image/jpeg' | 'image/png' | 'image/webp';
|
|
289
|
+
/** Output quality (0-1), for JPEG/WebP */
|
|
290
|
+
outputQuality?: number;
|
|
291
|
+
/** Max canvas pixels for export (iOS limit ~16M) */
|
|
292
|
+
maxCanvasPixels?: number;
|
|
293
|
+
/** Initial image state (for re-editing) */
|
|
294
|
+
initialState?: Partial<ImageState>;
|
|
295
|
+
/** Custom plugins to register in addition to built-in plugins */
|
|
296
|
+
customPlugins?: EditorPlugin[];
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export declare interface EditorPlugin {
|
|
300
|
+
/** Unique plugin ID (e.g., 'crop', 'filter') */
|
|
301
|
+
id: string;
|
|
302
|
+
/** SVG icon as HTML string or component */
|
|
303
|
+
icon: string | Component;
|
|
304
|
+
/** Display label key (used for locale lookup) */
|
|
305
|
+
labelKey: string;
|
|
306
|
+
/** Controls component rendered in the control panel */
|
|
307
|
+
controls: Component;
|
|
308
|
+
/** Overlay component rendered on top of the canvas viewport */
|
|
309
|
+
overlay?: Component;
|
|
310
|
+
/** Called when the plugin tab is activated */
|
|
311
|
+
onActivate?: () => void;
|
|
312
|
+
/** Called when the plugin tab is deactivated */
|
|
313
|
+
onDeactivate?: () => void;
|
|
314
|
+
/** Called after the base canvas render to draw plugin-specific preview content */
|
|
315
|
+
onRender?: (context: PluginRenderContext) => void;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export declare const en: {
|
|
319
|
+
undo: string;
|
|
320
|
+
redo: string;
|
|
321
|
+
revert: string;
|
|
322
|
+
zoomIn: string;
|
|
323
|
+
zoomOut: string;
|
|
324
|
+
zoomToFit: string;
|
|
325
|
+
done: string;
|
|
326
|
+
cancel: string;
|
|
327
|
+
export: string;
|
|
328
|
+
close: string;
|
|
329
|
+
crop: string;
|
|
330
|
+
filter: string;
|
|
331
|
+
finetune: string;
|
|
332
|
+
sticker: string;
|
|
333
|
+
frame: string;
|
|
334
|
+
resize: string;
|
|
335
|
+
aspectRatio: string;
|
|
336
|
+
custom: string;
|
|
337
|
+
square: string;
|
|
338
|
+
landscape: string;
|
|
339
|
+
portrait: string;
|
|
340
|
+
rotation: string;
|
|
341
|
+
rotateLeft: string;
|
|
342
|
+
rotateRight: string;
|
|
343
|
+
flipHorizontal: string;
|
|
344
|
+
flipVertical: string;
|
|
345
|
+
brightness: string;
|
|
346
|
+
contrast: string;
|
|
347
|
+
saturation: string;
|
|
348
|
+
exposure: string;
|
|
349
|
+
temperature: string;
|
|
350
|
+
gamma: string;
|
|
351
|
+
clarity: string;
|
|
352
|
+
vignette: string;
|
|
353
|
+
original: string;
|
|
354
|
+
intensity: string;
|
|
355
|
+
chrome: string;
|
|
356
|
+
fade: string;
|
|
357
|
+
pastel: string;
|
|
358
|
+
cold: string;
|
|
359
|
+
warm: string;
|
|
360
|
+
mono: string;
|
|
361
|
+
noir: string;
|
|
362
|
+
wash: string;
|
|
363
|
+
stark: string;
|
|
364
|
+
sepia: string;
|
|
365
|
+
rust: string;
|
|
366
|
+
blues: string;
|
|
367
|
+
color: string;
|
|
368
|
+
solidSharp: string;
|
|
369
|
+
solidRound: string;
|
|
370
|
+
lineSingle: string;
|
|
371
|
+
lineMultiple: string;
|
|
372
|
+
hook: string;
|
|
373
|
+
polaroid: string;
|
|
374
|
+
edgeSeparate: string;
|
|
375
|
+
edgeCross: string;
|
|
376
|
+
edgeOverlap: string;
|
|
377
|
+
fill: string;
|
|
378
|
+
transparent: string;
|
|
379
|
+
emoji: string;
|
|
380
|
+
shapes: string;
|
|
381
|
+
none: string;
|
|
382
|
+
frameSize: string;
|
|
383
|
+
frameColor: string;
|
|
384
|
+
width: string;
|
|
385
|
+
height: string;
|
|
386
|
+
lockAspectRatio: string;
|
|
387
|
+
loading: string;
|
|
388
|
+
loadError: string;
|
|
389
|
+
processing: string;
|
|
390
|
+
cropApply: string;
|
|
391
|
+
unsavedChanges: string;
|
|
392
|
+
confirm: string;
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
/** Exposure adjustment matrix. v: -0.25 to 0.25 */
|
|
396
|
+
export declare function exposureMatrix(v: number): number[];
|
|
397
|
+
|
|
398
|
+
export declare function FillPlugin(): EditorPlugin;
|
|
399
|
+
|
|
400
|
+
export declare function FilterPlugin(): EditorPlugin;
|
|
401
|
+
|
|
402
|
+
declare interface FilterPreset {
|
|
403
|
+
id: string;
|
|
404
|
+
labelKey: string;
|
|
405
|
+
matrix: number[];
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
export declare const filterPresets: FilterPreset[];
|
|
409
|
+
|
|
410
|
+
export declare interface FilterState {
|
|
411
|
+
/** Filter preset ID, null = no filter */
|
|
412
|
+
id: string | null;
|
|
413
|
+
/** Filter intensity 0 to 1 */
|
|
414
|
+
intensity: number;
|
|
415
|
+
/** Optional 5x4 color matrix (20 elements) */
|
|
416
|
+
matrix?: number[];
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
declare interface FinetuneEffect {
|
|
420
|
+
key: keyof FinetuneState;
|
|
421
|
+
labelKey: keyof LocaleStrings;
|
|
422
|
+
min: number;
|
|
423
|
+
max: number;
|
|
424
|
+
base: number;
|
|
425
|
+
step: number;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
export declare const finetuneEffects: FinetuneEffect[];
|
|
429
|
+
|
|
430
|
+
export declare function FinetunePlugin(): EditorPlugin;
|
|
431
|
+
|
|
432
|
+
export declare interface FinetuneState {
|
|
433
|
+
brightness: number;
|
|
434
|
+
contrast: number;
|
|
435
|
+
saturation: number;
|
|
436
|
+
exposure: number;
|
|
437
|
+
temperature: number;
|
|
438
|
+
gamma: number;
|
|
439
|
+
clarity: number;
|
|
440
|
+
vignette: number;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export declare function FramePlugin(): EditorPlugin;
|
|
444
|
+
|
|
445
|
+
export declare interface FrameState {
|
|
446
|
+
/** Frame style ID, null = no frame */
|
|
447
|
+
style: string | null;
|
|
448
|
+
/** Frame thickness as percentage of image size */
|
|
449
|
+
size: number;
|
|
450
|
+
/** RGBA color, each 0-1 */
|
|
451
|
+
color: [number, number, number, number];
|
|
452
|
+
/** Corner radius */
|
|
453
|
+
radius: number;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
declare interface FrameStyleDef {
|
|
457
|
+
id: string;
|
|
458
|
+
labelKey: keyof LocaleStrings;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
export declare const frameStyles: FrameStyleDef[];
|
|
462
|
+
|
|
463
|
+
declare class History_2 {
|
|
464
|
+
private states;
|
|
465
|
+
private pointer;
|
|
466
|
+
private maxSize;
|
|
467
|
+
constructor(maxSize?: number);
|
|
468
|
+
/** Push a new state snapshot. Truncates any future (redo) states. */
|
|
469
|
+
push(state: ImageState): void;
|
|
470
|
+
/** Undo: return the previous state, or null if at the beginning. */
|
|
471
|
+
undo(): ImageState | null;
|
|
472
|
+
/** Redo: return the next state, or null if at the end. */
|
|
473
|
+
redo(): ImageState | null;
|
|
474
|
+
/** Reset history with a single initial state. */
|
|
475
|
+
reset(state: ImageState): void;
|
|
476
|
+
get canUndo(): boolean;
|
|
477
|
+
get canRedo(): boolean;
|
|
478
|
+
get currentIndex(): number;
|
|
479
|
+
get length(): number;
|
|
480
|
+
}
|
|
481
|
+
export { History_2 as History }
|
|
482
|
+
|
|
483
|
+
/** Identity matrix — no transformation */
|
|
484
|
+
export declare const IDENTITY_MATRIX: number[];
|
|
485
|
+
|
|
486
|
+
export declare const ImageEditorModal: DefineComponent<ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
|
|
487
|
+
src: string | File | Blob;
|
|
488
|
+
plugins?: string[];
|
|
489
|
+
locale?: "en" | "ar";
|
|
490
|
+
dir?: "ltr" | "rtl";
|
|
491
|
+
theme?: "dark" | "light";
|
|
492
|
+
outputMimeType?: "image/jpeg" | "image/png" | "image/webp";
|
|
493
|
+
outputQuality?: number;
|
|
494
|
+
maxCanvasPixels?: number;
|
|
495
|
+
initialState?: Partial<ImageState>;
|
|
496
|
+
}>, {
|
|
497
|
+
plugins: () => string[];
|
|
498
|
+
locale: string;
|
|
499
|
+
dir: string;
|
|
500
|
+
theme: string;
|
|
501
|
+
outputQuality: number;
|
|
502
|
+
}>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
|
|
503
|
+
close: () => void;
|
|
504
|
+
process: (result: ProcessResult) => void;
|
|
505
|
+
}, string, PublicProps, Readonly<ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
|
|
506
|
+
src: string | File | Blob;
|
|
507
|
+
plugins?: string[];
|
|
508
|
+
locale?: "en" | "ar";
|
|
509
|
+
dir?: "ltr" | "rtl";
|
|
510
|
+
theme?: "dark" | "light";
|
|
511
|
+
outputMimeType?: "image/jpeg" | "image/png" | "image/webp";
|
|
512
|
+
outputQuality?: number;
|
|
513
|
+
maxCanvasPixels?: number;
|
|
514
|
+
initialState?: Partial<ImageState>;
|
|
515
|
+
}>, {
|
|
516
|
+
plugins: () => string[];
|
|
517
|
+
locale: string;
|
|
518
|
+
dir: string;
|
|
519
|
+
theme: string;
|
|
520
|
+
outputQuality: number;
|
|
521
|
+
}>>> & Readonly<{
|
|
522
|
+
onClose?: (() => any) | undefined;
|
|
523
|
+
onProcess?: ((result: ProcessResult) => any) | undefined;
|
|
524
|
+
}>, {
|
|
525
|
+
dir: "ltr" | "rtl";
|
|
526
|
+
plugins: string[];
|
|
527
|
+
locale: "en" | "ar";
|
|
528
|
+
theme: "dark" | "light";
|
|
529
|
+
outputQuality: number;
|
|
530
|
+
}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
|
|
531
|
+
|
|
532
|
+
export declare const ImageEditorShell: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_2<{
|
|
533
|
+
options: EditorOptions;
|
|
534
|
+
}>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
|
|
535
|
+
close: () => void;
|
|
536
|
+
process: (result: ProcessResult) => void;
|
|
537
|
+
}, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_2<{
|
|
538
|
+
options: EditorOptions;
|
|
539
|
+
}>>> & Readonly<{
|
|
540
|
+
onClose?: (() => any) | undefined;
|
|
541
|
+
onProcess?: ((result: ProcessResult) => any) | undefined;
|
|
542
|
+
}>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
|
|
543
|
+
|
|
544
|
+
export declare class ImageProcessor {
|
|
545
|
+
/**
|
|
546
|
+
* Process image at FULL RESOLUTION.
|
|
547
|
+
* Applies all transformations and exports as Blob.
|
|
548
|
+
*/
|
|
549
|
+
process(source: HTMLImageElement, state: ImageState, options?: ProcessOptions): Promise<ProcessResult>;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
export declare interface ImageState {
|
|
553
|
+
crop: CropState;
|
|
554
|
+
finetune: FinetuneState;
|
|
555
|
+
filter: FilterState;
|
|
556
|
+
stickers: StickerInstance[];
|
|
557
|
+
frame: FrameState;
|
|
558
|
+
resize: ResizeState;
|
|
559
|
+
backgroundColor: [number, number, number, number];
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
export declare function install(app: App): void;
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Load images from various sources into an HTMLImageElement.
|
|
566
|
+
* Handles URL strings, File objects, Blobs, and EXIF orientation.
|
|
567
|
+
*/
|
|
568
|
+
export declare function loadImage(src: string | File | Blob): Promise<HTMLImageElement>;
|
|
569
|
+
|
|
570
|
+
export declare const LOCALE_KEY: InjectionKey<(key: string) => string>;
|
|
571
|
+
|
|
572
|
+
export declare type LocaleStrings = typeof en;
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Create a full ImageState from a partial state, filling in defaults.
|
|
576
|
+
*/
|
|
577
|
+
export declare function mergeWithDefaults(partial: Partial<ImageState>): ImageState;
|
|
578
|
+
|
|
579
|
+
/** Multiply two 5x4 matrices (treating them as 5x5 with implicit last row [0,0,0,0,1]) */
|
|
580
|
+
export declare function multiplyMatrices(a: number[], b: number[]): number[];
|
|
581
|
+
|
|
582
|
+
export declare interface PluginRenderContext {
|
|
583
|
+
/** Canvas 2D rendering context */
|
|
584
|
+
ctx: CanvasRenderingContext2D;
|
|
585
|
+
/** Current editor state */
|
|
586
|
+
state: ImageState;
|
|
587
|
+
/** Image display rect in canvas pixels */
|
|
588
|
+
imageRect: {
|
|
589
|
+
x: number;
|
|
590
|
+
y: number;
|
|
591
|
+
width: number;
|
|
592
|
+
height: number;
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
declare interface ProcessOptions {
|
|
597
|
+
mimeType?: string;
|
|
598
|
+
quality?: number;
|
|
599
|
+
maxCanvasPixels?: number;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
export declare interface ProcessResult {
|
|
603
|
+
/** The processed image as a Blob */
|
|
604
|
+
blob: Blob;
|
|
605
|
+
/** The final image state (serializable for persistence) */
|
|
606
|
+
imageState: ImageState;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
export declare function ResizePlugin(): EditorPlugin;
|
|
610
|
+
|
|
611
|
+
export declare interface ResizeState {
|
|
612
|
+
width?: number;
|
|
613
|
+
height?: number;
|
|
614
|
+
fit: 'contain' | 'cover' | 'force';
|
|
615
|
+
upscale: boolean;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/** Saturation adjustment matrix. v: -0.25 to 0.25 */
|
|
619
|
+
export declare function saturationMatrix(v: number): number[];
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Serialize editor state to a JSON string.
|
|
623
|
+
* Safe to store in localStorage, a database, or send over network.
|
|
624
|
+
*/
|
|
625
|
+
export declare function serializeState(state: ImageState): string;
|
|
626
|
+
|
|
627
|
+
declare interface StickerCategory {
|
|
628
|
+
id: string;
|
|
629
|
+
labelKey: string;
|
|
630
|
+
stickers: string[];
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
export declare interface StickerInstance {
|
|
634
|
+
id: string;
|
|
635
|
+
/** URL, data URI, or emoji character */
|
|
636
|
+
src: string;
|
|
637
|
+
/** Normalized 0-1 position */
|
|
638
|
+
x: number;
|
|
639
|
+
y: number;
|
|
640
|
+
/** Normalized 0-1 size */
|
|
641
|
+
width: number;
|
|
642
|
+
height: number;
|
|
643
|
+
/** Rotation in radians */
|
|
644
|
+
rotation: number;
|
|
645
|
+
flipX: boolean;
|
|
646
|
+
flipY: boolean;
|
|
647
|
+
opacity: number;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
export declare function StickerPlugin(): EditorPlugin;
|
|
651
|
+
|
|
652
|
+
/** Temperature adjustment matrix. v: -0.25 to 0.25 (positive = warmer, negative = cooler) */
|
|
653
|
+
export declare function temperatureMatrix(v: number): number[];
|
|
654
|
+
|
|
655
|
+
export declare function useEditor(): EditorEngine;
|
|
656
|
+
|
|
657
|
+
declare interface ViewportTransform {
|
|
658
|
+
zoom: number;
|
|
659
|
+
panX: number;
|
|
660
|
+
panY: number;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
export { }
|