Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read image dimensions #1297

Closed
canvasbh opened this issue Feb 17, 2019 · 9 comments
Closed

Read image dimensions #1297

canvasbh opened this issue Feb 17, 2019 · 9 comments

Comments

@canvasbh
Copy link
Contributor

canvasbh commented Feb 17, 2019

Hello, and thanks for the great lib!

Is there a way to access the image dimensions within Uppy without need to go through a Blob -> FileReader -> Image conversion? I was unable to find a width/height metadata fields on the objects returned by the upload-success and complete events.

I'm currently doing this like so:

// convert the blob URL to an object
let objFile = await fetch(elem.preview)
let objBlob = await objFile.blob()

// convert it to a data URI
let reader = new FileReader()
reader.readAsDataURL(objBlob)

reader.onload = e => {
  // retrieve the image dimensions
  let image = new Image()
  image.src = e.target.result

  image.onload = (loadEvent) => {
    // all done
    resolve({
      thumbnail: e.target.result,
      url: elem.uploadURL,
      width: loadEvent.path[0].width,
      height: loadEvent.path[0].height,
      aspectRatio: loadEvent.path[0].width / loadEvent.path[0].height
    })
  }
}
@HeiVask
Copy link

HeiVask commented Feb 26, 2019

Related: It would be also nice to add the image dimensions as a restriction.

@goto-bus-stop
Copy link
Contributor

Indeed uppy doesn't have these built in. It would be possible to do with a plugin.

For the Blob/FileReader dance, the easier thing to do is to use URL.createObjectURL, which saves a few steps:

uppy.on('file-added', (file) => {
  const data = file.data // is a Blob instance
  const url = URL.createObjectURL(data)
  const image = new Image()
  image.src = url
  image.onload = () => {
    uppy.setFileMeta(file.id, { width: image.width, height: image.height })
    URL.revokeObjectURL(url)
  }
})

As for the .preview property, it's already a blob URL, which can be assigned directly to an Image's .src:

const image = new Image()
image.src = file.preview
image.onload = () => { ... }

Then you do not need the URL.createObjectURL and URL.revokeObjectURL calls.

@canvasbh
Copy link
Contributor Author

Thanks @goto-bus-stop for the comprehensive solution!

@RohiniJindam
Copy link

How to achieve this for a remote file eg Facebook or Intagram?

@goto-bus-stop
Copy link
Contributor

@RohiniJindam Unfortunately that is not possible, since there is no way to download remote files to the browser.

@RohiniJindam
Copy link

RohiniJindam commented Aug 6, 2020

@goto-bus-stop thanks for the quick reply.
This works:

this.uppy.on('file-added', (file) => {
         const data = file.data 
          const url = data.thumbnail?data.thumbnail:URL.createObjectURL(data)
          const image = new Image()
          image.src = url         
          image.onload = () => {
              uppy.setFileMeta(file.id, { width: image.width, height: image.height })
              URL.revokeObjectURL(url)
          }
          image.onerror = () => {             
             URL.revokeObjectURL(url)
          }

Do you see any issues here?

@goto-bus-stop
Copy link
Contributor

That kinda works, but note that the data.thumbnail for a remote file is not the same size as the original file.

@RohiniJ
Copy link

RohiniJ commented Aug 6, 2020

So preprocessors also cannot work for remote files? This plugin for example Image Processor Plugin @goto-bus-stop

@getup8
Copy link

getup8 commented Jul 12, 2021

Just going to leave this here in case helpful to anyone. I wanted to check the aspect ratio of the uploaded image and reject it if it was too weird. Using some of the logic above, I ended up with something like the below. The main assumption here is that the image preview doesn't change the underlying dimensions (or at least their ratio) of the uploaded image.

The only meh part of this is that you get a flash of the thumbnail and then it's immediately removed.

uppy.on('thumbnail:generated', (file, preview) => {
  const img = new Image();
  img.src = preview;
  img.onload = () => {
    const aspect_ratio = img.width / img.height;
    if (aspect_ratio > 1.8 || aspect_ratio < 0.5625 ) {
      uppy.removeFile(file.id);
      uppy.info(
        'Aspect ratio for photo is too skewed, please fix and try again.');
    }
  }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants