tokimeki-image-editor 0.4.4 → 0.4.5

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.
@@ -2,8 +2,8 @@
2
2
  import '../styles/tokens.css';
3
3
  import { _ } from 'svelte-i18n';
4
4
  import { Redo2, Undo2, RotateCcw, ImagePlus, Check, Sparkles, Download, LoaderCircle } from 'lucide-svelte';
5
- import { createEditorState, loadImageFromFile, loadImageFromUrl, applyImageToState, setMode, applyCrop, applyTransformUpdate, applyAdjustmentsUpdate, applyFilter, setBlurAreas, setStampAreas, setAnnotations, setViewport, resetState, handleZoom as coreHandleZoom, saveToHistory as coreSaveToHistory, handleUndo as coreHandleUndo, handleRedo as coreHandleRedo, canUndo, canRedo, getKeyboardAction, applyKeyboardAction, exportImage, downloadExportedImage, getDroppedFile, getInputFile, handleDragOver } from '../utils/editor-core';
6
- import { calculateFitScale } from '../utils/canvas';
5
+ import { createEditorState, loadImageFromFile, loadImageFromUrl, applyImageToState, setMode, applyCrop, applyTransformUpdate, applyAdjustmentsUpdate, applyFilter, setBlurAreas, setStampAreas, setAnnotations, setViewport, resetState, handleZoom as coreHandleZoom, saveToHistory as coreSaveToHistory, handleUndo as coreHandleUndo, handleRedo as coreHandleRedo, canUndo, canRedo, getKeyboardAction, applyKeyboardAction, exportImage, getDroppedFile, getInputFile, handleDragOver } from '../utils/editor-core';
6
+ import { calculateFitScale, downloadImage } from '../utils/canvas';
7
7
  import { haptic } from '../utils/haptics';
8
8
  import BottomDock from './BottomDock.svelte';
9
9
  import IconButton from './IconButton.svelte';
@@ -180,9 +180,12 @@ function handleAnnotationsChange(annotations) {
180
180
  }
181
181
  async function handleExport() {
182
182
  haptic('success');
183
- await downloadExportedImage(state);
184
183
  const result = await exportImage(state);
185
- if (result && onExport)
184
+ if (!result)
185
+ return;
186
+ const filename = `edited-image-${Date.now()}.${state.exportOptions.format}`;
187
+ downloadImage(result.dataUrl, filename);
188
+ if (onExport)
186
189
  onExport(result.dataUrl);
187
190
  }
188
191
  async function handleComplete() {
@@ -131,10 +131,6 @@ export interface ExportResult {
131
131
  * Export editor state to image
132
132
  */
133
133
  export declare function exportImage(state: EditorState): Promise<ExportResult | null>;
134
- /**
135
- * Download exported image
136
- */
137
- export declare function downloadExportedImage(state: EditorState): Promise<void>;
138
134
  /**
139
135
  * Add a new annotation to state
140
136
  */
@@ -352,29 +352,23 @@ export async function exportImage(state) {
352
352
  return null;
353
353
  const exportCanvas = await applyTransformWithWebGPU(state.imageData.original, state.transform, state.adjustments, state.cropArea, state.blurAreas, state.stampAreas, state.annotations);
354
354
  const format = state.exportOptions.format === 'jpeg' ? 'image/jpeg' : 'image/png';
355
- const dataUrl = exportCanvas.toDataURL(format, state.exportOptions.quality);
355
+ // Single async encode (toBlob) — avoids synchronous toDataURL blocking the main thread
356
356
  const blob = await new Promise((resolve) => {
357
357
  exportCanvas.toBlob(b => resolve(b), format, state.exportOptions.quality);
358
358
  });
359
- const bitmap = await createImageBitmap(blob);
360
- const result = {
359
+ // Convert blob to data URL without re-encoding (just base64-wraps the existing bytes)
360
+ const dataUrl = await new Promise((resolve) => {
361
+ const reader = new FileReader();
362
+ reader.onload = () => resolve(reader.result);
363
+ reader.readAsDataURL(blob);
364
+ });
365
+ // Dimensions directly from the export canvas (already crop+rotation adjusted)
366
+ return {
361
367
  dataUrl,
362
368
  blob,
363
- width: bitmap.width,
364
- height: bitmap.height
369
+ width: exportCanvas.width,
370
+ height: exportCanvas.height
365
371
  };
366
- bitmap.close();
367
- return result;
368
- }
369
- /**
370
- * Download exported image
371
- */
372
- export async function downloadExportedImage(state) {
373
- const result = await exportImage(state);
374
- if (!result)
375
- return;
376
- const filename = `edited-image-${Date.now()}.${state.exportOptions.format}`;
377
- downloadImage(result.dataUrl, filename);
378
372
  }
379
373
  // ============================================================================
380
374
  // ANNOTATION HELPERS (for QuickDrawEditor)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokimeki-image-editor",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "description": "A image editor for svelte.",
5
5
  "type": "module",
6
6
  "license": "MIT",