ImageMagick convert from pdf to image shrinks image and places it in bottom left corner - imagemagick

I am using this command to convert pages from a pdf to jpeg images:
magick convert -density 300 sample.pdf output.jpeg
I see a white background and the content of the PDF appears as a smaller image stuck to the bottom left corner of the white "canvas". Can anyone help with why this might be happening and how to prevent this "shrinking"?
My PDF has 14 pages. Here is the metadata for a few of those pages:
>magick identify sample.pdf
sample.pdf[0] PDF 2286x3600 2286x3600+0+0 16-bit sRGB 6458B 0.016u 0:00.017
sample.pdf[1] PDF 2286x3600 2286x3600+0+0 16-bit sRGB 6018B 0.016u 0:00.020
sample.pdf[2] PDF 2286x3600 2286x3600+0+0 16-bit sRGB 5732B 0.016u 0:00.023
And here are the actual and expected outputs for one of the pages:
actual output:
expected output:
edit: here is a sample PDF:
https://www.dropbox.com/s/0bzu5brfzbedd7i/sample.pdf?dl=0

I am not sure why you have that behavior. There is something in the PDF, perhaps a crop box, that Imagemagick/Ghostscript is not picking up. But you can get rid of the excess white using -trim
magick sample.pdf -trim sample_%d.jpg

Thanks for the example
> magick identify sample.pdf
> sample.pdf[0] PDF 2286x3600
Apears to be wrong as there is no match
from the PDF contents
/Width 1531
/Im0
/Height 2454
/MediaBox [0 0 1531 2454]
on
Page Size:
/CropBox [0 0 919 1473]
919 pt x 1473 pt
32.42 x 51.96 cm
12.76 x 20.45 inches
Therefore no problems when the images were inserted as # 120 dpi
We can check the image by copy when zoom to 100% in a viewer and paste into say paint, which agrees the image is 1531 x 2454 pixels.
As a result of comments with #fmw42, it was decided to see if GhostScript (which ImageMagick depends on for PDF handling) was having an affect, and certainly processing that PDF using GS v 9.55 without any special switches gave warnings and produced the output below left So the issue seems to be caused by recent GhostScript method of calling/scaling. since using simple GhostScript based image apps (Irfanview using GS plugin on the left) behave the same whilst other viewers have less of a problem even sister product MuPDF as previewed on the right. So the file Media Box as seen and probably used for scaling by Ghostscript seems to be the culprit, but was processed by two other PDF handlers during generation.
One solution would be to use a simpler method of extracting images as PNG thus look at Xpdf command line tools "pdftopng" which gives a good result but you need to calculate that the optimum resolution in this case is 120 (or 240), Typical windows command line does not need .exe but its best to use that when prefixing with a path for use from another location.
pdftopng.exe -r 120 -f 1 -l 1 sample.pdf

Related

Overlaying multiple PNG images of different sizes on a canvas using ImageMagick

I want to overlay multiple PNG images of different sizes on a transparent canvas using ImageMagick. First I create a transparent canvas of some fixed size, say like
convert -size 1500x1000 canvas:transparent PNG32:canvas.png
Then I loop over my images in order to add each image to the canvas
convert canvas.png nthimage.png -gravity Center -geometry xResxYres+xcoord+ycoord -composite canvas.png
This works fine, but I may overlay as many as 10 pictures and I do this for thousands of n-tuples of images, so a faster solution would be appreciated. So my question: Can I also do this in one step instead of creating the canvas first and then adding a single image at a time?
Edit: I use ImageMagick 7.0.11-13 on macOS 10.15.7. I run ImageMagick from within a python script, so a file containing a list of input files can be generated if needed. For concreteness, say my input files are file_1.png up to file_n.png with sizes A1xB1 up to AnxBn and should be placed at coordinates +X1+Y1 up to +Xn+Yn with respect to the center of the canvas and the output file is output.png and should have size 1500x1000.
I really wouldn't recommend shelling out subprocesses from Python to call ImageMagick thousands of times. You'll just end up including too much process creation overhead per image, which is pointless if you are already running Python which can do the image processing "in house".
I would suggest you use PIL, or OpenCV directly from Python, and as your Mac is certainly multi-core, I would suggest you use multi-processing too since the task of doing thousands of images is trivially parallelisable.
As you haven't really given any indication of what your tuples actually look like, nor how to determine the output filename, I can only point you to methods 7 & 8 in this answer.
Your processing function for each image will want to create a new transparent image then open and paste other images with:
from PIL import Image
canvas = Image.new('RGBA', SOMETHING)
for overlay in overlays:
im = Image.open(overlay)
canvas.paste(im, (SOMEWHERE))
canvas.save(something)
Documentation here.

