Copy link to clipboard
Copied
I'm not sure how to explain this. Please pardon my code if it is bad or my terminology if it is wrong, as I'm a novice ps programmer.
What I'm trying to do is draw a pattern of vertical lines, which I want to be based on a resolution of 100 dpi. If I write "72 100 div 1 scale" then I have changed the coordinate system so I have an effective horizontal resolution of 100 units per inch, is that correct? Is this the correct way to change the resolution of the coordinate system? In other words, can we really change the resolution of the user space (irrespective of the device space)? I understand that there are actually no dots in user space and dots do not actually exist until rasterization, but please pardon my use of the term dpi to mean units of the coordinate system when I refer to the user space.
My goal is to render graphics that will come out accurately on a printer. Since most laser printers have a resolution that is a multiple of 100, then I reason that during rasterization lines sized in multiples of 1/100" will be precise (e.g. @600 dpi, 1 user space unit = 6 device space units or dots). This is to avoid rounding errors resulting from converting from 72 dpi to say 600 dpi. Does this make sense? Is this a sound premise?
If I'm on the right path thus far, then I use the following code to render a series of vertical lines which alternate between one unit and three units in width separated by spaces of one unit:
/w 1 def
20 {currentpoint w 20 rectfill w 1 add 0 rmoveto /w w 2 xor def} repeat
Prior to the above, I place a moveto command. If I write say "360 500 moveto" then the lines do not render as expected (I'm using ghostscript and gsview). If however, I write "363.6 500 moveto" then the lines render as expected. The code segment would be as follows:
363.6 500 moveto
72 100 div 1 scale
/w 1 def
20 {currentpoint w 20 rectfill w 1 add 0 rmoveto /w w 2 xor def} repeat
So 360 appears to be round number in that it is evenly divisble by 72 and also 0.72 (the scale factor) and appears to be a more round number than 363.6. I think perhaps I'm missing something in the math to get coordinates that will align so that all the lines will render evenly. On the other hand, if I do the scale first, then the moveto, the results are reversed: @360(x) renders okay, but @363.6(x) does not.
Can someone explain to me why this is so, and how to align to the coordinate system to render a precise series of lines?
Copy link to clipboard
Copied
This is more complex than it might seem. The PostScript rule is to imagine the page as something like graph paper, then contruct the exact paths you need over the top - that is, draw the lines between two points, extending out to the required thickness. Now you fill every box which has any part of the width of the line inside it. This means that line widths are likely to vary by 1 pixel. There is a technique of setting the line centre exactly half way through the actual coordinate system, so widths are rounded consistently throughout a figure. This requires some work in the device coordinate system to get the position of each point. There used to be a tech note about this but I haven't seen it in years.
You can't really say anything about correct printer rendering from a screen view though!
Copy link to clipboard
Copied
Thank you for your response, Test Screen Name. PostScript's way of producing lines of a specified thickness centered around a path is what I meant to avoid by using rectfill instead of lineto. To acquire the necessary precision of the lines and intervening spaces, we can say start here and paint so many units up and to the right. While it is true that results on screen may not match printed output, I set the screen view to 100 dpi resolution and zoom to 100 dpi, and if rendered properly it will look right on screen. The actual test that I do, however, is to rasterize the page to a bitmap, and then I can see exactly how many pixels make up the width of each line and space. A tech note about this would be very helpful . There's definately something going on that I don't fully understand.
Copy link to clipboard
Copied
I see now why you used rectfill, but it really makes no difference. The same rules apply, since your rectangle results in filling all of the device pixels through which it passes. You cannot just use user coordinates and make assumptions about device coordinates. I think you are assuming that
(a) the device resolution is exactly what the box says, and equal in X and Y directions
(b) the device grid conveniently aligns with the user grid, such that the axes for both grids are equal
Also, even if you align with the grid you potentially have boundary effects - if a line is drawn such that it is exactly on the edge of the device pixel, is the pixel filled? Which pixel - the one to the left, the one to the right, both?
I think your idea has some legs but you need to now get low level and dirty with the device coordinates.
Copy link to clipboard
Copied
The technote is here under "Emulation of the setstrokeadjust Operator". http://partners.adobe.com/public/developer/ps/sdk/index_archive.html#sa
But this begs the question, about a facility I had quite forgotten. Why not just use setstrokeadjust?
Copy link to clipboard
Copied
Thanks for the link. I need to study and research further. I reviewed automatic stroke adjustment, and it appears that either the lines can be made to be of uniform thickness, or they can be of uniform spacing depending on the setting of setstrokeadjust, but not both without some additional controls in place. The paper describes quarter unit alignment that merits some further study. The issue of whether the center of the line passes through the center of a column of pixels or precisely between columns of pixels is what I meant to avoid by using rectfill. As long as we start on a pixel boundry and go a whole number of units along, there won't be an issue of centering the line on the path.
As far as points (a) and (b) you made, they are good points to consider. I've yet to see any evidence that suggests that the RIP of a printer would deviate from specification of device resolution or that there would be a reason for the grids to not align if one is a multiple of the other. But even if there was a difference, how would one know?
I'll study the papers at the link you gave. You've been very helpful and given a lot of good pointers. Thank you.
Copy link to clipboard
Copied
How would one know? Inspection of the device matrix, which is effectively what is being used in that tech note.
Copy link to clipboard
Copied
I read the tech note, but I don't really understand how to inspect the device matrix. It doesn't seem to go into enough detail on that part. I spoke with an application developer a while back who develops PS programs. He described a process he calls "grid fitting" which is what I want to do. He described it thusly:
1. Detect the device's reported resolution.
2. Scale the user coordinate system to align with the device
resolution, such that 1 userspace unit = 1 device pixel.
3. Snap the user coordinate base point to the devices base point so
that where would be no unintended offset between these systems, i.e. a
dot exactly at some whole number coordinate will be right in the
center of the corresponding pixel in device space.
4. Rescale the user coordinate system by the most suitable integer
value such that the line or space between lines is rendered as close to the originally intended size as possible. This maintains the constraint that
lines and spaces of integer proportions will be mapped into correspondingly proportioned integer numbers of device pixels, providing as near a perfect rendition as the device is able to generate.
Steps 2 and 4 seem simple enough, but I don't know how to do steps 1 and 3. Any advice or recommendations of resources?
Copy link to clipboard
Copied
This is a viable process, but it isn't the simplest, and it has a flaw: in many devices the X and Y resolution are not equal (sometimes by a little, sometimes by a lot).
This isn't the technique used by the tech note so far as I remember (except that it has the same effect).
The trick is to work with device coordinates rather than user coordinates. That doesn't mean you have to know the resolution and code for it. Instead
For each coordinate in your paths
1. Convert to device coordinates ("transform")
2. Manipulate the device coordinates as required
3. Convert the device coordinates back to user coordinates ("itransform")
4. Process the (possibly modified) coordinates in the usual way ("moveto", "lineto" etc.)
Simple applications can process the coordinates singly and independently; more complex ones might need to process entire paths together.
Copy link to clipboard
Copied
Just quick note about resolution
Postscript programming is totally independent with device resolution
the Postscript only see 72 dots per inch - which match the way in offset screening ...
However the PS applications draw or fill 2 inch which means 144 dots ! then the PS Interpreter/Rip will handle the output to be exactly two inches wither your printer is 600 DPI or 1200 DPI it will be two inches - you - The Application Coder - don't have to worry at all about the output device resolution and that is the unique and petty thing in Postscript.
Cheers
Adam