Saturday, February 09, 2013

How to convert(1) foo.pdf to bar.png with high resolution

Short version:use convert -density 300x300

I'm an occasional (→non-expert) user of the ImageMagick's marvelous convert program. Today I wanted to convert a nice PDF file to a high-resolution (300dpi, say) PNG file for some editing.

But I was having trouble with it; saying
convert foo.pdf bar.png
resulted in a 72dpi image. What to do? I wondered. Perhaps the help would be useful?

collin@p3:~> convert --help|grep -i resol
  -units type          the units of image resolution
  -resample geometry   change the resolution of an image
collin@p3:~> convert --help|grep -i size
  -page geometry       size and location of an image canvas (setting)
  -pointsize value     font point size
  -size geometry       width and height of image
  -adaptive-resize geometry
                       adaptively resize image using 'mesh' interpolation
  -extent geometry     set the image size
  -geometry geometry   preferred size or location of the image
  -repage geometry     size and location of an image canvas
  -resize geometry     resize the image
collin@p3:~> convert --help|grep -i dots
collin@p3:~> convert --help|grep -i dpi
collin@p3:~> 
None of those looked promising. I didn't want to change the resolution of the image, or resize the image; I just wanted the pre-existing information to be used! Well, when all else fails, Read The Fine Manual.
convert(1)                                                          convert(1)



NAME
       convert  -  convert  between  image formats as well as resize an image,
       blur, crop, despeckle, dither, draw on, flip, join, re-sample, and much
       more.

SYNOPSIS
       convert [input-options] input-file [output-options] output-file

OVERVIEW
       The  convert  program is a member of the ImageMagick(1) suite of tools.
       Use it to convert between image formats as well  as  resize  an  image,
       blur, crop, despeckle, dither, draw on, flip, join, re-sample, and much
       more.

       For more information about the convert command, point your  browser  to
       file:///usr/share/doc/packages/ImageMagick/www/convert.html          or
       http://www.imagemagick.org/script/convert.php.

Ah-HA! The manual is actually online. So I went to the link and looked for "resolution" -- it pointed me at resample, which I knew I didn't want, but I clicked on it anyway, which got me to http://www.imagemagick.org/script/command-line-options.php#resample, where I did a search for "dpi" (dots per inch). That led me to this entry:
-density width
-density widthxheight
Set the horizontal and vertical resolution of an image for rendering to devices.
This option specifies the image resolution to store while encoding a raster image or the canvas resolution while rendering (reading) vector formats such as Postscript, PDF, WMF, and SVG into a raster image. Image resolution provides the unit of measure to apply when rendering to an output device or raster image. The default unit of measure is in dots per inch (DPI). The -units option may be used to select dots per centimeter instead.

The default resolution is 72 dots per inch, which is equivalent to one point per pixel (Macintosh and Postscript standard).
I see that the image is interpreted as 72x72 dpi during conversion; if I resample after that, the higher-resolution info is already gone. But this "density" thing says we'll read the original image at the specified resolution, and then convert to the output format desired. Following are three commands; in the image on the right are the results.
collin@p3:/tmp> convert foo.pdf bar.png
collin@p3:/tmp> convert foo.pdf -resample 300x300 bar3-resampled.png 
collin@p3:/tmp> convert -density 300x300 foo.pdf bar3.png
The first command is the naive command to convert foo.pdf to bar.png; the top image is a screenshot, magnified, of bar.png. You can see that the image is pretty ugly.

The second command is the result of resampling the interpreted-as-72dpi image. The information was lost when foo.pdf was read (i.e., it was read at 72dpi); we then tried to expand the image to 300dpi. The edges are smoothed, so it doesn't look quite as ugly as the first image—if you don't look too close that is. But still, a lot of information was lost.

The last command retains more information from the original, and in the bottom image you can see how much nicer it looks.

openSUSE 11.3: printer won’t print some PDFs

So I have a PDF file (it's from the social security administration's BSO, but really, it could have been from anywhere). I opened it with okular and told it to print pages 1-3, then pages 5-6. I waited briefly, then started wondering what was wrong.

I ran yast2 and tried to see what was up... the test page printed successfully (my PDF print jobs were still in the queue) so I knew the printer was fine.

I'm embarrassed to tell you that I next rebooted the computer. My excuse is that this machine does have some hardware issues, but that's lame. Of course the print jobs didn't print, and lpq still showed them there...

collin@p3:/mnt/home/collin> lpq
hp is ready
Rank    Owner   Job     File(s)                         Total Size
1st     collin  246     SGV147.pdf                      852992 bytes
2nd     collin  247     SGV147.pdf                      800768 bytes
collin@p3:/mnt/home/collin> 
I wondered if something was fishy about the printer itself. After failing to remember the command "lpc", some web searching reminded me of it, but it didn't have much to say, either.
collin@p3:/mnt/home/collin> lpc status
Absolute path to 'lpc' is '/usr/sbin/lpc', so running it may require superuser privileges (eg. root).
collin@p3:/mnt/home/collin> /usr/sbin/lpc status
hp:
 printer is on device 'socket' speed -1
 queuing is enabled
 printing is enabled
 2 entries
 daemon present
simplex:
 queuing is enabled
 printing is enabled
 no entries
 daemon present
