@gradio/imageeditor 0.12.13 → 0.13.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 (130) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/Example.svelte +1 -1
  3. package/IMAGE_EDITOR_OVERVIEW.md +224 -0
  4. package/ImageEditor.stories.svelte +4 -4
  5. package/Index.svelte +35 -46
  6. package/{shared/InteractiveImageEditor.svelte → InteractiveImageEditor.svelte} +56 -103
  7. package/dist/Example.svelte.d.ts +1 -1
  8. package/dist/Index.svelte +29 -33
  9. package/dist/Index.svelte.d.ts +17 -16
  10. package/dist/{shared/InteractiveImageEditor.svelte → InteractiveImageEditor.svelte} +47 -88
  11. package/dist/{shared/InteractiveImageEditor.svelte.d.ts → InteractiveImageEditor.svelte.d.ts} +13 -15
  12. package/dist/shared/Anchor.svelte +311 -0
  13. package/dist/shared/Anchor.svelte.d.ts +18 -0
  14. package/dist/shared/Controls.svelte +162 -23
  15. package/dist/shared/Controls.svelte.d.ts +7 -2
  16. package/dist/shared/{tools/IconButton.svelte → IconButton.svelte} +19 -3
  17. package/dist/shared/{tools/IconButton.svelte.d.ts → IconButton.svelte.d.ts} +4 -1
  18. package/dist/shared/ImageEditor.svelte +546 -289
  19. package/dist/shared/ImageEditor.svelte.d.ts +51 -56
  20. package/dist/shared/Layers.svelte +233 -0
  21. package/dist/shared/Layers.svelte.d.ts +35 -0
  22. package/dist/shared/Resize.svelte +218 -0
  23. package/dist/shared/Resize.svelte.d.ts +29 -0
  24. package/dist/shared/SecondaryToolbar.svelte +54 -0
  25. package/dist/shared/SecondaryToolbar.svelte.d.ts +35 -0
  26. package/dist/shared/Toolbar.svelte +337 -0
  27. package/dist/shared/Toolbar.svelte.d.ts +42 -0
  28. package/dist/shared/{tools → brush}/BrushOptions.svelte +68 -64
  29. package/dist/shared/{tools → brush}/BrushOptions.svelte.d.ts +9 -9
  30. package/dist/shared/{tools → brush}/BrushSize.svelte +2 -27
  31. package/dist/shared/{tools → brush}/ColorField.svelte +2 -1
  32. package/dist/shared/{tools → brush}/ColorField.svelte.d.ts +1 -0
  33. package/dist/shared/{tools → brush}/ColorPicker.svelte +81 -9
  34. package/dist/shared/{tools → brush}/ColorPicker.svelte.d.ts +1 -0
  35. package/dist/shared/{tools → brush}/ColorSwatch.svelte +78 -38
  36. package/dist/shared/{tools → brush}/ColorSwatch.svelte.d.ts +6 -2
  37. package/dist/shared/brush/brush-cursor.d.ts +101 -0
  38. package/dist/shared/brush/brush-cursor.js +327 -0
  39. package/dist/shared/brush/brush-textures.d.ts +71 -0
  40. package/dist/shared/brush/brush-textures.js +404 -0
  41. package/dist/shared/brush/brush-utils.d.ts +32 -0
  42. package/dist/shared/brush/brush-utils.js +59 -0
  43. package/dist/shared/brush/brush.d.ts +152 -0
  44. package/dist/shared/brush/brush.js +396 -0
  45. package/dist/shared/brush/types.d.ts +37 -0
  46. package/dist/shared/brush/types.js +1 -0
  47. package/dist/shared/core/editor.d.ts +252 -0
  48. package/dist/shared/core/editor.js +1221 -0
  49. package/dist/shared/crop/crop.d.ts +201 -0
  50. package/dist/shared/crop/crop.js +727 -0
  51. package/dist/shared/image/image.d.ts +89 -0
  52. package/dist/shared/image/image.js +185 -0
  53. package/dist/shared/resize/resize.d.ts +270 -0
  54. package/dist/shared/resize/resize.js +1413 -0
  55. package/dist/shared/types.d.ts +12 -0
  56. package/dist/shared/utils/pixi.d.ts +16 -57
  57. package/dist/shared/utils/pixi.js +15 -113
  58. package/dist/shared/zoom/zoom.d.ts +136 -0
  59. package/dist/shared/zoom/zoom.js +548 -0
  60. package/package.json +11 -10
  61. package/shared/Anchor.svelte +384 -0
  62. package/shared/Controls.svelte +194 -27
  63. package/shared/{tools/IconButton.svelte → IconButton.svelte} +21 -4
  64. package/shared/ImageEditor.svelte +682 -349
  65. package/shared/Layers.svelte +249 -0
  66. package/shared/Resize.svelte +239 -0
  67. package/shared/SecondaryToolbar.svelte +61 -0
  68. package/shared/Toolbar.svelte +386 -0
  69. package/shared/brush/BRUSH_TOOL.md +134 -0
  70. package/shared/brush/BrushOptions.svelte +200 -0
  71. package/shared/{tools → brush}/BrushSize.svelte +2 -30
  72. package/shared/{tools → brush}/ColorField.svelte +3 -1
  73. package/shared/{tools → brush}/ColorPicker.svelte +86 -9
  74. package/shared/{tools → brush}/ColorSwatch.svelte +95 -42
  75. package/shared/brush/brush-cursor.ts +408 -0
  76. package/shared/brush/brush-textures.ts +508 -0
  77. package/shared/brush/brush-utils.ts +76 -0
  78. package/shared/brush/brush.ts +506 -0
  79. package/shared/brush/types.ts +41 -0
  80. package/shared/core/EDITOR.md +182 -0
  81. package/shared/core/editor.ts +1730 -0
  82. package/shared/crop/CROP.md +139 -0
  83. package/shared/crop/crop.ts +1027 -0
  84. package/shared/image/IMAGE.md +135 -0
  85. package/shared/image/image.ts +300 -0
  86. package/shared/resize/resize.ts +1894 -0
  87. package/shared/types.ts +14 -0
  88. package/shared/utils/pixi.ts +19 -246
  89. package/shared/zoom/zoom.ts +729 -0
  90. package/dist/shared/layers/Layers.svelte +0 -231
  91. package/dist/shared/layers/Layers.svelte.d.ts +0 -18
  92. package/dist/shared/layers/utils.d.ts +0 -73
  93. package/dist/shared/layers/utils.js +0 -156
  94. package/dist/shared/tools/Brush.svelte +0 -215
  95. package/dist/shared/tools/Brush.svelte.d.ts +0 -29
  96. package/dist/shared/tools/Crop.svelte +0 -155
  97. package/dist/shared/tools/Crop.svelte.d.ts +0 -16
  98. package/dist/shared/tools/Cropper.svelte +0 -271
  99. package/dist/shared/tools/Cropper.svelte.d.ts +0 -41
  100. package/dist/shared/tools/Handle.svelte +0 -260
  101. package/dist/shared/tools/Handle.svelte.d.ts +0 -29
  102. package/dist/shared/tools/Sources.svelte +0 -257
  103. package/dist/shared/tools/Sources.svelte.d.ts +0 -34
  104. package/dist/shared/tools/Tools.svelte +0 -102
  105. package/dist/shared/tools/Tools.svelte.d.ts +0 -48
  106. package/dist/shared/tools/brush.d.ts +0 -62
  107. package/dist/shared/tools/brush.js +0 -133
  108. package/dist/shared/tools/crop.d.ts +0 -15
  109. package/dist/shared/tools/crop.js +0 -154
  110. package/dist/shared/tools/index.d.ts +0 -5
  111. package/dist/shared/tools/index.js +0 -5
  112. package/dist/shared/tools/sources.d.ts +0 -46
  113. package/dist/shared/tools/sources.js +0 -121
  114. package/dist/shared/tools/types.d.ts +0 -1
  115. package/shared/layers/Layers.svelte +0 -250
  116. package/shared/layers/utils.ts +0 -294
  117. package/shared/tools/Brush.svelte +0 -280
  118. package/shared/tools/BrushOptions.svelte +0 -180
  119. package/shared/tools/Crop.svelte +0 -189
  120. package/shared/tools/Cropper.svelte +0 -346
  121. package/shared/tools/Handle.svelte +0 -289
  122. package/shared/tools/Sources.svelte +0 -283
  123. package/shared/tools/Tools.svelte +0 -162
  124. package/shared/tools/brush.ts +0 -247
  125. package/shared/tools/crop.ts +0 -213
  126. package/shared/tools/index.ts +0 -5
  127. package/shared/tools/sources.ts +0 -195
  128. package/shared/tools/types.ts +0 -1
  129. /package/dist/shared/{tools → brush}/BrushSize.svelte.d.ts +0 -0
  130. /package/dist/shared/{tools/types.js → types.js} +0 -0
