How to fix Lighthouse “Serves images with low resolution” - lighthouse

One of the recommendations I get when I audit my website using https://web.dev/measure, is "Serves images in low resolution".
As you can see from the screenshot below, my displayed image size matches the actual size. I don't know what's wrong here and what's the expected size.
If I made the images larger, I get an opposite error saying that my images are not properly sized and should reduce the size.
All these images have an explicit height of 48px and width: auto; to make it responsive.
Any suggestions to fix this issue?
Thanks in advance.

This error is stating that web.dev would have expected you to serve a 96x96 pixel image instead of the 48x48 pixel image. Given that this expected size is 2x the served size, my guess is that web.dev is expecting a scaled up version of the image for a device with a Device Pixel Ratio (DPR) of 2. web.dev performs a series of checks for responsive images (checking for both DPR 1 and DPR 2 devices), so serving only one size will always lead to this error of either images too large or images too small.
Using srcset in your image tag can resolve this. If you follow the example in the Mozilla docs for providing options for 1x and 2x DPR screens, you should see this error get resolved.
<img src="<48px image source>"
srcset="<48px image source> 1x, <96px image source> 2x" />

The whole thing only happens if the image is at the beginning of the page (visible area without scrolling) - if the image is included later (so that you have to scroll) the "error message" does not appear

Related

Resize image programatically to get the same result as a browser

