Blurry Images when rendering to PDF using UIKit/Coregraphics - ios

Everything seems pretty standard I downloaded PDF GENERATION SAMPLE and used my own assets at normal resolutions and my images look a little off.
Here's the asset
Here's what it looks like in app
And this is what it looks like in the PDF at 100% zoom
The code in the drawImage function is as simple as it gets
UIImage * demoImage = [UIImage imageNamed:#"icon_map_project.png"];
[demoImage drawInRect:CGRectMake( (pageSize.width - demoImage.size.width)/2,
350,
demoImage.size.width,
demoImage.size.height)];
Nothing fancy at all. I do admit that my familiarity with the details of how PDF work, DPI, and things like that are beyond me at this point.
I've looked at LibHaru and think it's a great system but I'd rather keep this within the confines of UIKit/CoreGraphics.
You'll notice a strange jaggedness on the right side, even shrinking the image down by 50% doesn't seem to help.
Here's a zoomed up image using Digital Color Meter with the PDF at 100% and then the app
As you can see the image simply does not render correctly into the PDF and I'm struggling to find a solution for this.
Thanks for any advice.

You draw the image in the PDF in a rectangle that matches the image size. This results in a 72dpi for the image. Because the viewer application use 96dpi or a higher value as reference for 100% zoom, when the file is displayed at 100% your image will be rendered 100% * 96/72 scale. If you enlarge the bitmap at that scale with an imaging tool you'll see a similar jaggedness. The solution is to use a larger image drawn in a 37x36pt rectangle so that the resulting image dpi is higher.
If you zoom your PDF file to 75% the image size displayed on the page should match the image size in your application (this assumption is based on a 96 dpi screen).

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.

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 image quality improvement

Icons Are Pretty Right?
I'm working on an UI update in an iOS app, and trying to make things look a bit better with some new icons- but I seem to be incapable of determining how to save an image correctly so that it looks good in the interface!
As you can see from this image, if I include a white background with the image it looks great. If I take those same images and use an alpha background they look terrible! It appears that either the images aren't using the #2x correctly, or something else is going horribly wrong.
These images are either saved with GIMP as a png with alpha, or exported from inkscape, the originals are vector graphics. We get the same results from both avenues. I am using both a base imageName.png and imageName#2x.png for scaling.
Somehow, magically, I changed the a single image to greyscale in gimp, and changed the base size to 25px and it showed up with alpha correctly blended. Stock images from apple are also functioning correctly, so it absolutely seems to be something that I'm doing incorrectly when I'm saving the images.
The Setup in XCode
Basic Questions
Is there a certain bit depth, argb vs rgba format, or some other quirk that I need to know to get these images to show up correctly? Is there any way to verify that the program is loading the correct imageName#2x vs imageName? Is there some document that talks about integrated graphics (the iconography documentation isn't very helpful on technical details)
Actual Images
With Background:
Without Background:
I think you will find success if you just save the image at 4x the size you actually want and specify the size manually.

Bigger size image in smaller image view

This is more sort of a logical question, everything is working fine.
I have an ImageView and for that I download images from the web server. Our web server keeps the biggest size image and then I am rescaling the images down for required devices. So lets say, if I have an UIImageView with size 200 * 200 and I am downloading image of 400 * 400, I rescale the image to 200 * 200 and then I put it in the imageview, I tried putting 400 by 400 image in 200 by 200 image view and it looks fine to me (no pixelation). The way I implemented the downscaling is
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
within the image context. Now I feel like apple might be doing this anyway because it is rescaling my image to fit in the image view, so is it really required? Or should I just put high resolution images directly in the image view?
Suggestions required.
You should be fine to just assign a 400x400 UIImage to a 200x200 UIImageView. CoreAnimation will deal with the image scaling underneath.
Image Quality
If you want to experiment with different image scaling qualities, you can set the minificationFilter on the UIImageView's layer. The default is kCAFilterLinear, which I think would be fine for your usage. Multiple pixels from the 400x400 image will be selected and linearly blended together to get the 200x200 image pixel color. kCAFilterNearest will get you better performance at the cost of image quality (a single pixel from the 400x400 image is selected to get the color for the 200x200 image pixel).
You could experiment using kCAFilterTrilinear instead, which should get you better image quality at the cost of some performance. The documentation doesn't make it clear which devices this will actually have an affect, although this guy's had success using it on an iPad 2 which makes me think it may be supported on all devices now. The documentation also notes your image may need to be of dimensions of a power of 2 for this to have affect.
Performance
You could scale the image down from 200x200 perhaps as a performance optimization to save memory and CoreAnimation render time (including the image scaling), but I wouldn't do that unless you have reason to think your app's performance would actually benefit from this.

How to get rid of empty transparent areas in a PNG image so that it conforms to actual image size?

I have a series of images that I would look to loop through using iOS's [UIView startAnimating]. My trouble is that, when I exported the images, they all came standard in a 240x160 size, although only 50x50 contains the actual image, the rest being transparent parts that are just taking up space.
When I set the frame of the image automatically using image.size.width and image.size.height, iOS takes into images' original size of 240x160, so I am unable to get a frame that conforms to the actual parts of the image. I was wondering if there is a way using Illustrator or Photoshop, or any other graphics editing software for me to export the images based on their natural dimensions, and not a fixed dimension. Thanks!
I am a fan of vector graphics and thinks everything in the world should be vector ;-) so here is what you do in illustrator: file - document setup - edit artboards. Then click on the image, and the artboard should adjust to the exact size. You can of course have multiple artboards, or simply operate with one artboard and however-many images.

Resources