collin@p3:/mnt/home/collin>
Finally (D’oh!) it occurred to me to look at the log file. Which logfile? There's no "cups" or "lp" in /var/log/messages but there is /var/log/cups, whence
collin@p3:/var/log/cups> less error_log
…
E [09/Feb/2013:08:59:17 -0800] [Job 246] Job stopped due to filter errors; please consult the error_log file for details.
D [09/Feb/2013:08:59:17 -0800] [Job 246] The following messages were recorded from 08:59:17 to 08:59:17
…
D [09/Feb/2013:08:59:17 -0800] [Job 246] HWMargins = [ 9.000 9.000 9.000 9.000 ]
D [09/Feb/2013:08:59:17 -0800] [Job 246] Error: /undefinedresult in --stringwidth--
D [09/Feb/2013:08:59:17 -0800] [Job 246] Operand stack:
D [09/Feb/2013:08:59:17 -0800] [Job 246] ()   0   ()
D [09/Feb/2013:08:59:17 -0800] [Job 246] Execution stack:
D [09/Feb/2013:08:59:17 -0800] [Job 246] %interp_exit   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   --nostringval--   --nostringval--   false   1   %stopped_push   1878   1   3   %oparray_pop   1877   1   3   %oparray_pop   1861   1   3   %oparray_pop   1755   1   3   %oparray_pop   --nostringval--   %errorexec_pop   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   --nostringval--
D [09/Feb/2013:08:59:17 -0800] [Job 246] Dictionary stack:
D [09/Feb/2013:08:59:17 -0800] [Job 246] --dict:1172/3371(ro)(G)--   --dict:0/20(G)--   --dict:77/200(L)--   --dict:66/75(L)--   --dict:18/25(L)--   --dict:0/15(L)--   --dict:0/15(L)--   --dict:8/15(L)--
D [09/Feb/2013:08:59:17 -0800] [Job 246] Current allocation mode is local
D [09/Feb/2013:08:59:17 -0800] [Job 246] Last OS error: 2
D [09/Feb/2013:08:59:17 -0800] [Job 246] GPL Ghostscript 8.70: Unrecoverable error, exit code 1
D [09/Feb/2013:08:59:17 -0800] [Job 246] cups_close(0x80ad2dc)
D [09/Feb/2013:08:59:17 -0800] [Job 246] prnt/hpcups/HPCupsFilter.cpp 505: cupsRasterOpen failed, fd = 0
D [09/Feb/2013:08:59:17 -0800] [Job 246] Print file sent, waiting for printer to finish...
D [09/Feb/2013:08:59:17 -0800] [Job 246] Ready to print.
D [09/Feb/2013:08:59:17 -0800] [Job 246] End of messages
D [09/Feb/2013:08:59:17 -0800] [Job 246] printer-state=3(idle)
D [09/Feb/2013:08:59:17 -0800] [Job 246] printer-state-message="Ready to print."
D [09/Feb/2013:08:59:17 -0800] [Job 246] printer-state-reasons=none
Why "Job 246"? Because that was the first print job shown in the "lpq" output above. In case you can't see the messages I marked in boldface above, they were:
  • [Job 246] Job stopped due to filter errors; please consult the error_log file for details.
  • [Job 246] GPL Ghostscript 8.70: Unrecoverable error, exit code 1
That "Execution stack:" message was actually my first clue that it was ghostscript.

So the problem lay with ghostscript, which didn't grok whatever okular was telling it. The upshot was, I printed the file using the mac's Preview program, which knew what to send to the printer (an hp officejet pro L7650, but I don't think it matters).

What if you don't have a consumer operating system and utilities? It turns out that pdf2ps works and produces ghostscript-able postscript, albeit with some ugly-looking messages:

collin@p3:/mnt/home/collin> pdf2ps SVG147.pdf tmp/x.ps

   **** Warning: Invalid 0.0 font scale given for Tf ****

   **** Warning: Invalid 0.0 font scale given for Tf ****

   **** Warning: Invalid 0.0 font scale given for Tf ****

   **** Warning: Invalid 0.0 font scale given for Tf ****

   **** Warning: Invalid 0.0 font scale given for Tf ****

   **** Warning: Invalid 0.0 font scale given for Tf ****

   **** Warning: Invalid 0.0 font scale given for Tf ****

   **** Warning: Invalid 0.0 font scale given for Tf ****

   **** Warning: Invalid 0.0 font scale given for Tf ****

   **** Warning: Invalid 0.0 font scale given for Tf ****

   **** Warning: Invalid 0.0 font scale given for Tf ****

   **** This file had errors that were repaired or ignored.
   **** The file was produced by: 
   **** >>>> iText 2.1.5 (by lowagie.com) <<<<
   **** Please notify the author of the software that produced this
   **** file that it does not conform to Adobe's published PDF
   **** specification.

collin@p3:/mnt/home/collin>
The resulting file (tmp/x.ps in this case) does print; I think it became a sort of bitmapped file.
collin@p3:/mnt/home/collin> ls -o SVG147.pdf tmp/x.ps
-rw-r--r-- 1 collin  309812 2013-02-09 08:54 SVG147.pdf
-rw-r--r-- 1 collin 2014259 2013-02-09 09:46 tmp/x.ps
collin@p3:/mnt/home/collin> 

Tuesday, February 05, 2013

“The reason why we do things so badly…

…is that we are not content to do what we can.”
Merton, No Man Is an Island 7.5 (p. 124)
Merton continues:
We insist on doing what is not asked of us, because we want to taste the success that belongs to somebody else.

We never discover what it is like to make a success of our own work, because we do not want to undertake any work that is merely proportionate to our powers.

Who is willing to be satisfiedd with a job that expresses all his limitations?

Merton, loc. cit.
Or as Paul wrote: “Do not think of yourself more highly than you ought, but rather think of yourself with sober judgment, in accordance with the measure of faith God has given you” (Romans 12:3). And: “If anyone thinks he is something when he is nothing, he deceives himself. Each one should test his own actions. Then he can take pride in himself, without comparing himself to somebody else” (Galatians 6:3f).

Good advice.