In my web application, I need to resize pictures to avoid loading really big files when I'm only displaying avatars or previews.
I'm using imagemagick to do the resize, but the result is always blurry. I tried a lot of command options (scale/resize/thumbnail, adding filters, changing color spaces, changing quality/density/sharpness, ...) but I never had a good result.
But when I try to display the big file in the browser and let the browser do the resize, the picture is displayed correctly, without any blur.
Here is a little test I did :
I downloaded this picture https://www.normandie-tourisme.fr/wp-content/uploads/2020/01/8118-Mont-Saint-Michel-couleur-dautomne-%C2%A9-DaLiu-Shutterstock.com-%C2%A9-DaLiu-Shutterstock.com_.jpg, renamed it st_michel.jpg and created a resized version with convert st_michel.jpg -resize 200x resize_st_michel.jpg
After that, I created a html file to display both:
<!DOCTYPE html>
<html>
<body>
<div style="display: flex">
<img src="st_michel.jpg" width=200>
<img src="resize_st_michel.jpg" width=200>
</div>
</body>
</html>
And here's the result :
As we can see, the right version (the version resized by imagemagick) is way more blurry than the browser-resized version (and I have the same results with any picture uploaded by the users of my web app).
So my question is : Can I have a picture with the same quality than the one resized by the browser using imagemagick ?
Downscaling always blurs things a bit, so you can recover some by sharpening, but text doesn't like it much.
A middle-of-the-road solution is to scale down to 400px which already produces a much smaller file, and leave the final scaling to the browser:
(left to right: full size (280K), 400px (32K), 200px+sharpen (16K)).
This will also let you have something bigger to display on high-definition displays where 200px may be a bit small.
Edit: trying to dig the matter a bit more I tried to grab your picture again but your site seems down, so I tried with a picture of mine and surprisingly the blurriness doesn't happen, I would even say that the pre-downscaled image is better than the one produced by Firefox from the full-size image (see artifacts along wing edges, and at the wing/fuselage junction):
In all rows, left it the original image (1200x800) resized to 200px, and right is an image obtained by:
convert $image.jpg -filter $f -resize 200x -quality 80 $image-200-$f-Q80.jpg
No filter (Plain) is normally the same as Lanczos. Some blurring with quadratic and cubic is expected.
BTW another reason to not downsize too much is that if someone zooms in on the page the image is rescaled from the larger size (so still scaled down) while if you transfer an image at the exact size for 100% display, zooming in will scale it up and make it blurry.
Edit2: Eventually retrieved the image. I don't see much difference between IM scale and FF scale at 200px with moderate sharpening applied (-sharpen 0x1.0):
However if you look closely (zooming on a screenshot here, so FF isn't rescaling things), the Firefox rescaling creates some weird artifacts:
Edit3: I took the liberty to pay a visit to your site and the blurriness of the thumbnails may have nothing to do with IM. It seems that your thumbnails are resized to something slightly bigger:
Top left is a screenshot of the thumbnail as shown in the page, which appears to be bigger than intended (224x153)
Top right and bottom are the actual image shown in Firefox, at its native size (220x150).
This kind of pernicious minute rescale always creates a lot of blur.
Saving as a png is a bit better and I wonder if it is due to jpg compression. The browser is just resizing the image but Imagemagick is resizing it and saving so introducing some compression?
I also added a bit of sharpening:
magick "E:\Pictures\8118-Mont-Saint-Michel-couleur-dautomne-©-DaLiu-Shutterstock.com-©-DaLiu-Shutterstock.com_.jpg" -resize 200x -unsharp 1.5x1+0.7+0.02 "E:\Pictures\resize_st_michel.png"
I always use png resized images on my website.

How iiifhosting site processing images to up/down scale to make it compatible to iiif?

My question is regarding IIIF. I am using iiifhosting.com but now i want to setup my own server. I want to know how iiifhosting.com processing my images to high resolution?
I have uploaded an image of 2000x1000 and when i get info.json i got width: 11658, height: 6112. Check this url.
http://bafdev.iiifhosting.com/iiif//e6ebb551407a5c64903d100ab8ba9199bb264d1c17cdcf0a9e745cd6c5aea432/info.json
When i try to get full image and save it its just only 1000x524
http://bafdev.iiifhosting.com/iiif//e6ebb551407a5c64903d100ab8ba9199bb264d1c17cdcf0a9e745cd6c5aea432/full/full/0/default.jpg
I want to know how iiifhosting doing this? Any clue?
1- iiifhosting is not upscaling images. It only shows image information which image have. There is no conversion in image to high resolution. In info.json you are getting image info how much width height it has and tiles sizes. Tile sizes formula is (smallest dimension) * 1/2n > endpoint.iiif.min_tile_size
endpoint.iiif.min_tile_size is which you set in cantaloupe.properties file default is 512x512
2- http://bafdev.iiifhosting.com/iiif//e6ebb551407a5c64903d100ab8ba9199bb264d1c17cdcf0a9e745cd6c5aea432/full/full/0/default.jpg
Regarding your second point there is restriction to get full resolution image on iiif hosting so you cant get full image of their client files. Therefore they are serving maximum of 1000x1000 image.
Second thing is if iiifhosting client have 2gb images (very high res) and you request 100 images on your site than it will overwhelm image server.

Xcode #2x image suffix not showing as Retina in iOS

I am having difficulties with retina images.
The screenshot below shows the UICollectionView with a UIImageView contained within each UICollectionViewCell.
Within the app I have a large image 512x512 pixels called travel.png.
The green circle shows what is displayed on the app when I name this file: travel.png. The blue circle shows what I see when I update the image name to be travel#2x.png (i.e. retina naming).
I was hoping due to the large size of the image (512x512) that simply adding the #2x suffix would be enough to convert it to twice the definition (i.e. retina) but as you can see from the two screenshots, both version images show as non-retina.
How can I update the image so that it will display in retina?
travel.png:
travel#2x.png:
* Updated *
Following request in comments below:
I load this image by calling the following function:
// Note - when this method is called: contentMode is set to .scaleAspectFit & imageName is "travel"
public func setImageName(imageName: String, contentMode: ContentMode) {
self.contentMode = contentMode
if let image = UIImage(named: imageName) {
self.image = image
}
}
Here is how the image appears in Xcode before the app renders it (as you can see it is high enough definition):
The reason why you see the low quality image is anti-aliasing. When you provide images bigger then an actual frame of UIImageView (scaleAspectFit mode) the system will automatically downscale them. During scaling some anti-aliasing effects can be added at curve shapes. To avoid the effect you should provide the exact image size you want to display on the screen.
To detect if UIImageView autoscale the image you can switch on Debug->Color Misaligned Images at Simulator menu:
Now all scaled images will highlight at simulator with yellow color. Each highlighted image may have anti-aliasing artifacts and affect CPU usage for scaling algorithms:
To resolve the issue you should use exact sizes. So the system will use them directly without any additional calculations. For example, if your button have 80x80px size you should add three images to assert catalog with following sizes and dpi: 80x80px (72 dpi), 160x160px (144 dpi) and 240x240px (216 dpi):
Now the image will be drawn at the screen without downscaling with much better visual quality:
If your intention is to have just one image for all the sizes, I would suggest it having under Assets.xcassets. It is easy to create the folder structures and manage media assets here.
Steps
On clicking + icon, you will displayed a list of actions. Choose to create a New folder.
Choosing the new folder that is created, click on the + icon again and click on New Image Set.
Choose the imageset. And choose the attributes inspector.
Select Single Scale, under Scales.
Drag and drop the image.
Rename the image name and folder names as you wish.
Now you can use this image using the image name for all the screen sizes.
TL;DR;
Change the view layer's minificationFilter to .trilinear
imageView.layer.minificationFilter = .trilinear
as illustrated by the device screenshot below
As Anton's answer correctly pointed out, the aliasing effet you observe is caused by the large difference in dimensions between the source image and the image view it's displayed in. Adding the #2x suffix won't change anything if you do not change the dimensions of the source image itself.
That said there is an easy way to improve the situation without resizing the original image: CALayer offers some control over the method used by the graphics back-end to resize images : minificationFilter and magnificationFilter. The first one is relevant in your case since the image size is being reduced. The default value is CALayerContentsFilter.linear, just switch to .trilinear for a much better result (more info on those wikipedia pages). This will require more GPU power (thus battery), especially if you apply it on many images.
You should really consider resizing the images before displaying them, either statically or at run-time (and maybe cache the resized versions). In addition to the bad visual quality, using such large images in quantities in your UI will decrease performance and waste lots of memory, leading to potentially other issues.
I have fixed, #DarshanKunjadiya issue.
Make sure (if you are already using assets):
Make sure images are not un-assigned
Now use images in storyboard or code without extensions. (e.g. "image" NOT "image.png")
If you are not using images from assets, move them to assets.
Demo Projects
Hope it helps.
Let me know of your feedback.
I think images without the #2x and #3x are rendered for devices with low resolutions (like the iphone 4 an 3G).
The solution I think is to always use the .xcassets file or to add the #2x or #3X in the names of your images.
In iOS, content is placed on the screen based on the iOS coordinate system. for displaying an image on a standard resolution system having 1:1 pixel density we should supply image at #1x resolution. for higher resolution displays the pixel density will be a scale factor of 2.0, 3.0 which refers in the iOS system as #2x and #3x respectively. That is high-resolution displays demands images with higher density.
For example, if you want to display an image of size 128x128 in standard resolution. You have to supply the #2x and #3x size image of the same. ie., 256x256 at #2x version and 384x384 image at #3x version.
In the following screenshot, I have supplied an image of size 256x256 for 2x version to display a 128x128 pixel image in iPhone 6s. iPhone 6s render images at #2x size. Using the three version of images such as 1x, 2x and 3x with asset catalogue will resolve your issues. So the iPhone will automatically render the correct sized image automatically with the screen resolution.

button image gets pixelated

I have designed a lock icon in Sketch to add to a button in my application:
I exported it both in pdf and png (2x, 3x) to add to Xcode assets. Problem is when I run the app on iPhone (SE), heavy pixelation can be seen around the edges of the icon:
I've tried both pdf and png formats, but result stays the same. Am I missing any settings that need to be applied for image to look sharp on screen?
Bigger is not necessarily better for a UIButton's image. Try to export your icon in more or less the same size with which it will be used. (Note that this also frees up memory in comparison to a way bigger image).
To adapt to different screens' resolutions, you should provide up to three images (#1x, #2x, #3x). You should read this excellent Apple's documentation on Image Size and Resolution. It explains perfectly how big should the images you provide in Xcode be.
They also have a good explanation on which format you should use according to the purpose of the image.
EDIT:
You can also use vector ressources (.pdf files for instance) that will render perfectly for any resolution. You can read this article about how to implement it in your Xcode project (If you do so, please be careful in the attributes of the asset to check Preserve Vector Data and the Scales to Single Scale, otherwise it may not render well).
It will happen if image sizes are not correct
check the size of images. 1x,2x and 3x sizes are should be as followed
1x = 24x24 px
2x = 48x48 px
3x = 72x72 px
If images size are too big than ImageView then pixelate will happen
Hope this will help you

iOS ideal image resolution

I'm having a real hard time understanding this, but let's say I have an iOS app for both iPad and iPhone and I want to download an image from a server and display it in full screen.
I have read that the iPad pro has a resolution of 2732x2048 and if we want to display an image in fullscreen we would need to download the image with this size right? However, I also read that the image should never be over 300KB. I was not able to bring an image with this size under 2MB (I used JPEGmini for example to reduce size).
And I don't think that iPhone user would need to download such a huge image, so my question is: what resolution should my images be on the server and how can I manage to keep them in a rational file size. Also should I upload multiple images for different devices? If so, how many and at what resolutions?
Isn't the problem merely that you are holding incompatible beliefs? This is the belief that is giving you trouble:
I also read that the image should never be over 300KB.
Let go of it.
Clearly it is right to say that the image should be no larger than needed for display. But an image to be shown as a 3x scale image on the iPad pro needs to be 2732x2048. So that's that.
(You could, alternatively, use an image 2/3 of that size and show it as a 2x scale image. It wouldn't look quite as good as the 3x scale image, but it might be acceptable.)
On a smaller device, yes, you should scale down the image in code, so that you are not holding in memory an image larger than needed for display. But in this case, you need the large image for display.

Resources