CropperBlazor / Cropper.Blazor

Cropper.js as Blazor component for cropping images
https://cropperblazor.github.io
MIT License
121 stars 12 forks source link

WPF Hybrid: change copper src image old image #309

Closed LeeCY-C closed 4 months ago

LeeCY-C commented 4 months ago

Describe the bug ![Uploading 8d4df8b72b62900b1e1c55786d41bcd.png…]()

load default image and first change image is no problem. The problem arise when change the image second time . Change copper src image old image ,but old image append under the new image. This problem will not always arise,It just happens sometimes.

MaxymGorn commented 4 months ago

Hi @LeeCY-C you should use 'Replace' or 'Change' functionality instead of changing src image: https://cropperblazor.github.io/examples/replacing#simple-usage, https://cropperblazor.github.io/examples/rebuild#simple-usage. In addition, you can see example of code from demo site: https://github.com/CropperBlazor/Cropper.Blazor/blob/68dfc6d6cb4043dc8f7c5ade6ec492dbf22974bd/src/Cropper.Blazor/Client/Pages/CropperDemo.razor.cs#L386, https://github.com/CropperBlazor/Cropper.Blazor/blob/68dfc6d6cb4043dc8f7c5ade6ec492dbf22974bd/src/Cropper.Blazor/Client/Pages/CropperDemo.razor.cs#L404

LeeCY-C commented 4 months ago

8d4df8b72b62900b1e1c55786d41bcd this is the bug image

LeeCY-C commented 4 months ago

This is my change image code. ` public async Task FileInputValueChanged(IBrowserFile imageFile) { try { if (imageFile != null) { string oldSrc = imageSrc; string newSrc = await ImageCropper!.GetImageUsingStreamingAsync(imageFile, imageFile.Size);

                if (IsErrorLoadImage)
                {
                    IsAvailableInitCropper = true;
                    IsErrorLoadImage = false;
                }
                else
                {
                    IsAvailableInitCropper = false;
                }

                await Task.WhenAll(
                    ImageCropper?.ReplaceAsync(newSrc, false).AsTask(),
                    ImageCropper?.RevokeObjectUrlAsync(oldSrc).AsTask())
                    .ContinueWith(x =>
                    {
                        imageSrc = newSrc;
                    });
            }
        }
        catch (Exception exception)
        {
            await JSRuntime!.InvokeVoidAsync("console.log", $"{exception.Message}");
        }
    }`
MaxymGorn commented 4 months ago

@LeeCY-C I memorize in old versions library we have that issue. Could you check your version of library or try to update and use newest version? In addition, could you provide temporary project with reproduce of bug to check it? Moreover, verify cropper component parameters: IsAvailableInitCropper, IsErrorLoadImage and so on... Maybe, you can find the answer this following conversation: https://github.com/CropperBlazor/Cropper.Blazor/issues/150

MaxymGorn commented 4 months ago

Moreover, in your case we expecting to double initialization of cropper component, but we expect that regarding specific of work cropper component in our docs Screenshot_20240311_234856_Chrome

You can governance of cropper lifestyle independently, just using destroy or init function of cropper, but it should works in newest version of library properly.

LeeCY-C commented 4 months ago

CopperTestFor#309.zip This is an temporary project, and can recurrent this bug.

MaxymGorn commented 4 months ago

Hi @LeeCY-C in your case you should set up IsAvailableInitCropper = false; due to cropper.js rebuild inner cropper when you passed hasSameSize with falsevalue in ReplaceAsync method.

image

Seems we have this condition in our associated docs page, but you don't use error handing from processing images in library:

image
MaxymGorn commented 4 months ago

@LeeCY-C sometimes in your example project I have the same error for specific images, I have no clue in this moment why it's happened, I suppose it's a problem with hybrid WebView in WPF. I'm would investigate about this issue in multiple platforms. In your case, I'm recommended try to use rebuild cropper functionality: https://cropperblazor.github.io/examples/rebuild#simple-usage.

Code:

public async Task FileInputValueChanged(IBrowserFile imageFile)
{
    try
    {
        if (imageFile != null)
        {
            string oldSrc = imageSrc;
            imageSrc = await ImageCropper!.GetImageUsingStreamingAsync(imageFile, imageFile.Size);

            IsAvailableInitCropper = true;
            IsErrorLoadImage = false;

            ImageCropper!.Destroy();
            ImageCropper!.RevokeObjectUrlAsync(oldSrc);
        }
    }
    catch (Exception exception)
    {
        _snackbarOptions.Content = exception.Message;
        PopupService!.EnqueueSnackbarAsync(_snackbarOptions);
    }
}

Although you will have the same result. In addition, you need to add a style so that during processing (loading) the image is not be too large during processing in the cropper when changing the image

LeeCY-C commented 4 months ago

Thank you for your patient guidance. Now it work well.

MaxymGorn commented 4 months ago

Hi @LeeCY-C . I'm figure out why it's not working correctly in hybrid with WPF .net6 based on WebView2. I think it's a very specific problem in this platform, because we don't test on this platform and use Cropper.Blazor library. Overall, I see what caused this problem:

image

I see await ImageCropper!.RevokeObjectUrlAsync(oldSrc).AsTask(); not works properly sometimes in WebView with WPF platform. As result, we have the second cropper in this case. I'm resolve it with following code:

string OldSrc = string.Empty;

public async Task FileInputValueChanged(IBrowserFile imageFile)
{
    try
    {
        if (imageFile != null)
        {
            OldSrc = imageSrc;
            string newSrc = await ImageCropper!.GetImageUsingStreamingAsync(imageFile, imageFile.Size);

            IsAvailableInitCropper = false;

            await ImageCropper!.ReplaceAsync(newSrc, false).AsTask();
            imageSrc = newSrc;

            // not work in this place correctly, this line was moves to the OnLoadImageEvent method
            //await ImageCropper!.RevokeObjectUrlAsync(oldSrc).AsTask();
        }
    }
    catch (Exception exception)
    {
        _snackbarOptions.Content = exception.Message;
        PopupService!.EnqueueSnackbarAsync(_snackbarOptions);
    }
}
 public async void OnLoadImageEvent()
 {
// possible to check it to empty or whitespaces
       await ImageCropper!.RevokeObjectUrlAsync(OldSrc).AsTask(); // new line

       await JSRuntime!.InvokeVoidAsync("console.log", "Image Is loaded");
 }       

In general, it was a great solution to clean the redundant resource(s) (blobs) in OnLoadImageEvent method