[comp.lang.postscript] Screening Procedures

sg1q+@andrew.cmu.edu (Simon Peter Gatrall) (06/29/88)

I've been interested in playing with the procedures PostScript uses to do
halftoning, and I was wondering if anyone else is familiar with this stuff.
One thing that bothers me is that once a pattern is made to represent a
specific gray value, it isn't recomputed.  This makes all the sense in the
world for line and dot screens, but what if you want something that looks like
a texture?  How do you make a circular line screen?

Personally it seems to me that Adobe has made it so that you can redefine the
screen operator, but not in a useful way.  Has anybody out there come up with
neat effects using screen redefintion?

-Simon Gatrall                  sg1q+@andrew.cmu.edu

tony@oha.UUCP (Tony Olekshy) (07/02/88)

In <cWm8qMy00Xc8sPk0iw@andrew.cmu.edu>, sg1q+@andrew.cmu.edu (Simon Peter
Gatrall) writes:
>
> I've been interested in playing with the procedures PostScript uses to do
> halftoning, and I was wondering if anyone else is familiar with this stuff. 
> One thing that bothers me is that once a pattern is made to represent a
> specific gray value, it isn't recomputed.  This makes all the sense in the
> world for line and dot screens, but what if you want something that looks
> like a texture?

Here, here!  The following code will generate a random-patterned grey scale
with the probability of any pixel being white being proportional to the grey
level:

	1 45 { pop pop rand 1073741824 div 1 sub } setscreen

The problem is that when you use this, the maximum area that gets patterned
is 0.1" x 0.1", and THAT pattern is replicated over the whole area being
painted.  CAN halftoning be used to randomly pattern the entire area being
painted?

Yours, etc., Tony Olekshy (<smart>!alberta!oha!tony, +1 403 425 9657).

olson@endor.harvard.edu (Eric K. Olson) (07/05/88)

In a recent article Tony Olekshy writes:
>sg1q+@andrew.cmu.edu (Simon Peter Gatrall) writes:
>>
>> I've been interested in playing with the procedures PostScript uses to do
>> halftoning, and I was wondering if anyone else is familiar with this stuff. 
>> One thing that bothers me is that once a pattern is made to represent a
>> specific gray value, it isn't recomputed.  This makes all the sense in the
>> world for line and dot screens, but what if you want something that looks
>> like a texture?
>
>Here, here!  The following code will generate a random-patterned grey scale
>with the probability of any pixel being white being proportional to the grey
>level:
>
>	1 45 { pop pop rand 1073741824 div 1 sub } setscreen
>
>The problem is that when you use this, the maximum area that gets patterned
>is 0.1" x 0.1", and THAT pattern is replicated over the whole area being
>painted.  CAN halftoning be used to randomly pattern the entire area being
>painted?
>

As far as I know, there's no way to specify a screen in PostScript for which
the pattern for weight n>m does not include all of the pattern for weight m.
For instance, dots are possible ({ dup mul exch dup mul add 1 exch sub}),
but circles are not.  This is due to the way the screen is specified (at least
in part), as a function of x and y.  Chances are that PostScript internally
stores the _order_ of turning on the pixels in the pattern, and not the
patterns themselves.

