You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi, sorry this post has become very large, but I've spent all evening digging into this and would love to see improvements in this brilliantly useful library.
My issue mostly pertains to the fact that the library appears to not use byte arrays for images, and instead handles things mostly using data urls i.e. throwing lots of very large base64 strings around.
I apologise if I'm wrong with that analysis - I have looked into a lot of the code, and have been trying a lot of things with it in my own project, but it seems to have optimisation issues that I was unable to resolve with any of the existing Cropper library methods.
So this is what I've noticed / would like to suggest:
GetCroppedCanvasDataURLAsync() is far too slow.
Tested with image size >2MB, dimensions 1900 x 700
Not sure what's causing this. I've found the window.getPolygonImage JS method which appears to be where the work is done. Something there is presumably in need of optimisation.
Currently I'm using my own code to handle the raw byte data, and it is a LOT faster.
It takes the raw image bytes, along with Cropper.Blazor.Models.CropBoxData and Cropper.Blazor.Models.ContainerData, then crops the image almost instantly.
exportasyncfunctioncropImage(imageBytes: Uint8Array,cropBox: CropBoxData,container: ContainerData): Promise<Uint8Array>{try{constblob=newBlob([imageBytes],{type: "image/png"});constimageUrl=URL.createObjectURL(blob);constimg=newImage();img.src=imageUrl;awaitnewPromise((resolve,reject)=>{img.onload=resolve;img.onerror=reject;});constcroppingCanvas=document.createElement("canvas");constcontext=croppingCanvas.getContext("2d");if(!context){thrownewError("Unable to get canvas context");}// Calculate uniform scale factor based on image fit within containerconstscale=Math.min(container.width/img.naturalWidth,container.height/img.naturalHeight);// Calculate the offsets for centering the image within the containerconstoffsetX=(container.width-img.naturalWidth*scale)/2;constoffsetY=(container.height-img.naturalHeight*scale)/2;// Adjust crop box coordinates from container space to image spaceconstimageCropBox={left: (cropBox.left-offsetX)/scale,top: (cropBox.top-offsetY)/scale,width: cropBox.width/scale,height: cropBox.height/scale,};// Set the cropping canvas size to match the cropped regioncroppingCanvas.width=imageCropBox.width;croppingCanvas.height=imageCropBox.height;// Draw the cropped portion of the image onto the cropping canvascontext.drawImage(img,imageCropBox.left,imageCropBox.top,imageCropBox.width,imageCropBox.height,0,0,imageCropBox.width,imageCropBox.height);constresizedBlob=awaitnewPromise<Blob|null>((resolve)=>{croppingCanvas?.toBlob((blob)=>resolve(blob),'image/jpeg',1);});if(resizedBlob){returnnewUint8Array(awaitresizedBlob.arrayBuffer());}else{thrownewError("Resized blob empty");}}catch(error){console.error("Error cropping image:",error);returnnewUint8Array();}}
Return image as a byte array
To accompany the above, it would be good to have a C# method in the library that returns the canvas data as a Uint8Array object so it can be handled as a byte array in C#.
I've tried searching but can't find one.
So currently I'm using my own custom code for this too, i.e.
This even happens in the demo page so I'm sure it's not just an issue I'm facing.
Would it be possible to perform the image processing in the the background? i.e. not any await on the main function, then use DotNet.invokeMethodAsync to send the completed data back.
You could expose an event handler service for this so users can handle it without locking the UI, i.e.
// A Cropper message handlerpublicclassCropperService:ICropperService{privateeventAction<string>OnDataUrlProcessingComplete;[JSInvokable]publicstaticasyncTaskDataUrlProcessingComplete(stringdataUrl){this.OnDataUrlProcessingComplete?.Invoke(dataUrl);}}
@Stuart88 Have you ever wondered how to handle a case where the image is still being prepared in 'getCroppedCanvasDataURL' method but the cropper component has been destroyed?
@Stuart88 Have you ever wondered how to handle a case where the image is still being prepared in 'getCroppedCanvasDataURL' method but the cropper component has been destroyed?
I haven't looked back at the Cropper code in my project since I made this post, so I don't have any specific thoughts sorry!
However in general I think a way to prevent data being lost if the component is destroyed, is to use a separate service (probably a singleton) to hold onto any data so it can persist a little longer if needed.
Or maybe if the component implements IDisposableAsync it might be possible to prevent disposal until the canvas data processing is complete. I'm not 100% sure about it though.
Hi, sorry this post has become very large, but I've spent all evening digging into this and would love to see improvements in this brilliantly useful library.
My issue mostly pertains to the fact that the library appears to not use byte arrays for images, and instead handles things mostly using data urls i.e. throwing lots of very large base64 strings around.
I apologise if I'm wrong with that analysis - I have looked into a lot of the code, and have been trying a lot of things with it in my own project, but it seems to have optimisation issues that I was unable to resolve with any of the existing Cropper library methods.
So this is what I've noticed / would like to suggest:
GetCroppedCanvasDataURLAsync()
is far too slow.Tested with image size >2MB, dimensions 1900 x 700
Not sure what's causing this. I've found the
window.getPolygonImage
JS method which appears to be where the work is done. Something there is presumably in need of optimisation.Currently I'm using my own code to handle the raw byte data, and it is a LOT faster.
It takes the raw image bytes, along with
Cropper.Blazor.Models.CropBoxData
andCropper.Blazor.Models.ContainerData
, then crops the image almost instantly.Return image as a byte array
To accompany the above, it would be good to have a C# method in the library that returns the canvas data as a
Uint8Array
object so it can be handled as a byte array in C#.I've tried searching but can't find one.
So currently I'm using my own custom code for this too, i.e.
GetCroppedCanvasDataURLAsync()
locks the UI.This even happens in the demo page so I'm sure it's not just an issue I'm facing.
Would it be possible to perform the image processing in the the background? i.e. not any
await
on the main function, then useDotNet.invokeMethodAsync
to send the completed data back.You could expose an event handler service for this so users can handle it without locking the UI, i.e.
Thanks! And sorry for the wall of text, and sorry if I've missed something and all of my commentary is incorrect!
The text was updated successfully, but these errors were encountered: