1

I have a 100% client-side web app that processes images picked by users. However I want users to be able to only pick formats that browser can read.

None of the below code really works without feature detection. Is there any standard or foolproof way to do it?

  • This input let users pick ALL image formats including TIFF which only Safari can open:
<input type="file" accept="image/*" />
  • This input let users pick certain file formats. However we have to maintain a list that may change in the future. Also AVIF is supported in most browsers EXCEPT Chromium Edge. So, a list as well as feature detection are needed.
<input type="file" accept=".apng, .gif, .jpg, .jpeg, .jfif, .pjpeg, .pjp, .png, .svg, .webp, .bmp, .ico, .cur" />

By "supporting", I would like the browser to be able to either:

  • Show it in an <img /> tag.

  • Draw it into a <canvas>.


Update: This question focuses mainly from the UI/UX perspective. I know there must be an error check anyway after user picks a file (users can pick any file they want, and even a corrupt PNG file for example). What I meant is, I would like to show the open dialog with just the formats that I know the browser would support so I don't show the error message after user already picks a file.

Luke Vo
  • 17,859
  • 21
  • 105
  • 181
  • 1
    I'm not sure if this is a solution but use `accept="image/*"` then the use [`onerror` event](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#image_loading_errors). If the image fails to load then that means that the image isn't supported by the browser (do whatever you want). If the Image loads then the browser supports it and you're good to go. We need [`canPlayType` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType) for images, yeah, [we need it](https://github.com/whatwg/html/issues/6324) the most... ;) – Sally loves Lightning Jul 04 '23 at 16:31
  • @LightningMcQueen yes the proposed method is what I meant :) Glad there's already a proposal for it though IMO `canPlayType` only partially solves it. We need something like `getSupportedFormats()` so we don't have to maintain a list. You can see similar issues with [WebCodec](https://stackoverflow.com/questions/39393784/is-it-possible-to-check-which-video-audio-codec-supported-by-which-browser-usi) and [MediaRecorder](https://stackoverflow.com/questions/41739837/all-mime-types-supported-by-mediarecorder-in-firefox-and-chrome) – Luke Vo Jul 04 '23 at 16:38
  • 1
    You're welcome. I'm going to add "Googler" to my resume, aha! Anyway, yeah, true `canPlayType` only partially solves the problem, but at least there's one. For images, there's pretty almost nothing. Actually, such a method like `getSupportedFormats()` will take a lot of time to be coded, and about a decade to be supported by all major browsers, and will need more time for Firefox to have the same behavior as Chrome browsers (some people call Firefox the new Internet Explorer due to differences between both browsers), so till 2033, move on and just check using JavaScript. (1/2) – Sally loves Lightning Jul 04 '23 at 16:44
  • 1
    Also, since you're looking from a UI/UX perspective, then this is such a minor change, most users won't notice it anyway, so do something better, and actually, most people use PNG/JPG, and sometimes the new WEBP. it's quite uncommon to see someone that uses TIFF or other file formats unless your application was made for such a purpose as using/editing/storing high-quality photos or something similar. (2/2) – Sally loves Lightning Jul 04 '23 at 16:49
  • 1
    @LightningMcQueen thanks, that makes sense! As a workaround, I am actually adding TIFF support (using a JS lib) when user picks such files as well. – Luke Vo Jul 04 '23 at 17:01
  • 1
    @LightningMcQueen (One of) the problem(s) with a method like `canPlayType` on `Image` is that image formats come with a lot of various features that not all decoders do support, take for instance webp and its alpha, animations, lossless features. A decoder could decode basic .webp files but not the advanced ones (e.g. old Safari's). And contrary to video formats, there is no *codecs* one can test again. Even .png will soon have an HDR field, which should be backward compatible, meaning current decoders will still be able to do *something* of it, but they won't have the HDR features. (1/2) – Kaiido Jul 04 '23 at 22:47
  • 1
    A proper `canPlayType` method should be able to tell that apart. But MIME types for images won't work. But for the case here that doesn't matter much because `accept` only accepts extensions and MIME types and so won't be able to tell apart these formats that are only *partially* supported anyway. (2/2) – Kaiido Jul 04 '23 at 22:48
  • Regarding the question, show it in an tag or draw it on a are equivalent, you need to pass through an or an ImageBitmap (which supports less formats than ) to draw on a . – Kaiido Jul 04 '23 at 22:50

1 Answers1

-1

Like you mention, a user can open whatever they want just by typing asterisk.asterisk and pressing [enter] in the file opening dialog box.

Therefore it all comes down to the error checking which you can set up like this:

So given...

function ProcessImage(Img){}

Then you can do your error checking like so...

<input type="file" accept="image/*" onchange="if((this.value!==null)&&(this.value!=='')){ProcessImage(this);} this.value=null;">

NB: Cancelling the file opening dialog box should also trigger the error.

PassThru
  • 1
  • 1