PDFJS to fixed width with higher resolution/image quality - pdf.js

I'm looking to use PDFJS to embed PDFs into a webpage. I'd like to render them into a fixed-width canvas (and have them scaled appropriately so they fit into the canvas), while having similar resolution/image quality as the original PDF.
If I use a viewport generated like this:
var viewport =
page.getViewport(page.getViewport(canvas.width/page.getViewport(1.0).width);
I get very low-quality image rendering for small-ish canvases. Is there a way to specify both the scale at which a PDF should be rendered and a suggestion for resolution/image quality?
I'm assuming some method of using/resizing a wrapper div may be the solution, but my attempts thus far have not been successful in scaling the contents of the canvas.
(Also, I know this is related to this other post, but that post doesn't mention a way to specify a higher quality pdf rendering for small canvases).

Related

Is there a way to compress a pdf made with pdfkit?

I’m using pdfkit to create multi-page documents with embedded images, and the files get really large quickly. I can compress them nicely afterwards using Preview on the Mac, and they still look great, so I’m wondering if there is perhaps a setting I’m missing in pdfkit that controls resolution or size, or if there is way to compress them after creating them.
No, there isn't a way of specifying the image compression using PDFKit. It's just putting the image data in a PDF wrapper.
I'd suggest that you probably don't want to reduce the size of the image; but just the compression level. However, if you do, you can use CGPDFDocument and scale the image to fit a particular-sized graphic context.
On macOS, it is possible to create a Quartz Filter programmatically, which can include options for compression, which you can then apply in the options when you write your PDF; but this isn't available in iOS.
(If you're using macOS's 'Reduce File Size' Quartz Filter when exporting from Preview, it's well-known to be not very good; many people have made better ones.)
However, you can set the JPEG compression level in a UIImage object, so you may be able to increase the compression in the image data before you convert it to PDF.
https://developer.apple.com/documentation/uikit/uiimage/1624115-jpegdata/

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.

Any way to restrict the full resolution image from being served up with Imageprocessor in Umbraco?

I'm working on a photography website in which full resolution photos can be uploaded but full-res should not be able to be displayed/accessed (download of the full res will take place through a token.)
I've tried the "restrictTo" setting but resolutions need to not be reliant on specified dimensions.
Is there a way to have myphoto.jpg by default without a querystring display at for example 700x700 yet still have the full resolution file available through a token download? Pretty much, an image without a querystring is still processed by Imageprocessor but with a default resize rule.
I can request an image with a native width of 5000px by myphoto.jpg?width=1400 but the resulting image is the full 5000px width image, why doesn't the max width 1400px image serve up?
If you are getting the full image back it means something has gone wrong. (You've probably ran out of contiguous memory) so make sure you're in 64bit mode.
maxWidth restricts the resize param to an upper limit only. So does nothing on it's own.
What you are probably looking for is the ValidatingRequest event
http://imageprocessor.org/imageprocessor-web/imageprocessingmodule/#events
I would first set ImageProcessor.Web to intercept all image requests in the processing.config file by changing the interceptAllRequests property. That will ensure you capture any attempts to view the image without a token.
In the event you can cancel the request and also alter/add any querystring parameters to limit your size transparently without showing the querystring to the end user.
I would use a query string for the image.
url?width=1400&height=900&mode=crop&anchor=center
I would also use a lazy load so the page loads faster with small blurry images and then afterwards replaces them all with the full res or querystring for max size you want to display at.
I wrote a script for this.
http://www.codeshare.co.uk/blog/lazy-loading-images/
Also on my site now, when I upload an image, I automatically resize it down to 1080p resolution when it saves. So I can upload a massive image and not have to worry about resizing it first or it taking up too much space on my server.
Here's the code for that too
http://www.codeshare.co.uk/blog/automatically-resize-your-media-images-in-umbraco/

Force user to crop/upload an image to a certain size? Preferably using filepicker

I have users uploading images using filepicker, but I want them to have to upload an image of a certain size (and crop if the image is too big). I could cut it myself, but then it won't look good. Ideally, the user would crop it themselves.
I've tried this page: https://www.filepicker.com/documentation/file-ingestion/widgets/pick?v=v2 and I've tried various options but nothing seems to work quite well.
data-fp-image-min doesn't prevent users from uploading smaller images. data-fp-crop-force along with data-fp-crop-max and data-fp-crop-min doesn't do the trick either.
I'm open to using other image uploading libraries, but I like using filepicker. Seems like this is something other people would have run into.
I'm using rails btw.
From the docs:
data-fp-image-min - Images smaller than the specified dimensions will be upscaled to the minimum size.
So it doesn't really prevent users from uploading smaller images.
data-fp-crop-max and data-fp-crop-min specifies the maximum and minimum dimensions of the crop area so it won't give you specific dimensions.
I would recommend you to:
Set data-fp-crop-ratio - Specify the crop area height to width ratio. User will be able to adjust the crop area for each photo with desired ratio.
Set data-fp-crop-force="true" - User could not skip cropping image.
Then resize image to specific height or width.
This will result, you will always get the image with the desired dimensions.
Example for 150 x 200 image output:
Html widget:
<input type="filepicker"
data-fp-crop-ratio="3/4"
data-fp-crop-force="true"
mimetype="image/*"
onchange="window.upload(event)"
data-fp-apikey="APUGwDkkSvqNr9Y3KD4tAz" />
Javascript:
window.upload = function(event){
console.log(JSON.stringify(event.fpfile));
var listElem = document.createElement("li");
var image = document.createElement("img");
/*
set w=150 (width) conversion option
so all images would be 150x200
and crop_first option to make sure the image is cropped
before any other conversion parameters are executed.
*/
image.setAttribute('src', event.fpfile.url + '&w=150&crop_first=true');
listElem.appendChild(image);
document.getElementById('results').appendChild(listElem);
};
Here is working solution: http://jsfiddle.net/krystiangw/9o9ebddL/

Blurry Images when rendering to PDF using UIKit/Coregraphics

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).

Resources