Client Side Image Compression Before Upload

What about it?

My point is that implementing something like compression or croppie or anything else, you just use those external libraries separately from your server connect form. Just load the library, create the functions/scripts you need, and submit the results just in JavaScript rather than dmx.

Or did you have a specific question?

Oh. Got it. Did not tie “submit the image” point meaning submitting from JS library.
That’s something i’ll try.
I did find a way to do it without multiple submits. But still testing it.

Think @JonL did some work on integrating croppie if that helps; perhaps he can offer some assistance?

1 Like

I implemented cropper for profile pic selection.

It’s integrated with the browser S3 component.

Feel free to ask

I have found a working solution for my use case for now.
Its a regular image upload. But i could not make it work with dropzone, so not using dropzone now.

Thanks Jonas… I will definitely ping you when I get to the cropper style uploading. :smiley:

1 Like

As mentioned in this Feature Request Client-side image resizing before upload - Megapixels (Mb) rather than Image Resolution (pixels) The BlueImp’s jQuery File Upload plugin for PHP would do this very well.

I don’t think this particular library would be a good option anymore seeing that Wappler is also trying to get away from jQuery with BS5.

1 Like

Howdy! Any update regarding this implementation with Wappler?

1 Like

How did you solve this @sid?

I used this library: https://github.com/blueimp/JavaScript-Load-Image
The logic, in brief, is to have two file upload inputs. One inside the form, and one outside. When user selects and image, its using the outside file element. In onchange event of the outside element, I used this library to dynamically add cropped image(s) to the file element inside form.
Then user submits the form as a regular Wappler SC Form.

3 Likes

Thanks for the info. This library reduces the filesize enough for you?

For my use case, yes. Images uploaded are usually taken from mobile camera in this app - which usually have a resolution of 3000/4000px. My logic is to resize them to 800/1000px max, resulting in a good enough reduction.

Thanks for sharing Sid :slight_smile:
I’m trying to prevent a situation where users upload multiple images, let’s say 5, of 3MB which results in 15MB needed to be downloaded to load that page.

THink I’ll go with this https://www.npmjs.com/package/browser-image-compression - perhaps another server side compressor that makes it webp

This one looks good too. Make sure to use the on page JS option to make it work client side.

1 Like

Hi @JonL,
how have you implemented copperjs on wappler file upload and form submit?
I was trying that by replacing the dataUrl, but didn’t work, could you please let me know on how you implemented it for your projects

It’s from an old project. Let me check the source and get back to you.

1 Like

That’s what I did. Replace the dataUrl.

This is not how I would approach a cropper integration nowadays. I will refactor everything into a custom component as I will need for my current project.

Anyway, I hope you can make sense of this.

<script>
  var image = document.getElementById('profile_photo');
  var cropBoxData;
  var canvasData;
  var cropper;
  var c;
  function cropInit() {
    dmx.app.set('cropped', false);
    original = dmx.app.data.view2.s3upload1.file.dataUrl;
    cropper = new Cropper(image, {
      dragMode: 'move',
      restore: false,
      guides: false,
      center: false,
      highlight: false,
      cropBoxMovable: false,
      cropBoxResizable: false,
      toggleDragModeOnDblclick: false,
      aspectRatio: 1 / 1,
      autoCropArea: 0.5,
      ready: function () {
        //Should set crop box data first here
        cropper.setCropBoxData(cropBoxData).setCanvasData(canvasData);
        cropper.reset();
      }
    });
  }
  function cropDestroy() {
    cropBoxData = cropper.getCropBoxData();
    canvasData = cropper.getCanvasData();
    cropper.destroy();    
    dmx.parse('s3upload1.reset()')
  }
  function crop() {
     dmx.app.data.view2.s3upload1.file.dataUrl = cropper.getCroppedCanvas({"width" : "200", "height" : "200", "imageSmoothingQuality" : "high", "imageSmoothingEnabled" : true}).toDataURL("image/jpeg");
     dmx.app.set('cropped', true);
     cropper.getCroppedCanvas({"width" : "200", "height" : "200", "imageSmoothingQuality" : "high", "imageSmoothingEnabled" : true}).toBlob(function(blob) {
       document.getElementById('s3upload1').dmxComponent.file = new File([blob], "profile.jpeg", { lastModified: new Date().getTime(), type: blob.type });
     }, 'image/jpeg', 0.8);
  }
  function cancel() {    
    dmx.app.data.view2.s3upload1.file.dataUrl = original;
    dmx.app.set('cropped', false);  
  }
</script>
2 Likes

Thanks @JonL . This solved my problem

1 Like

Saturday coffee nights…who doesn’t love them?

Working on a cropperjs integration via custom component.

  1. Add to your img html tag the attribute is="dmx-jonl_cropper" and the src of the img you want to crop.
  2. Add some cropperjs options dragMode="move" aspectRatio="1" autoCropArea="0.5" noRestore noGuides noCenter noHighlight noCropBoxMovable noCropBoxResizable noToggleDragModeOnDblclick
<img is="dmx-jonl_cropper" id="cropper" dmx-bind:src="s3upload1.file.dataUrl" 
dragMode="move" aspectRatio="1" autoCropArea="0.5" noRestore noGuides 
noCenter noHighlight noCropBoxMovable noCropBoxResizable
noToggleDragModeOnDblclick>

Tada!

Still missing some methods and events but I ran out of coffee. And when I say coffee I mean coffee. My new hobby:

3 Likes