From: Michael J G. <mic...@fa...> - 2008-09-09 12:23:05
|
hiresbbox=0 is the default, unchanged behaviour. hiresbbox=1 means that the high resolution bounding box (HiResBoundingBox) is used rather than the normal one (BoundingBox). Signed-off-by: Michael J Gruber <mic...@us...> --- manual/epsfile.tex | 3 ++- pyx/epsfile.py | 23 +++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) Sometimes a 1pt mismatch can make a difference; this match helps with eps inclusion in such cases. The default behaviour is unchanged. Specifying hiresbbox=1 for an eps file which has only an ordinary bbox results in an error, intentionally so: If the user asks for hires she wants hires. This patch is against svn r3000. I don't have commit rights (but an sf account michaeljgruber which may serve as the svn author field). diff --git a/manual/epsfile.tex b/manual/epsfile.tex index db250b4..486fa7a 100644 --- a/manual/epsfile.tex +++ b/manual/epsfile.tex @@ -39,7 +39,8 @@ horizontal alignment: \texttt{l} for left, \texttt{c} for center file? Set to $0$ with care.\\ \texttt{bbox=None} & If given, use \texttt{bbox} instance instead of bounding box of EPS file.\\ -\texttt{kpsearch=0} & Search for file using the kpathsea library. +\texttt{kpsearch=0} & Search for file using the kpathsea library.\\ +\texttt{hiresbbox=0} & Use the high resolution bounding box rather than the normal one. \end{tabularx} diff --git a/pyx/epsfile.py b/pyx/epsfile.py index bb203ac..859f086 100644 --- a/pyx/epsfile.py +++ b/pyx/epsfile.py @@ -138,7 +138,7 @@ class linefilereader: self.file.close() -def _readbbox(filename): +def _readbbox(filename, hiresbbox=0): """returns bounding box of EPS file filename""" file = linefilereader(filename) @@ -147,20 +147,26 @@ def _readbbox(filename): if not file.readline().startswith("%!"): raise IOError("file doesn't start with a '%!' header comment") + if hiresbbox: + bboxmatch = "%%HiResBoundingBox:" + bboxtype = float + else: + bboxmatch = "%%BoundingBox:" + bboxtype = int bboxatend = 0 # parse the header (use the first BoundingBox) while 1: line = file.readline() if not line: break - if line.startswith("%%BoundingBox:") and not bboxatend: + if line.startswith(bboxmatch) and not bboxatend: values = line.split(":", 1)[1].split() if values == ["(atend)"]: bboxatend = 1 else: if len(values) != 4: raise IOError("invalid number of bounding box values") - return bbox.bbox_pt(*map(int, values)) + return bbox.bbox_pt(*map(bboxtype, values)) elif (line.rstrip() == "%%EndComments" or (len(line) >= 2 and line[0] != "%" and line[1] not in string.whitespace)): # implicit end of comments section @@ -214,11 +220,11 @@ def _readbbox(filename): line = True while line: line = file.readline(EOFmsg=None) - if line.startswith("%%BoundingBox:"): + if line.startswith(bboxmatch): values = line.split(":", 1)[1].split() if len(values) != 4: raise IOError("invalid number of bounding box values") - usebbox = bbox.bbox_pt(*map(int, values)) + usebbox = bbox.bbox_pt(*map(bboxtype, values)) if not usebbox: raise IOError("missing bounding box information in document trailer") return usebbox @@ -232,7 +238,7 @@ class epsfile(canvasitem.canvasitem): x, y, filename, width=None, height=None, scale=None, align="bl", clip=1, translatebbox=1, bbox=None, - kpsearch=0): + kpsearch=0, hiresbbox=0): """inserts epsfile Object for an EPS file named filename at position (x,y). Width, height, @@ -241,7 +247,8 @@ class epsfile(canvasitem.canvasitem): translatebbox is not set, the EPS graphics is not translated to the corresponding origin. If bbox is not None, it overrides the bounding box in the epsfile itself. If kpsearch is set then filename is searched - using the kpathsea library. + using the kpathsea library. If hiresbbox is set then the high resolution + bbox is used instead of the normal one. """ self.x_pt = unit.topt(x) @@ -250,7 +257,7 @@ class epsfile(canvasitem.canvasitem): self.filename = pykpathsea.find_file(filename, pykpathsea.kpse_pict_format) else: self.filename = filename - self.mybbox = bbox or _readbbox(self.filename) + self.mybbox = bbox or _readbbox(self.filename, hiresbbox=hiresbbox) # determine scaling in x and y direction self.scalex = self.scaley = scale -- 1.6.0.1.285.g1070 |
From: Alan G I. <ai...@am...> - 2008-09-09 13:48:40
|
Here is a simple test. Run the following Python script import pyx pyx.unit.set(defaultunit='pt') c = pyx.canvas.canvas() c.insert(pyx.epsfile.epsfile(0, 0, "eg.eps")) c.writeEPSfile('pyxout.eps') where eg.eps is below. Should get a bounding box of 0 0 100 100. Right now (revision 3000) it is off by 1 in every direction. One comment: this is actually a big deal, for graphics headed for publication. Good behavior should be the default, imo. I did not fully understand the linewidth argument: when I give you a bounding box, that's it! Everything outside is clipped. I cannot have a 1 point "halo" around the figure. My usage is generally to import and EPS file and then do things **inside** the bounding box. (E.g., add text or perhaps a JPEG in some cases.) In this case, I guess it would be nice to be able to just say explicitly, "set the bounding box based on the bounding box from that EPS file, unless I explicitly change it". This might be generally useful? Alan Isaac %!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 100 100 %%HiResBoundingBox: 0 0 100 100 %%Title: eg.eps %%CreationDate: Mon Sep 08 22:10:39 2008 %%Pages: 1 %%EndComments %%Page: 1 1 %%BeginDocument: eg.eps /bmargin 0 def /lmargin 0 def /width 100 def /height 100 def %draw a border completely inside bounding box /lwh 4 def %half line width /lwf lwh 2 mul def %full line width lwf setlinewidth lmargin lwh add bmargin lwh add width lwf sub height lwf sub rectstroke %%EndDocument %%Trailer |
From: Michael J G. <mic...@fa...> - 2008-09-09 14:52:44
|
Alan G Isaac venit, vidit, dixit 09.09.2008 15:48: > Here is a simple test. > Run the following Python script > > import pyx > pyx.unit.set(defaultunit='pt') > c = pyx.canvas.canvas() > c.insert(pyx.epsfile.epsfile(0, 0, "eg.eps")) > c.writeEPSfile('pyxout.eps') > > where eg.eps is below. Should get a bounding box > of 0 0 100 100. Right now (revision 3000) it is > off by 1 in every direction. This is caused by the default value bboxenlarge=1, and can be changed by using bboxenlarge=0 as an argument to writeEPSfile(). If you have integral values for the bbox then you don't need my patch. If you have non-integral values than with my patch (and the hiresbbox=1 option to epsfile.epsfile) the included eps file in PyX will have exactly the bbox specified in the eps (as opposed to the rounded values). > One comment: this is actually a big deal, for > graphics headed for publication. Yes. When I encountered it first I didn't know how to cope with it. > Good behavior > should be the default, imo. I did not fully understand > the linewidth argument: when I give you a bounding > box, that's it! Everything outside is clipped. > I cannot have a 1 point "halo" around the figure. Well, "good behaviour" for whom. By default the bbox (for the output) is determined by PyX. As Jörg explains, PyX doesn't know how to compute the bbox of a stroked path. At the joints it's certainly more difficult than just computing leftmost coordinate minus half linewidth etc. The default for bboxenlarge is a crude (sorry) fix for that. In fact, bounding boxes of stroked rectangles do change when I change the linewidth, so PyX takes them into account somehow. As Jörg points out, it's suboptimal that the bboxenlarge fix is applied to all canvas items. Michael |
From: Alan G I. <ai...@am...> - 2008-09-09 15:16:07
|
On 9/9/2008 10:52 AM Michael J Gruber apparently wrote: > This is caused by the default value bboxenlarge=1, and can be changed by > using bboxenlarge=0 as an argument to writeEPSfile(). > If you have integral values for the bbox then you don't need my patch. Right you are. Thanks, Alan PS This seems important enough to deserve documentation here: http://pyx.sourceforge.net/manual/node17.html and here: http://pyx.sourceforge.net/manual/node20.html |
From: Michael J G. <mic...@fa...> - 2008-09-09 15:45:24
|
Alan G Isaac venit, vidit, dixit 09.09.2008 17:16: >> On 9/9/2008 10:52 AM Michael J Gruber apparently wrote: >>>> This is caused by the default value bboxenlarge=1, and can be changed by >>>> using bboxenlarge=0 as an argument to writeEPSfile(). If you >>>> have integral values for the bbox then you don't need my patch. >>>> >> >> >> Right you are. Thanks, Alan PS This seems important enough to >> deserve documentation here: >> http://pyx.sourceforge.net/manual/node17.html and here: >> http://pyx.sourceforge.net/manual/node20.html Well, it is documented here: http://pyx.sourceforge.net/manual/node19.html But I agree there should be a reference there:17 and there:20 :) Cheers, Michael |
From: Michael J G. <mic...@us...> - 2011-07-22 12:09:47
|
hiresbbox=0 is the default, unchanged behaviour. hiresbbox=1 means that the high resolution bounding box (HiResBoundingBox) is used rather than the normal one (BoundingBox). --- manual/epsfile.rst | 3 +++ pyx/epsfile.py | 23 +++++++++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/manual/epsfile.rst b/manual/epsfile.rst index 7becc79..8badb08 100644 --- a/manual/epsfile.rst +++ b/manual/epsfile.rst @@ -59,6 +59,9 @@ are summarized in the following table: +---------------------+-----------------------------------------------+ | ``kpsearch=0`` | Search for file using the kpathsea library. | +---------------------+-----------------------------------------------+ +| ``hiresbbox=0`` | Use the high resolution bounding box rather | +| | than the normal one. | ++---------------------+-----------------------------------------------+ .. _epsfile: diff --git a/pyx/epsfile.py b/pyx/epsfile.py index 59d291b..d04e07b 100644 --- a/pyx/epsfile.py +++ b/pyx/epsfile.py @@ -137,7 +137,7 @@ class linefilereader: self.file.close() -def _readbbox(file): +def _readbbox(file, hiresbbox=0): """returns bounding box of EPS file filename""" file = linefilereader(file) @@ -146,20 +146,26 @@ def _readbbox(file): if not file.readline().startswith("%!"): raise IOError("file doesn't start with a '%!' header comment") + if hiresbbox: + bboxmatch = "%%HiResBoundingBox:" + bboxtype = float + else: + bboxmatch = "%%BoundingBox:" + bboxtype = int bboxatend = 0 # parse the header (use the first BoundingBox) while 1: line = file.readline() if not line: break - if line.startswith("%%BoundingBox:") and not bboxatend: + if line.startswith(bboxmatch) and not bboxatend: values = line.split(":", 1)[1].split() if values == ["(atend)"]: bboxatend = 1 else: if len(values) != 4: raise IOError("invalid number of bounding box values") - return bbox.bbox_pt(*map(int, values)) + return bbox.bbox_pt(*map(bboxtype, values)) elif (line.rstrip() == "%%EndComments" or (len(line) >= 2 and line[0] != "%" and line[1] not in string.whitespace)): # implicit end of comments section @@ -213,11 +219,11 @@ def _readbbox(file): line = True while line: line = file.readline(EOFmsg=None) - if line.startswith("%%BoundingBox:"): + if line.startswith(bboxmatch): values = line.split(":", 1)[1].split() if len(values) != 4: raise IOError("invalid number of bounding box values") - usebbox = bbox.bbox_pt(*map(int, values)) + usebbox = bbox.bbox_pt(*map(bboxtype, values)) if not usebbox: raise IOError("missing bounding box information in document trailer") return usebbox @@ -231,7 +237,7 @@ class epsfile(canvasitem.canvasitem): x, y, filename, width=None, height=None, scale=None, align="bl", clip=1, translatebbox=1, bbox=None, - kpsearch=0): + kpsearch=0, hiresbbox=0): """inserts epsfile Object for an EPS file named filename at position (x,y). Width, height, @@ -240,7 +246,8 @@ class epsfile(canvasitem.canvasitem): translatebbox is not set, the EPS graphics is not translated to the corresponding origin. If bbox is not None, it overrides the bounding box in the epsfile itself. If kpsearch is set then filename is searched - using the kpathsea library. + using the kpathsea library. If hiresbbox is set then the high resolution + bbox is used instead of the normal one. """ self.x_pt = unit.topt(x) @@ -251,7 +258,7 @@ class epsfile(canvasitem.canvasitem): self.mybbox = bbox else: epsfile = self.open() - self.mybbox = _readbbox(epsfile) + self.mybbox = _readbbox(epsfile, hiresbbox=hiresbbox) epsfile.close() # determine scaling in x and y direction -- 1.7.6.336.gdf067 |
From: Michael J G. <mic...@us...> - 2011-07-22 12:09:47
|
Highlighting bbox issues. --- I failed to install whatever I need from zope, I hope the example builds. --- examples/drawing2/INDEX | 1 + examples/drawing2/epsbbox.py | 23 +++++++++++++++++++++++ examples/drawing2/epsbbox.txt | 14 ++++++++++++++ 3 files changed, 38 insertions(+), 0 deletions(-) create mode 100644 examples/drawing2/epsbbox.py create mode 100644 examples/drawing2/epsbbox.txt diff --git a/examples/drawing2/INDEX b/examples/drawing2/INDEX index e547b1b..e2f9ae5 100644 --- a/examples/drawing2/INDEX +++ b/examples/drawing2/INDEX @@ -3,3 +3,4 @@ insert smoothed parallel clipping +epsbbox diff --git a/examples/drawing2/epsbbox.py b/examples/drawing2/epsbbox.py new file mode 100644 index 0000000..408183f --- /dev/null +++ b/examples/drawing2/epsbbox.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# -*- coding: ISO-8859-1 -*- +from pyx import * + +r = canvas.canvas() +r.stroke(path.line(0, 0, 0.15, 0.15)) +r.writeEPSfile("epsbbox-inc", bboxenlarge=0) + +s = canvas.canvas() +s.insert(r, [trafo.scale(10)]) +elow = epsfile.epsfile(0, 0, "epsbbox-inc.eps", scale=10) +ehigh = epsfile.epsfile(0, 0, "epsbbox-inc.eps", scale=10, hiresbbox=1) + +c = canvas.canvas() +x = 0 + +for cc in [s, elow, ehigh]: + c.stroke(cc.bbox().rect(), [color.rgb.red, trafo.translate(x,0)]) + c.insert(cc, [trafo.translate(x,0)]) + x += cc.bbox().width()*1.2 + +c.writeEPSfile("epsbbox") +c.writePDFfile("epsbbox") diff --git a/examples/drawing2/epsbbox.txt b/examples/drawing2/epsbbox.txt new file mode 100644 index 0000000..7b82c60 --- /dev/null +++ b/examples/drawing2/epsbbox.txt @@ -0,0 +1,14 @@ +EPS-file inclusion and bounding boxes + +In this example we first generate an EPS-file and write it out. +Reading an EPS-file with `epsfile.epsfile()` gives you a canvas which can be +inserted just like other canvases. Note how you can scale the EPS when it is read. + +Like many others, PyX writes out high resolution bounding boxes. +By default it reads the normal bounding boxes, but using `hiresbbox=1` you can +instruct PyX to use the high resolution version. Note the difference between the +middle (low res bbox) and right (high res bbox) boxes. + +!The difference between left (canvas bbox) and right (high res eps bbox) is due to +fact that PyX can take into account the width of the line only for the bounding +box calculation during the output of the EPS. -- 1.7.6.336.gdf067 |
From: Joerg L. <jo...@us...> - 2011-07-22 13:24:40
|
Hi Michael, On 22.07.11, Michael J Gruber wrote: > hiresbbox=0 is the default, unchanged behaviour. > hiresbbox=1 means that the high resolution bounding box (HiResBoundingBox) > is used rather than the normal one (BoundingBox). Thanks! I wonder whether one should not do this automatically, i.e., if there is a HiResBoundingBox present, use that one instead of BoundingBox. Cheers, Jörg |
From: Michael J G. <mic...@us...> - 2011-07-22 13:40:12
|
Joerg Lehmann venit, vidit, dixit 22.07.2011 15:24: > Hi Michael, > > On 22.07.11, Michael J Gruber wrote: >> hiresbbox=0 is the default, unchanged behaviour. >> hiresbbox=1 means that the high resolution bounding box (HiResBoundingBox) >> is used rather than the normal one (BoundingBox). > > Thanks! I wonder whether one should not do this automatically, i.e., if there > is a HiResBoundingBox present, use that one instead of BoundingBox. Well, that would change existing behaviour, which would mean a no-go in another project I'm working with. That attitude somewhat stuck to me ;) Note that with my implementation, hirebbox=1 even errors out when there is no hires bbox. This is intentional (user asks for it but there is none), but I don't mind changing it. Michael |
From: Joerg L. <jo...@us...> - 2011-07-22 13:47:42
|
On 22.07.11, Michael J Gruber wrote: > Joerg Lehmann venit, vidit, dixit 22.07.2011 15:24: > > On 22.07.11, Michael J Gruber wrote: > >> hiresbbox=0 is the default, unchanged behaviour. > >> hiresbbox=1 means that the high resolution bounding box (HiResBoundingBox) > >> is used rather than the normal one (BoundingBox). > > > > Thanks! I wonder whether one should not do this automatically, i.e., if there > > is a HiResBoundingBox present, use that one instead of BoundingBox. > > Well, that would change existing behaviour, which would mean a no-go in > another project I'm working with. That attitude somewhat stuck to me ;) PyX is still officially in its alpha state. The only problem I can see is that it changes existing behaviour without notifying the user. But since in my opinion, the current behaviour of PyX is just not fully in accordance with the standard, I would live with such a change. > Note that with my implementation, hirebbox=1 even errors out when there > is no hires bbox. This is intentional (user asks for it but there is > none), but I don't mind changing it. Yep, that would need to change, of course. What do the others think? Jörg |
From: Michael S. <m-s...@us...> - 2011-07-22 13:52:30
|
Salut, On 22/07/11, Michael J Gruber wrote: > Joerg Lehmann venit, vidit, dixit 22.07.2011 15:24: > > On 22.07.11, Michael J Gruber wrote: > >> hiresbbox=0 is the default, unchanged behaviour. > >> hiresbbox=1 means that the high resolution bounding box (HiResBoundingBox) > >> is used rather than the normal one (BoundingBox). > > > > Thanks! I wonder whether one should not do this automatically, i.e., if there > > is a HiResBoundingBox present, use that one instead of BoundingBox. +1 for defaulting to HiRes, with fallback to ordinary BB if HiRes not present. In my opinion, the ordinary BB is the default only for historical reasons. BTW: If I compare inclusion of eps and pdf in latex/pdflatex, then eps defaults to BB, and in pdf there is only a HiResBB. This made me use always the HiResBB, also if I include eps in latex. > Well, that would change existing behaviour, which would mean a no-go in > another project I'm working with. That attitude somewhat stuck to me ;) > > Note that with my implementation, hirebbox=1 even errors out when there > is no hires bbox. This is intentional (user asks for it but there is > none), but I don't mind changing it. Cordialement, Michael |
From: André W. <wo...@us...> - 2011-07-25 20:38:34
Attachments:
smime.p7s
|
Hi, I'm sorry for being late in the discussion. Am 22.07.2011 um 14:09 schrieb Michael J Gruber: > hiresbbox=0 is the default, unchanged behaviour. > hiresbbox=1 means that the high resolution bounding box (HiResBoundingBox) > is used rather than the normal one (BoundingBox). First of all thank you for your patch. We should certainly use the HiResBoundingBox. I agree to other comments in the thread to change the default to use the HiResBB (if available). While this is an incompatible change, it is for the better. PyX development allows for incompatible changes. While the graphical defect might need to be fixed for certain use-cases, I suggest to make this exceptional by a deprecation warning (just add a warnings.warn(...)). Furthermore I suggest to rename the parameter to "ignore_hiresbbox" and set it to False. While this is more verbose, it is a better description of what the parameter does. To summarize my point of view: We don't have a lowresbbox paramter and we don't need to add it. As a side remark: PyX requires Python 2.3 now and we can use True and False. While we did not yet fix all the old code in this respect, we should use it for new code from the very beginning. Any comment regarding the addition of the second part of the patch, the epsfile.epsfile example? Fine for me, even as an example, not just an gallery entry. However, I wonder whether we should demonstrate "ignore_hiresbbox". It could be a double dangerous bend signed paragraph, but we don't need to show it. This example will also display the bitmap based display of the embedded epsfile in the pdf output, which could (and should) be discussed by a double dangerous bend signed paragraph. It is fine to demonstrate this problem, as we need to work on a pdffile.pdffile functionality too (and it slightly increases the pressure). But for PDF there will never be a lowresbbox feature so the same functionality for epsfile should be an exception and to my mind even a deprecated feature. Best, André -- by _ _ _ Dr. André Wobst, Amselweg 22, 85716 Unterschleißheim / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |