Chromium Update "Respecting" Image Orientation Causing Issues with JPEG Uploads - javascript

Last year I found an old JS function by hMatoba from a previous question thread that allows client-side resizing of JPEGs before uploads. This is very useful when EXIF data is needed on the server-side, and when images larger than a certain size are not needed.
This worked very well until Chromium's switch to respecting EXIF image orientation, this library now creates images that cut off part of the image. See here for an example: https://imgur.com/a/JdYooXC. The library continues to work fine in IE (which is a bit useless in 2020...), but fails in Chrome and Edge (Chromium).
I feel like the issue is when the image object is created in the function and loaded with file data, there's a conflict between what the browser presents as "width" and "height" and what the EXIF data shows. Unfortunately, I can't figure out exactly where the fix needs to be implemented. Anyone care to help, or know if an alternative?

Related

Rendering Multiple Images in React and HTML

I have a problem rendering images with large file sizes. When I upload a lot of large file sizes of images and display them, it becomes very laggy.
My question is:
The ideal way is the backend should provide an very small image file size url?
Or the frontend can do it using Canvas API?
Could you provide an explanation please? Thank you
If you have a bunch of thumbnails to display, the source images for those thumbnails should definitely not be the original, full-size images. If those images are large, it will take a long time for the client to download them, no matter how you render them on the client.
When figuring out an image to be shown to client, you should have two versions on the server:
Thumbnail version - low resolution, small file size, easy to download and render many at once
Full-size version, downloaded when the user wants to zoom in on one of them
It could be that the full-size version should not necessarily be the original image. For example, if the original image is 20MB (yes, they can exist), you wouldn't want to burden clients with that. So you'd want to perform resizes and optimizations on the server for both the thumbnail version and the "full" version - enough such that there isn't much of a delay between when the client tries to zoom in and the full-size image fully loads.
My recommendation is that you convert the image type to something more performant like .webp or .jpeg and give the element the exact width and height properties.
And react also have a feature to lazy load your images using react.lazy() that can boost your web performance significantly
Handling large images is too much work for a frontend client. You should get these images at a smaller size in order to just show them as they are.
Imagine someone trying to use your application with an old computer, or even an old smartphone, you shouldn't rely on client's processing power to handle all this heavy work.
I hope my answer helps you!
Jpegs are what you should be using, look at functionPreload() as well

Image Preview using File API for images over 100MB will freeze broswer

First, let me note that I've searched and read I think all of SE questions regarding this issue and there isn't so far a good answer! (with a working example)So, here is what I'm trying to achieve: a user selects an image in browser and using filereader I'll generate a preview before uploading. The problem is with large files, over 50MB or 100MB images which freeze the broswer
I've been trying dozens of solutions but all seem to freeze the UI of the browser. In order to generate a good quality preview, I'm using filereader and canvas with some interpolation to scale down the image.
What I noticed is that the freeze happens when the scale down and interpolation happens and during canvas.toDataURL("image/png"); call
Is there a way to avoid this (maybe using web workers?) from happening? As I said, I tried some libraries and read most of the stack questions but the ones that relate to this problem do not have an answer.
I've come across these two issues:
the readAsDataURL will return a base64 encoded and extremely long
line for over 50MB/100MB images (the base64 is 137% larger than the file
size so this is kept in system memory) - so this might be a performance issue
when loading a large image from canvas.toDataURL(), the whole page freezes while the image is being loaded
If there is someone who did this and works well and can provide some examples and explain, it would be awesome.
Mozilla gives an example here how to use readAsDataURL. I try with a 50MB image and works perfectly ( for creating the image i use ImageJ 10000*10000 pixel random value RGB ). I think toDataURL() function create a very long String which become unreadable by the browser.

Choose file, set image and upload without blocking UI

Problem
I can successfully achieve the following steps, but the UI can become unresponsive for files of 2 MB or more. These files are in the size range of what a user might upload from their camera or desktop, so I will need to handle them.
User uploads file using the standard file input HTML element:
<input class="cancel" type="file" name="userFile" id="userFile" accept="image/*"/>
On the client side I resize the file so that the width is 500px or less (specifically to reduce the image size for large files) and show the image.
On the client side I upload the resized smaller file.
Demo
See this fiddle.
There you can see that the - stops moving when uploading larger files. The delay seems more significant in Chrome than Firefox, but it still noticeable on Firefox.
Cause of blocking
When the file data URL is set on the img src. This is needed so that the image can be resized in the canvas.
img.src = e.target.result;//blocking here
When the img is written to the canvas. This is needed to resize the image.
ctx.drawImage( img, 0, 0, width, height );//blocking here
Options I have considered
Doing the blocking actions in a Web Worker. This is not possible because Web Workers cannot manipulate DOM elements and the blocking calls both occur when manipulating the DOM.
Resizing the raw image data in a Web Worker. Unfortunately, I don't know what the format of the img will be so resizing will need to handle all image types. I am not aware of any JavaScript library that will do this and I don't particularly want to write my own cross-format image compression library.
Resizing the img directly, but this does not change the underlying data size that needs to be uploaded.
Doing the resizing on the server is not an option because I want to reduce the upload size. Resizing on the client is also better since the memory for the large image is released early and the resized image is displayed immediately.
Other thoughts
I know that setting the img src is async, so I guess that it is the copying of the data that is causing the blocking. I wonder if there is a way to share the same data rather than doing a copy?
I am using what I believe to be a standard approach of using FileReader to get a data URL, then set the data URL to an img.src and canvas.drawImage to resize (there are many examples of this, one being here). Any assistance in improving the responsiveness of this approach or another approach would be appreciated.
What I assume you are trying to do is the following
User uploads image
The client displays a reduced quality image to the user.
The client then uploads that reduced quality image to your server for later use.
The problem you are running into is you are forcing javascript (the client) to do things that the would most likely be best done on the server side. As for displaying the image at a lower resolution that can be easily attained by using drawImage. There is no reason to display to the user the actual reduced file immediately on the client side. Here is my version of your use flow.
User uploads image.
Client uploads it to a server while displaying a reduced resolution version using drawImage.
The server runs a script much like this one resizing it to the requested size.
Then when the image needs to be used in the future the server coughs up the resized version.
I hope this helps!!!

dynamically generating multiple thumbnails from a video src with javascript

Before you say it can't be done please take a look at my train of thought and entertain me.
I have read on stackoverflow that it can't be done and how to implement this using ffmpeg and other stuff on the server side which is great and simpleish enough to comprehend .. ive even used an extensiion to Video.js i found on github that makes this one step easier. But none the less what if I dont have a copy of the <video src=... > and I really dont care to get one?
I Do not want to use a server to do this Okay with that out of the way, I understand thanks to a post from Paul Irish that video playback is not a shared aspect of web-kit ports (the code which powers basically every browser ... minus chrome canary now using blink a webkit fork) This kinda makes sense why certain browsers only support certain video containers.
So for the sake of simplicity: I want to make this functionality only available on Chrome and only MPEG-4 AVC video containers, why can't this be done if some how I can actually view each frame of the video while its playedback?
additional note
So the generating of video thumbnails is possible using by drawing frames to a canvas, this will only be part of a final solution to my problem, I'm looking to do this each and everytime a video is viewed not store images on my server after a first playback is completed by a user. What I would like to eventually work up to is generating a thumbnail as the video is downloaded that can be viewed while a user uses a dragging scrollbar to ff/rw to a point in the video. So this will need to be done as frames of video come available, not once they have been rendered by the browser for user to view
One can actually feed in a video to the canvas, as seen here in HTML5Doctor. Basically, the line that does the magic is:
canvasContext.drawImage(videoElement,0,0,width,height);
Then you can run a timer that periodically retrieves the frames from the canvas. There are 2 options on this one
get raw pixel data
get the base64 encoded data
As for saving, send the data to the server to reconstruct an image using that data, and save to disk. I also suggest you size your canvas and video to the size you want your screenshots to be since the video-canvas transfer automatically manages scaling.
Of course, this is limited by the video formats that are supported by the browser. As well as support for canvas and video.
Generating thumbnails during first render? You'd run into problems with that since:
You can't generate all frames unless it's rendered on the video element.
Suppose you have generated thumbnails during first run and want to use them for further runs. Base64 data is very long, usually 3 times the file size if the image. Raw pixel data array is width x height x 4 in length. The most viable storage candidate is localStorage, which is just 5-10MB depending on the browser.
No way to cache the images generated into the browser cache (there could be a cache hack that I don't know using data-urls).
I suggest you do it on the server instead. It's too much burden and hassle to do in the client side.

Bicubic-ly Resize Images with Javascript

Is there a way to resize the actual image using JavaScript? I'm not talking about modifying the DOM to get the browser to resize the image. I actually want to resize the image's pixel data and then display that.
Basically my problem is: Firefox completely fails at downsizing images with delicate features because it only has Nearest Neighbor and Binlinear. Every other browser -- even IE -- has Bicubic support. There's talk of this being included in the near future but that talk has been going on for over a year.
I don't mind downloading the full sized images because I want them downloaded anyway. When the user hovers over the small version of an image, the large version immediately appears elsewhere on the page. If I did server-side resizing I'd have to download BOTH copies of the images which would result in even more traffic. If there's no other workaround then this is what I'm going to have to do... I just don't want to.
It is possible. You get a image on the same domain, write to canvas, then manipulate pixel data from there (complicated, but possible I'm sure), and then either use that or output as png/gif/jpg... BUT... I don't think you will find it will better way to preserve delicate features that CSS.

Categories

Resources