@@ -0,0 +1,12 @@
1
+ export interface ImageBlobs {
2
+ background: Blob | null;
3
+ layers: (Blob | null)[];
4
+ composite: Blob | null;
5
+ }
6
+ export interface LayerOptions {
7
+ allow_additional_layers: boolean;
8
+ layers: string[];
9
+ disabled: boolean;
10
+ }
11
+ export type Source = "upload" | "webcam" | "clipboard";
12
+ export type Transform = "crop" | "resize";
@@ -1,60 +1,4 @@
1
- import { Container, Graphics, Rectangle, type IRenderer, type ICanvas } from "pixi.js";
2
- import { type LayerScene } from "../layers/utils";
3
- /**
4
- * interface holding references to pixi app components
5
- */
6
- export interface PixiApp {
7
- /**
8
- * The pixi container for layers
9
- */
10
- layer_container: Container;
11
- /**
12
- * The pixi container for background images and colors
13
- */
14
- background_container: Container;
15
- /**
16
- * The pixi renderer
17
- */
18
- renderer: IRenderer;
19
- /**
20
- * The pixi canvas
21
- */
22
- view: HTMLCanvasElement & ICanvas;
23
- /**
24
- * The pixi container for masking
25
- */
26
- mask_container: Container;
27
- destroy(): void;
28
- /**
29
- * Resizes the pixi app
30
- * @param width the new width
31
- * @param height the new height
32
- */
33
- resize(width: number, height: number): void;
34
- /**
35
- * Gets the blobs for the background, layers, and composite
36
- * @param bounds the bounds of the canvas
37
- * @returns a promise with the blobs
38
- */
39
- get_blobs(layers: LayerScene[], bounds: Rectangle, dimensions: [number, number]): Promise<ImageBlobs>;
40
- /**
41
- * Gets the layers
42
- */
43
- get_layers?: () => LayerScene[];
44
- }
45
- /**
46
- * Creates a PIXI app and attaches it to a DOM element
47
- * @param target DOM element to attach PIXI app to
48
- * @param width Width of the PIXI app
49
- * @param height Height of the PIXI app
50
- * @param antialias Whether to use antialiasing
51
- * @returns object with pixi container and renderer
52
- */
53
- export declare function create_pixi_app({ target, dimensions: [width, height], antialias }: {
54
- target: HTMLElement;
55
- dimensions: [number, number];
56
- antialias: boolean;
57
- }): PixiApp;
1
+ import { Graphics, type Renderer, type Container } from "pixi.js";
58
2
  /**
59
3
  * Creates a pixi graphics object.
60
4
  * @param z_index the z index of the graphics object
@@ -69,6 +13,21 @@ export declare function make_graphics(z_index: number): Graphics;
69
13
  * @returns The clamped number.
70
14
  */