However, it should be possible to write an ordered dither screen function
(I don't know how useful it would be at 300 dpi, though), since it conforms
to the limitation above.

Some other fun screens:

Horizontal Lines:	{exch pop abs 1 exch sub}
Crosses:		{dup mul exch dup mul mul 1 exch sub}
Diamonds:		{abs exch abs add 2 div} 
BowTies:		{mul}
Lines & Dots:		{dup dup mul mul exch dup dup mul mul
			 add abs 1 exch sub} 

Note that these are named for their appearance at 0 degree rotation:
diamonds are squares at 45 degrees, for instance.

Also, since PostScript picks randomly among pixels returning the same
ordering value, I believe you can get a random texture screen via
{pop pop 1} (i.e., a function returning the same value all the time).
This, of course, doesn't work any better than the random screen
suggested above.

-Eric


          Lexington Software Design:  Tomorrow's Software Yesterday

Eric K. Olson     olson@endor.harvard.edu     harvard!endor!olson     D0760
   (Name)                (ArpaNet)                 (UseNet)        (AppleLink)

sg1q+@andrew.cmu.edu (Simon Peter Gatrall) (07/09/88)

For those of you that tuned in late, I posted a request for screening
procedures that generated random patterns to create interesting textures.
(where _interesting_ is defined by the eye of the beholder :-)

I recieved the following reply from tony@oha.UUCP (Tony Olekshy):
>Here, here!  The following code will generate a random-patterned grey scale
>with the probability of any pixel being white being proportional to the grey
>level:
>
>       1 45 { pop pop rand 1073741824 div 1 sub } setscreen
>
>The problem is that when you use this, the maximum area that gets patterned
>is 0.1" x 0.1", and THAT pattern is replicated over the whole area being
>painted.  CAN halftoning be used to randomly pattern the entire area being
>painted?

I should have been clearer in my original request, but Tony's question is
exactly the one I wanted answered in the first place.  I have written screening
procedures very similar to his.  If your halftone cell is smaller than 0.1"
then each cell of a specific gray value over the entire image is screened
exactly the same.  If you try setting the cell size larger (I haven't tried
this myself, I'm just interpreting Tony's message) then you get a maximum of a
0.1" x 0.1" pattern.

I realize that in general the screening procedures that you can make (ie
various dots and lines) are adequite for most applications, I really want to
duplicate some of the texture effects that someone with a texture screen and a
stat camera can make.

I can think of one brute force method.  First you take your grey-scale image
and turn it into a dithered black and white image, and then print it out with
the standard screening methods.  I don't know how to write the dithering
procedure off-hand to get any interesting textures, but I imagine this approach
would work.  What I would prefer is to just be able to write some screening
procedure that has the same effect.  I guess that if you could customize the
low-level routines that do the screening, you could make PostScript recompute
each halftone cell.  Then the only problem is writing _interesting_ screening
procedures.

Is there anybody out there who knows more about this stuff?

-Simon Gatrall                  sg1q+@andrew.cmu.edu

steve@hanauma.stanford.edu (Steve Cole) (07/12/88)

I have also noticed that setscreen appears to limit your pattern to
a size of roughly 0.1 by 0.1 inches when you are trying to redefine the
halftone screen. I think I partly understand why. Maybe someone else
will know more.
 
In section 9.2 of the green book, on pattern fills, it says:
"Since the halftone screen is intended to be set once and forgotten,
much of the overhead is done when setscreen is invoked.
Even if only one gray level is needed, they may all be computed (by
calling the spot function as many times as necessary to build each
possible halftone cell)."
So PostScript wants to compute 256 (one for each gray level) copies of
your new halftone screen, one for each of the 256 possible gray levels.
This requires a lot of memory. For a 300 dot per inch printer, defining
a halftone screen that was one inch square would require 300x300x256
bits, or almost 3 megabytes. This is particularly annoying if you don't
want to do halftoning, but are using setscreen to do a pattern fill.
In that case only one of the 256 gray levels will ever be used. That is
why the green book doesn't advocate using setscreen for pattern fills.
 
I don't know why it seems to stop at around 0.1 inch square though, or
why in fact it stops at all. In section 4.8 of the red book, it says:
"In principle, the PostScript language permits defining screens with
arbitrarily large cells (i.,e. arbitrarily low frequencies). However,
cells that are very large (relative to the device resolution) or are at
unfavorable angles may exceed screen storage in some PostScript
configurations; if this occurs, setscreen executes a limitcheck error."
I have a feeling that PostScript is trying to avoid the limitcheck error
here by scaling down the requested halftone screen size. But I have never
found anything in the documentation that says it will do this.
 
I have done some work with different halftone patterns. I always do the
dithering myself and then print it in 1 bit/pixel mode rather than using
setscreen, partly because setscreen is difficult to use, and partly because
I want to be able to use a variety of output devices, and most don't have
any concept of halftoning. For anyone who's interested, some of my
halftoning code was distributed on the net in comp.sources.unix, as part
of a device-independent graphics package called "vplot".

--------------------------------------------------------------------------------
Steve Cole  (steve@hanauma.stanford.edu, decvax!hanauma!steve)
Department of Geophysics, Stanford University, Stanford, CA 94305

olson@endor.harvard.edu (Eric K. Olson) (07/12/88)

In a recent article Steve Cole writes:
>In section 9.2 of the green book, on pattern fills, it says:
>"Since the halftone screen is intended to be set once and forgotten,
>much of the overhead is done when setscreen is invoked.
>Even if only one gray level is needed, they may all be computed (by
>calling the spot function as many times as necessary to build each
>possible halftone cell)."
>So PostScript wants to compute 256 (one for each gray level) copies of
>your new halftone screen, one for each of the 256 possible gray levels.
>This requires a lot of memory. For a 300 dot per inch printer, defining
>a halftone screen that was one inch square would require 300x300x256
>bits, or almost 3 megabytes. This is particularly annoying if you don't
>want to do halftoning, but are using setscreen to do a pattern fill.
>In that case only one of the 256 gray levels will ever be used. That is
>why the green book doesn't advocate using setscreen for pattern fills.

PostScript might just save the absolute order of turning on the pixels in
the pattern, since each heavier pattern contains the entire pattern from
the lighter weights.  This would produce the same outward behavior as saving
the pattern for each of 256 weights.  Also, it would seem that there can
be more than 256 weights, since the 8-bit (maximum) data is passed through
a floating-point transfer function before being screened.

Perhaps someone from Adobe could enlighten us all?

-Eric
          Lexington Software Design:  Tomorrow's Software Yesterday

Eric K. Olson     olson@endor.harvard.edu     harvard!endor!olson     D0760
   (Name)                (ArpaNet)                 (UseNet)        (AppleLink)