With ImageMagick, how can a JPEG image be reduced in quality until it is below a certain file size?

A JPEG image can be reduced in quality and, thus, in file size using ImageMagick in a way such as the following:
convert -quality 85% image.jpg image_small.jpg
How can the quality of an image be reduced such that the resulting image is below a certain file size (e.g. 3 MB)? A scenario in which this would be useful would be preparing a large number of images for upload to a site like Imgur.
I thought there was a post about this last week but can not find it. There was another here: ImageMagick: scale JPEG image with a maximum file-size
Anyway you want to use: -define jpeg:extent=400KB https://www.imagemagick.org/script/command-line-options.php#define
Out of interest your code is wrong as the input comes after convert and your quality goes before the output image.
So you want something like this:
convert image.jpg -define jpeg:extent=3000KB image_small.jpg
If you have an old version of Imagemagick it may not work that is why it is always good to include your imagemagick version in your question.
The results are a bit hit and miss on exact filesize.

Any way to batch resize png's canvas size keeping the image top left, but making the size divisible by 12

We need to have huge amounts of png's resized to be divisible by 12, each png is variable in size and the image needs to stay 1:1 in the top left.
At the moment were having to manually bring in each file into Photoshop and enlarge the canvas on the x+y to be divisible by 12 and keep the image in the top left corner. With the amount of png's we need doing now and in future we need an automated process.
I would do this with ImageMagick, which is free and installed on most Linux distros and also available for OSX and Windows from here.
This little bash script will resize all the PNG files in the current directory and save them with the original name in the subdirectory called output. It is pretty easy to read - it basically loops through all the PNG files in the directory. It then uses ImageMagick's built-in calculator to work out the size of your output file as nearest multiple of 12. Then it loads the image and extends the background using transparent pixels (-background none) to that size (using -extent) and leaves the original image in the top-left corner (-gravity NorthWest).
#!/bin/bash
# Make output directory - ignore errors
mkdir output 2> /dev/null
# Make sure we don't barf if there are no files
shopt -s nullglob
# Make sure we process *.png, *.PNG, *.pNg etc
shopt -s nocaseglob
# Loop through all pngs in current directory
for f in *.png; do
# Calculate new extent as nearest multiple of 12
# In general, to round x to nearest n, you do ((x+n-1)/n)*n
extent=$(convert "$f" -format "%[fx:12*round(((w+11)/12)-0.5)]x%[fx:12*round(((h+11)/12)-0.5)]" info: )
# Now extend canvas transparently to new size and leave original image in top-left
convert "$f" -background none -gravity northwest -extent $extent output/"$f"
done
P.S. If installing ImageMagick on OSX, please ask for advice before trying.
P.P.S. If you have 10,000+ images to resize, and you do it often, and you are on OSX or Linux (probably not Windows), I would recommend GNU Parallel. If that is likely, please ask.
Never mind, this is a possible solution for your problem. This script will run in MATLAB or Octave (Octave is an open-source alternative to MATLAB, so you might want to use that.)
Copy the following function into a file and call it resizeIm.m. Then start Octave and call this function for every image you have.
function resizeIm(fileName)
% Read image
origIm = imread(fileName);
% Get size and calculate new size
origSize = size(origIm);
div = ceil(origSize ./ 12);
% Create new, padded image
newIm = zeros(12*div,class(origIm));
newIm(1:origSize(1),1:origSize(2)) = origIm;
% Write image to new file
[dir, name, ext] = fileparts(fileName);
newFileName = [dir,name,"_resized",ext];
imwrite(newIm,newFileName);
end
The function can be called by
resizeIm("C:\path\to\file\myimage.png")

