@@ -19,7 +19,7 @@ import { ifDefined } from 'lit/directives/if-defined.js';
1919
2020import Bowser from 'bowser' ;
2121const LoaderGif = new URL ( './images/duck-loader.gif' , import . meta. url ) . href ;
22- const DEFAULT_IMAGE_QUALITY = 0.80 ;
22+ const DEFAULT_IMAGE_QUALITY = 0.8 ;
2323
2424export declare type CropperOptions = {
2525 shape ?: 'square' | 'circle' ;
@@ -164,39 +164,29 @@ export class CropAndSaveImageDialog extends LoadWhile(LitElement) {
164164 } ) ;
165165 }
166166
167- async #applyCircleMask( sourceUrl : string ) : Promise < Blob > {
168- const canvas = document . createElement ( 'canvas' ) ;
169- const image = new Image ( ) ;
170-
171- const blobPromise = new Promise < Blob > ( ( resolve , reject ) => {
172- image . onload = async ( ) => {
173- const size = Math . min ( image . naturalWidth , image . naturalHeight ) ;
174-
175- canvas . width = size ;
176- canvas . height = size ;
177-
178- const ctx = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ;
179- ctx . drawImage ( image , 0 , 0 ) ;
180-
181- ctx . globalCompositeOperation = 'destination-in' ;
182-
183- ctx . fillStyle = '#000' ;
184- ctx . beginPath ( ) ;
185- ctx . arc ( size * 0.5 , size * 0.5 , size * 0.5 , 0 , 2 * Math . PI ) ;
186- ctx . fill ( ) ;
167+ #applyCircleMask( canvas : HTMLCanvasElement ) {
168+ const size = Math . min ( canvas . width , canvas . height ) ;
169+ if ( canvas . width !== size || canvas . height !== size ) {
170+ const sourceCanvas = document . createElement ( 'canvas' ) ;
171+ sourceCanvas . width = size ;
172+ sourceCanvas . height = size ;
173+ const sourceCtx = sourceCanvas . getContext ( '2d' ) as CanvasRenderingContext2D ;
174+ sourceCtx . drawImage ( canvas , 0 , 0 ) ;
175+ canvas . width = size ;
176+ canvas . height = size ;
177+ const resizedCtx = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ;
178+ resizedCtx . drawImage ( sourceCanvas , 0 , 0 ) ;
179+ }
187180
188- ctx . globalCompositeOperation = 'source-over' ;
181+ const ctx = canvas . getContext ( '2d' ) as CanvasRenderingContext2D ;
182+ ctx . globalCompositeOperation = 'destination-in' ;
189183
190- try {
191- resolve ( await this . #canvasToBlob( canvas , this . #mimeType, this . options ?. outputQuality ?? DEFAULT_IMAGE_QUALITY ) ) ;
192- } catch ( e ) {
193- reject ( e ) ;
194- }
195- } ;
196- } ) ;
197- image . src = sourceUrl ;
184+ ctx . fillStyle = '#000' ;
185+ ctx . beginPath ( ) ;
186+ ctx . arc ( size * 0.5 , size * 0.5 , size * 0.5 , 0 , 2 * Math . PI ) ;
187+ ctx . fill ( ) ;
198188
199- return blobPromise ;
189+ ctx . globalCompositeOperation = 'source-over' ;
200190 }
201191
202192 // adapted from https://fengyuanchen.github.io/cropperjs/v2/api/cropper-selection.html#limit-boundaries
@@ -487,16 +477,10 @@ export class CropAndSaveImageDialog extends LoadWhile(LitElement) {
487477 return ;
488478 }
489479
490- const blob = await this . #canvasToBlob( canvas , this . #mimeType, this . options ?. outputQuality ?? DEFAULT_IMAGE_QUALITY ) ;
491-
492- let previewBlob : Blob ;
493480 if ( this . options ?. shape === 'circle' ) {
494- const tempUrl = URL . createObjectURL ( blob ) ;
495- previewBlob = await this . #applyCircleMask( tempUrl ) ;
496- URL . revokeObjectURL ( tempUrl ) ;
497- } else {
498- previewBlob = blob ;
481+ this . #applyCircleMask( canvas ) ;
499482 }
483+ const previewBlob = await this . #canvasToBlob( canvas , this . #mimeType, this . options ?. outputQuality ?? DEFAULT_IMAGE_QUALITY ) ;
500484
501485 const previewUrl = URL . createObjectURL ( previewBlob ) ;
502486 const file = this . blobToFile ( previewBlob , this . #changeFileExtension( this . fileName , this . #extension) ) ;
0 commit comments