71
15
  export declare function clamp(n: number, min: number, max: number): number;
16
+ /**
17
+ * Generates a blob from a pixi object.s
18
+ * @param renderer The pixi renderer.
19
+ * @param obj The pixi object to generate a blob from.
20
+ * @param bounds The bounds of the canvas that we wish to extract
21
+ * @param width The full width of the canvas
22
+ * @param height The full height of the canvas
23
+ * @returns A promise with the blob.
24
+ */
25
+ export declare function get_canvas_blob(renderer: Renderer, obj: Container | null, bounds?: {
26
+ x: number;
27
+ y: number;
28
+ width: number;
29
+ height: number;
30
+ }): Promise<Blob | null>;
72
31
  export interface ImageBlobs {
73
32
  background: Blob | null;
74
33
  layers: (Blob | null)[];
@@ -1,96 +1,4 @@
1
- import { Application, Container, Graphics, Sprite, Rectangle, RenderTexture } from "pixi.js";
2
- import {} from "../layers/utils";
3
- /**
4
- * Creates a PIXI app and attaches it to a DOM element
5
- * @param target DOM element to attach PIXI app to
6
- * @param width Width of the PIXI app
7
- * @param height Height of the PIXI app
8
- * @param antialias Whether to use antialiasing
9
- * @returns object with pixi container and renderer
10
- */
11
- export function create_pixi_app({ target, dimensions: [width, height], antialias }) {
12
- const ratio = window.devicePixelRatio || 1;
13
- const app = new Application({
14
- width,
15
- height,
16
- antialias: antialias,
17
- backgroundAlpha: 0,
18
- eventMode: "static"
19
- });
20
- const view = app.view;
21
- // ensure that we can sort the background and layer containers
22
- app.stage.sortableChildren = true;
23
- view.style.maxWidth = `${width / ratio}px`;
24
- view.style.maxHeight = `${height / ratio}px`;
25
- view.style.width = "100%";
26
- view.style.height = "100%";
27
- target.appendChild(app.view);
28
- // we need a separate container for the background so that we can
29
- // clear its content without knowing too much about its children
30
- const background_container = new Container();
31
- background_container.zIndex = 0;
32
- const layer_container = new Container();
33
- layer_container.zIndex = 1;
34
- // ensure we can reorder layers via zIndex
35
- layer_container.sortableChildren = true;
36
- const mask_container = new Container();
37
- mask_container.zIndex = 1;
38
- const composite_container = new Container();
39
- composite_container.zIndex = 0;
40
- mask_container.addChild(background_container);
41
- mask_container.addChild(layer_container);
42
- app.stage.addChild(mask_container);
43
- app.stage.addChild(composite_container);
44
- const mask = new Graphics();
45
- let text = RenderTexture.create({
46
- width,
47
- height
48
- });
49
- const sprite = new Sprite(text);
50
- mask_container.mask = sprite;
51
- app.render();
52
- function reset_mask(width, height) {
53
- background_container.removeChildren();
54
- mask.beginFill(0xffffff, 1);
55
- mask.drawRect(0, 0, width, height);
56
- mask.endFill();
57
- text = RenderTexture.create({
58
- width,
59
- height
60
- });
61
- app.renderer.render(mask, {
62
- renderTexture: text
63
- });
64
- const sprite = new Sprite(text);
65
- mask_container.mask = sprite;
66
- }
67
- function resize(width, height) {
68
- app.renderer.resize(width, height);
69
- view.style.maxWidth = `${width / ratio}px`;
70
- view.style.maxHeight = `${height / ratio}px`;
71
- reset_mask(width, height);
72
- }
73
- async function get_blobs(_layers, bounds, [w, h]) {
74
- const background = await get_canvas_blob(app.renderer, background_container, bounds, w, h);
75
- const layers = await Promise.all(_layers.map((layer) => get_canvas_blob(app.renderer, layer.composite, bounds, w, h)));
76
- const composite = await get_canvas_blob(app.renderer, mask_container, bounds, w, h);
77
- return {
78
- background,
79
- layers,
80
- composite
81
- };
82
- }
83
- return {
84
- layer_container,
85
- renderer: app.renderer,
86
- destroy: () => app.destroy(true),
87
- view: app.view,
88
- background_container,
89
- mask_container,
90
- resize,
91
- get_blobs
92
- };
93
- }
1
+ import { Graphics, Rectangle } from "pixi.js";
94
2
  /**
95
3
  * Creates a pixi graphics object.
96
4
  * @param z_index the z index of the graphics object
@@ -113,7 +21,7 @@ export function clamp(n, min, max) {
113
21
  return n < min ? min : n > max ? max : n;
114
22
  }
115
23
  /**
116
- * Generates a blob from a pixi object.
24
+ * Generates a blob from a pixi object.s
117
25
  * @param renderer The pixi renderer.
118
26
  * @param obj The pixi object to generate a blob from.
119
27
  * @param bounds The bounds of the canvas that we wish to extract
@@ -121,28 +29,22 @@ export function clamp(n, min, max) {
121
29
  * @param height The full height of the canvas
122
30
  * @returns A promise with the blob.
123
31
  */
124
- function get_canvas_blob(renderer, obj, bounds, width, height) {
32
+ export function get_canvas_blob(renderer, obj, bounds) {
125
33
  return new Promise((resolve) => {
126
- // for some reason pixi won't extract a cropped canvas without distorting it
127
- // so we have to extract the whole canvas and crop it manually
128
- const src_canvas = renderer.extract.canvas(obj, new Rectangle(0, 0, width, height));
129
- // Create a new canvas for the cropped area with the appropriate size
130
- let dest_canvas = document.createElement("canvas");
131
- dest_canvas.width = bounds.width;
132
- dest_canvas.height = bounds.height;
133
- let dest_ctx = dest_canvas.getContext("2d");
134
- if (!dest_ctx) {
34
+ if (!obj) {
135
35
  resolve(null);
136
- throw new Error("Could not create canvas context");
36
+ return;
137
37
  }
138
- // Draw the cropped area onto the destination canvas
139
- dest_ctx.drawImage(src_canvas,
140
- // this is the area of the source that we want to copy (the crop box)
141
- bounds.x, bounds.y, bounds.width, bounds.height,
142
- // this is where we want to draw the crop box on the destination canvas
143
- 0, 0, bounds.width, bounds.height);
144
- // we grab a blob here so we can upload it
145
- dest_canvas.toBlob?.((blob) => {
38
+ const image_bounds = obj.getLocalBounds();
39
+ const frame = bounds
40
+ ? new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height)
41
+ : new Rectangle(0, 0, image_bounds.width, image_bounds.height);
42
+ const src_canvas = renderer.extract.canvas({
43
+ target: obj,
44
+ resolution: 1,
45
+ frame
46
+ });
47
+ src_canvas.toBlob?.((blob) => {
146
48
  if (!blob) {
147
49
  resolve(null);
148
50
  }
@@ -0,0 +1,136 @@
1
+ import { type FederatedWheelEvent, type FederatedPointerEvent } from "pixi.js";
2
+ import { type ImageEditorContext, type Tool } from "../core/editor";
3
+ import { type Tool as ToolbarTool, type Subtool } from "../Toolbar.svelte";
4
+ /**
5
+ * ZoomTool class for handling zoom and pan functionality in the image editor
6
+ * Implements the Tool interface
7
+ */
8
+ export declare class ZoomTool implements Tool {
9
+ name: string;
10
+ min_zoom: import("svelte/store").Writable<boolean>;
11
+ private image_editor_context;
12
+ private readonly max_zoom;
13
+ private readonly border_padding;
14
+ private pad_bottom;
15
+ private is_pinching;
16
+ private is_dragging;
17
+ private is_pointer_dragging;
18
+ private last_touch_position;
19
+ private last_pinch_distance;
20
+ private drag_start;
21
+ private current_tool;
22
+ private current_subtool;
23
+ private local_scale;
24
+ private local_dimensions;
25
+ private local_position;
26
+ /**
27
+ * Prevents default behavior for events
28
+ * @param {FederatedWheelEvent | FederatedPointerEvent} event - The event to prevent default behavior for
29
+ */
30
+ prevent_default(event: FederatedWheelEvent | FederatedPointerEvent | WheelEvent): void;
31
+ /**
32
+ * Sets the current tool and subtool
33
+ * @param {ToolbarTool} tool - The tool to set
34
+ * @param {Subtool} subtool - The subtool to set
35
+ */
36
+ set_tool(tool: ToolbarTool, subtool: Subtool): void;
37
+ /**
38
+ * Sets the zoom level to a specific percentage or fits the image to the screen
39
+ * @param {number | 'fit'} zoom_level - The zoom level to set (0-1) or 'fit' to use min_zoom
40
+ * @returns {void}
41
+ */
42
+ set_zoom(zoom_level: number | "fit"): void;
43
+ /**
44
+ * Sets up the zoom tool with the given context and state
45
+ * @param {ImageEditorContext} context - The image editor context
46
+ * @param {ToolbarTool} tool - The current tool
47
+ * @param {Subtool} subtool - The current subtool
48
+ * @returns {Promise<void>}
49
+ */
50
+ setup(context: ImageEditorContext, tool: ToolbarTool, subtool: Subtool): Promise<void>;
51
+ /**
52
+ * Sets up event listeners for zoom and pan functionality
53
+ * @private
54
+ */
55
+ private setup_event_listeners;
56
+ /**
57
+ * Handles wheel events for zooming
58
+ * @param {FederatedWheelEvent} event - The wheel event
59
+ * @private
60
+ */
61
+ private handle_wheel;
62
+ /**
63
+ * Cleans up resources and event listeners
64
+ */
65
+ cleanup(): void;
66
+ /**
67
+ * Gets the dimensions of the container
68
+ * @returns {Promise<{width: number, height: number}>} The container dimensions
69
+ * @private
70
+ */
71
+ private get_container_dimensions;
72
+ /**
73
+ * Calculates the minimum zoom level to fit the image in the viewport
74
+ * @param {number} container_width - The width of the container
75
+ * @param {number} container_height - The height of the container
76
+ * @returns {number} The minimum zoom level
77
+ * @private
78
+ */
79
+ private calculate_min_zoom;
80
+ /**
81
+ * Handles touch start events
82
+ * @param {TouchEvent} event - The touch event
83
+ * @private
84
+ */
85
+ private handle_touch_start;
86
+ /**
87
+ * Handles touch move events
88
+ * @param {TouchEvent} event - The touch event
89
+ * @private
90
+ */
91
+ private handle_touch_move;
92
+ /**
93
+ * Handles touch end events
94
+ * @param {TouchEvent} event - The touch event
95
+ * @private
96
+ */
97
+ private handle_touch_end;
98
+ /**
99
+ * Gets the bounded position to keep the image within the viewport
100
+ * @param {Object} position - The position to bound
101
+ * @param {number} position.x - The x coordinate
102
+ * @param {number} position.y - The y coordinate
103
+ * @returns {Object} The bounded position
104
+ * @private
105
+ */
106
+ private get_bounded_position;
107
+ /**
108
+ * Zooms to a specific point with a new zoom level
109
+ * @param {number} new_zoom - The new zoom level
110
+ * @param {Object} point - The point to zoom to
111
+ * @param {number} point.x - The x coordinate of the point
112
+ * @param {number} point.y - The y coordinate of the point
113
+ * @param {boolean} hard - Whether to apply a hard zoom (no animation)
114
+ * @param {boolean} is_fit_zoom - Whether this is a fit zoom operation
115
+ * @private
116
+ */
117
+ private zoom_to_point;
118
+ /**
119
+ * Handles pointer down events
120
+ * @param {FederatedPointerEvent} event - The pointer event
121
+ * @private
122
+ */
123
+ private handle_pointer_down;
124
+ /**
125
+ * Handles pointer move events
126
+ * @param {FederatedPointerEvent} event - The pointer event
127
+ * @private
128
+ */
129
+ private handle_pointer_move;
130
+ /**
131
+ * Handles pointer up events
132
+ * @param {FederatedPointerEvent} event - The pointer event
133
+ * @private
134
+ */
135
+ private handle_pointer_up;
136
+ }