Converting a multi page pdf to multiple pages using a single command

I want to convert multi page pdfs into single page images efficiently.
I already know how to do this one page at a time with imagemagick. For example,
convert x.pdf[2] x3.jpg
will give me the 3rd page of the pdf as an image. So if I figure out how many pages are in the pdf using identify then I can loop through and convert all pages in the pdf to images. This method can however take a while. For example a 15 page pdf could take anywhere between 15-30 seconds.
According to answers that I have seen elsewhere (also on the imagemagick forums) the following imagemagick command should split a pdf into multiple images.
convert x.pdf x-%0d.jpg
but all this ends up doing is creating the first page named x-0.jpg
As an alternative I have tried using pdftk with the burst capability. The problem I faced there is that burst does not work in all cases. It does for some pdf's and does not for some others.
Any suggestions on how to improve things would help.
My OS is Mac OSX Lion but I do need this working on CentOS 6 as well.
You're missing the quantity of digits. Use:
convert x.pdf x-%04d.jpg
Where 4 means 4 digits will be show on the page count.
If you use Graphicsmagick on Debian or ImageMagick on macOS you probably have to add ADJOIN to your command.
So it should look like
convert x.pdf +adjoin x-%04d.jpg
When I tried to convert my multi-page pdf, the resulting image files had a gray background despite the pdf having a white background. (#John P commented on it on the accepted answer, but I couldn't get his comment to directly work for me.)
Here's what worked for me to make the background white:
convert -authenticate yourpassword -background white -alpha remove -alpha off -density 300 -quality 80 -verbose "Your file.pdf" "Your file.png"
My pdf had a password hence the authenticate.
You can see a summary of the options here:
-authenticate value decipher image with this password
-background color background color
-alpha on, activate, off, deactivate, set, opaque, copy", transparent, extract, background, or shape the alpha channel
-density geometry horizontal and vertical density of the image
-quality value JPEG/MIFF/PNG compression level
-verbose print detailed information about the image
More detail: https://imagemagick.org/script/convert.php
And the alpha remove option: http://www.imagemagick.org/Usage/masking/#alpha_remove
Ran into the same issue. Reinstall Imagemagick to work in Mountain Lion. If you use brew the simply
$brew unlink imagemagick
$brew install imagemagick

Taking a Screen Shot of an Embedded Linux Framebuffer

I'm running Embedded Linux on an evaluation kit (Zoom OMAP35x Torpedo Development Kit). The board has an LCD and I would like to be able to take screen shots convert them into a gif or png. I can get the raw data by doing the following: "cp /dev/fb0 screen.raw", but I am stumped on how to convert the image into a gif or png format.
I played around with convert from ImageMagick (example: "convert -depth 8 -size 240x320 rgb:./screen.raw -swap 0,2 -separate -combine screen.png"), but have been unable to get an image that looks right.
Does anyone know of any other tools that I could try out? Or does anyone have tips for using ImageMagick?
Take a look at fbgrab, an application that does just that (it saves the framebuffer content as a png).
You can simply capture the framebuffer to a file and open it in any raw image viewer or try online eg: https://rawpixels.net/
cat /dev/fb0 > fbdump
It might not be possible / easy to do it directly with ImageMagick.
The Linux kernel 4.2 documentation https://github.com/torvalds/linux/blob/v4.2/Documentation/fb/api.txt#45 says:
Pixels are stored in memory in hardware-dependent formats. Applications need
to be aware of the pixel storage format in order to write image data to the
frame buffer memory in the format expected by the hardware.
Formats are described by frame buffer types and visuals. Some visuals require
additional information, which are stored in the variable screen information
bits_per_pixel, grayscale, red, green, blue and transp fields.
Visuals describe how color information is encoded and assembled to create
macropixels. Types describe how macropixels are stored in memory. The following types and visuals are supported.
A list of visuals and types follows, but the description is not enough for me to understand the exact formats immediately.
But it seems likely that it might not be a format that ImageMagick will understand directly, or at least you'd have to find out the used format to decide the ImageMagick options.

Resources