Hi, I'm new to pic/groff and I've been having some problems producing
either gif or jpeg images using them. The basic problem seems to be that
pic/groff/postscript all have the concept of a page that they are
drawing on whereas I want the resulting image to have all the whitespace
cropped from the margins. This is to go in a web page so the idea of a
page doesn't make sense.
Anyway I started out following some instructions here:
http://www.spinellis.gr/sw/umlgraph/doc/faq.html#antialias but the
resulting command was very slow. Here are my findings as pasted from my
internal blog. I wondered if they made sense or if I'm missing some
simpler approach to the whole thing (btw I need the gs stage because
using -T gif in groff produces very poor text, no antialiasing).
Thanks!
Dave
From my blog:
I missed the hint in the FAQ and after a bit of messing around got the
following command to work:
pic test | groff | ps2eps | gs -dDEVICEHEIGHTPOINTS=1000 -q -r360
-dNOPAUSE -sDEVICE=pnm -sOutputFile=- - -c quit | pnmcrop | pnmscale 0.5
| ppmtogif > test.gif
I had to add the -dDEVICEHEIGHTPOINTS=1000 option because without that
it chopped off the top of the picture.
Anyway, I think I prefer this approach if only because the pnmscale
command gives me the option to scale the size of the image. Plus
ppmtogif gives me control over transparency.
Posted by D. H. Griffiths on May 04, 2005 at 07:02 AM EDT
I've been playing around with this some more because the command above
was just so slow (eg 17 seconds on my T40 for a trivial diagram). Turns
out that most of that time is spent in pnmcrop. The image is far larger
than it needs to be (as specified by the resolution argument -r360) and
is then shrunk back down again with pnmscale (for my tests I'm using
pnmscale 0.25). Why is that? Well if you use -r90 and get rid of the
pnmscale, the text looks ragged as though it's missing antialiasing. But
I found that you could overcome that by specifying -dTextAlphaBits=4 in
the gs command. So you end up with a command like this:
pic test | groff | ps2eps -q | gs -dTextAlphaBits=4
-dDEVICEHEIGHTPOINTS=1000 -q -r90 -dNOPAUSE -sDEVICE=pnm -sOutputFile=-
- -c quit | pnmcrop | ppmtogif > test.gif
now that's about four times faster because the intermediate pnm image is
four times smaller. This command took about 4 seconds on my Thinkpad.
But I found a still faster way.
Why bother to go to pnm format in the first place, why can't the image
be created directly by ghostscript? Well the answer is that can, but
ghostscript can only produce jpeg images, not gif. Which is fine for me.
The next issue relates to the pnmcrop command. What that does is chop
blank space from around your image. The problem is that a lot of what
groff and postscript do revolves round the concept of writing to a page
(typically letter size). Pic for instance has its coordinate origin at
the bottom left but positions your image at the top of the page. If you
play around you run into all sorts of issues with the image having white
space above or below or the image top gets chopped off because it's
above the top of the imaginary page and so on. After a lot of messing
around I came up with this version of the command:
pic test | groff | ps2eps -q -g | fixbox | gs -dTextAlphaBits=4 -q
-r90 -dNOPAUSE -sDEVICE=jpeg -sOutputFile=- - -c quit > test.jpg
the -g option to ps2eps is important because that tells it to use the
"internal bbox device of ghostscript" (whatever that means!), but anyway
it prevents ps2eps from setting the top of the bounding box to the top
of the default page. It's important because without it the diagram goes
above the bounding box set by ps2eps and the image gets cropped.
fixbox is a small python script I wrote that is a much simplified
version of epstopdf. What this does is to move the image to the bottom
left corner and set the page size to just include the bounding box.
Using this means that there is no longer a need for cropping. The script
is here:
#!/usr/bin/python
# This script converts the BoundingBox of a postscript file so that the
origin is at
# the bottom left corner (0, 0). It also sets the pagesize which avoids
the need for
# cropping blank space from the image.
import sys
import os
import re
inlines = sys.stdin.readlines()
for line in inlines:
if line.find("%%BoundingBox: ") != -1:
tokens = line.split()
minx = int(tokens[1])
miny = int(tokens[2])
maxx = int(tokens[3])
maxy = int(tokens[4])
new_maxx = maxx - minx
new_maxy = maxy - miny
print "%%BoundingBox: 0 0 " + str(new_maxx) + " " + str(new_maxy)
print "<< /PageSize [" + str(new_maxx + 10) + " " + str(new_maxy
+ 10) + "] >> setpagedevice"
print "gsave -" + str(minx) + " -" + str(miny - 1) + " translate"
else:
print line,
print "grestore"
And finally, the best news is that this takes just 1 second to run!
_______________________________________________
Groff mailing list
address@hidden
http://lists.gnu.org/mailman/listinfo/groff