[comp.sys.mac.programmer] turning on a pixel

mikeoro@hubcap.clemson.edu (Michael K O'Rourke) (08/21/89)

I am writing a graphics program that turns on many pixels one at a time
by calculating some mathematical eqns. (kind of a fractal).  It presently
is using :

moveto(x,y);
lineto(x,y);

to turn on a pixel.  Is there some quicker way to do this from pascal?
The program is horribly slow right now and it needs to be speeded up.
For instance, does someone have a quick assembly routine that will turn
on a pixel?  I'd be willing to convert to LSC so that i could use the 
inline assembly if it would really improve speed.

Michael O'Rourke

keith@Apple.COM (Keith Rollin) (08/21/89)

In article <6294@hubcap.clemson.edu> mikeoro@hubcap.clemson.edu (Michael K O'Rourke) writes:
>I am writing a graphics program that turns on many pixels one at a time
>by calculating some mathematical eqns. (kind of a fractal).  It presently
>is using :
>
>moveto(x,y);
>lineto(x,y);
>
>to turn on a pixel.  Is there some quicker way to do this from pascal?

I usually use PaintRect(r), where r is (x,y,x+1,y+1), just so I don't have to
make 2 calls through the Dispatcher. I've also heard that MoveTo/Line(0,0) is
particularly optimized, but I don't know if, internally, that's different from
what you are doing.

>The program is horribly slow right now and it needs to be speeded up.
>For instance, does someone have a quick assembly routine that will turn
>on a pixel?  I'd be willing to convert to LSC so that i could use the 
>inline assembly if it would really improve speed.

Do you know for sure that it's QuickDraw that's slowing you down? I was just
working on a program that did a lot of intense calculations and single-pixel
plotting. After my first pass at writing it (in MacApp, of course), I turned
on the Performance tools to see where I could speed things up. *MUCH* to my
surprise, almost no time was spent in QuickDraw. This was even after I was
doing a lot of plotting, setting and changing of ports and gDevices, Color
Manager calls, and region manipulations. It turned out that 85-90% of the time 
was spent in my calculations.

Of course, this is just my own experience, and may not apply to yours. You may
be plotting a bunch of X/Y pairs, and not be performing any calculations at
all...
------------------------------------------------------------------------------
Keith Rollin  ---  Apple Computer, Inc.  ---  Developer Technical Support
INTERNET: keith@apple.com
    UUCP: {decwrl, hoptoad, nsc, sun, amdahl}!apple!keith
"Argue for your Apple, and sure enough, it's yours" - Keith Rollin, Contusions

jimc@iscuva.ISCS.COM (Jim Cathey) (08/21/89)

In article <6294@hubcap.clemson.edu> mikeoro@hubcap.clemson.edu (Michael K O'Rourke) writes:
>I am writing a graphics program that turns on many pixels one at a time
>by calculating some mathematical eqns. (kind of a fractal).  It presently
>is using :
>
>moveto(x,y);
>lineto(x,y);
>
>to turn on a pixel.  Is there some quicker way to do this from pascal?
>The program is horribly slow right now and it needs to be speeded up.

For fast point plotting probably your best bet is to allocate an offscreen
bitmap the size of the active area of the screen, and then set the bits in
it yourself.  When done (or periodically) just CopyBits this thing onto the
real screen.

The overhead of clipping tests and all of that really hurts the plotting of
a single pixel.  On your own array it's just a matter of *, shift and mask to
find the bit to set.  If you're really in a hurry you can pre-calculate a
table of byte offsets based on Y value and skip the multiply.  Using assembly
means you can probably do it even faster.

Doing it this way means you don't ever run afoul of bit depth on the screen,
and you wont get whanged on the head if/when the video hardware ever gets
protected, or is in some way strange on any particular machine.  All it costs
you is the array and a bit of skull sweat.

+----------------+
! II      CCCCCC !  Jim Cathey
! II  SSSSCC     !  ISC-Bunker Ramo
! II      CC     !  TAF-C8;  Spokane, WA  99220
! IISSSS  CC     !  UUCP: uunet!iscuva!jimc (jimc@iscuva.iscs.com)
! II      CCCCCC !  (509) 927-5757
+----------------+
			"With excitement like this, who is needing enemas?"

parent@apple.com (Sean Parent) (08/22/89)

In article <6294@hubcap.clemson.edu> mikeoro@hubcap.clemson.edu (Michael K 
O'Rourke) writes:
> I am writing a graphics program that turns on many pixels one at a time
> by calculating some mathematical eqns. (kind of a fractal).  It presently
> is using :
> 
> moveto(x,y);
> lineto(x,y);

The best aproach is to allocate an offscreen Bit/Pix Map and write your 
own command to set a
pixel (this is rather trivial and could be made as a macro). Then copyBits 
the image to the screen when it is complete. If you wish to use the 
moveto, lineto approach then get the trap address and call them directly. 
You may also see some speed improvement if you hide the cursor first since 
lineto is just going to hide it anyway.

Sean Parent

tim@hoptoad.uucp (Tim Maroney) (08/22/89)

In article <6294@hubcap.clemson.edu> mikeoro@hubcap.clemson.edu (Michael
K O'Rourke) writes:
>I am writing a graphics program that turns on many pixels one at a time
>by calculating some mathematical eqns. (kind of a fractal).  It presently
>is using :
>
>moveto(x,y);
>lineto(x,y);
>
>to turn on a pixel.  Is there some quicker way to do this from pascal?
>The program is horribly slow right now and it needs to be speeded up.
>For instance, does someone have a quick assembly routine that will turn
>on a pixel?  I'd be willing to convert to LSC so that i could use the 
>inline assembly if it would really improve speed.

First of all, have you tried running the program without any drawing?
I wrote a silly little one-level B&W Mandelbrot program on a Mac II a
few years back, and it was tremendously slow, but it was spending all
its time in math, not in drawing.  Fractals are very slow to compute --
generally this is so even when you use tricks like "if every
surrounding pixel is black, the contained pixel is black".

But assuming that your problem really is in the drawing, then it's
probably the trap overhead, not any slowness of the QD routines
themselves, which on the Mac Plus and later ROMs really are about as
fast as you could hope for.  You can short-circuit them by using
NGetTrapAddress and calling that address instead of trapping; you might
expect to see an improvement of as much as 30% in drawing speed.  This
is not the world's most kosher technique, but it's marginally better
than drawing directly to the screen bitmap from your software, which
has been expressly forbidden by every compatibility guidelines list
from Eden onwards.

But if you must draw to the screen, then it's really not all that hard
to do.  Just familiarize yourself with the bitmap data structure and
the bit twiddling will be easy.  Pascal on the Mac has some inline
bit-setting operators which should let you avoid assembly language.
I'm not going to give much counsel in such a nasty technique, but
it really is not hard to mess with bitmaps directly.  It just looks
that way before you start.
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

"There are no Famous People on the net.  Only some of us with bigger mouths
 than others."  -- Dan'l Danehy-Oakes, The Roach

d88-jwa@nada.kth.se (Reply via mail or intl. +46 8 258 268...) (08/22/89)

In article <3735@internal.Apple.COM> parent@apple.com (Sean Parent) writes:
>If you wish to use the 
>moveto, lineto approach then get the trap address and call them directly. 

Nono ! This no longer an officially approved by Apple way to optimize
a program. Line is faster than LineTo, but the method of creating your
own BitMap (One bit deep) is far better. Or, if you have the memory,
use EIGHT BIT DEEP pixmaps. This makes for FAST code (No shifting and
things)

>Sean Parent

h+@nada.kth.se
-- 
This is your fortune from h+@nada.kth.se:
Life is what happens to you while you are planning to do something else.

rcbaem@eutrc3.urc.tue.nl (Ernst Mulder) (08/22/89)

In article <6294@hubcap.clemson.edu> mikeoro@hubcap.clemson.edu (Michael K O'Rourke) writes:
>
>moveto(x,y);
>lineto(x,y);
>
>to turn on a pixel.
>
>Michael O'Rourke

Hmm, I use:

moveto(x,y);
line(0,0);

Which is faster?

 Ernst.
   >

jpd00964@uxa.cso.uiuc.edu (08/23/89)

/* Written  3:09 pm  Aug 21, 1989 by d88-jwa@nada.kth.se in uxa.cso.uiuc.edu:comp.sys.mac.programmer */
>Nono ! This no longer an officially approved by Apple way to optimize
>a program.

So what?  

Michael Rutman

ralph@computing-maths.cardiff.ac.uk (Ralph Martin) (08/24/89)

Its not me thats crazy, its everyone else!

If you look at Inside Mac, it clearly says that coordinates refer to
points at the corner of pixels, not the pixels themselves. Thus, it
seems to me that any code like moveto(x,y) lineto(x,y) should draw a
line of zero length, ie nothing at all. It seems to me that all of you
have it wrong when you do this (including you guys at Apple, who
actually apparently make such code not draw a line of zero length, but
a single pixel).  I've always used (the equivalent of) moveto(x,y),
lineto(x+1,y+1) to set a given pixel.

So, hit me with the flamethrower! Who's right, and who's wrong?!

As I said, its the rest of the world thats crazy......

sdh@wind.bellcore.com (Stephen D Hawley) (08/25/89)

In article <843@cf-cm.UUCP> ralph@computing-maths.cardiff.ac.uk (Ralph Martin) writes:
>If you look at Inside Mac, it clearly says that coordinates refer to
>points at the corner of pixels, not the pixels themselves. Thus, it
>seems to me that any code like moveto(x,y) lineto(x,y) should draw a
>line of zero length, ie nothing at all. It seems to me that all of you
>have it wrong when you do this (including you guys at Apple, who
>actually apparently make such code not draw a line of zero length, but
>a single pixel).  I've always used (the equivalent of) moveto(x,y),
>lineto(x+1,y+1) to set a given pixel.
>So, hit me with the flamethrower! Who's right, and who's wrong?!
>As I said, its the rest of the world thats crazy......



One flame thrower coming up.  Inside Mac also claims that the pen hangs
below and to the right of the pixel's coordinates.  If you use a pen size
of 0,0 then nothing should happen.  A pen size of 1,1 will plot a single
point.


Nice try, though.

Steve Hawley
sdh@flash.bellcore.com
"Up is where you hang your hat."
	--Jim Blandy, computer scientist

ba0k+@andrew.cmu.edu (Brian Patrick Arnold) (08/25/89)

I though the same thing you thought, but when you do a LineTo to nowhere, think of it as 
"pressing" the pen on the grafport without moving it - and it will make its mark.  Make sure
you understand this: the line IS zero length, but the pen's ink has both nonzero height and width.
If you don't want a zero-length line drawn, don't attempt to draw it in the first place.

It does make you think points aren't at the corner of pixels, but when you deal
with fat or strange rectangular pen sizes, it doesn't seem so strange...  Apple isn't merely
right in its implementation, it's downright subtle and a pleasant change.

- Brian

kk@mcnc.org (Krzysztof Kozminski) (08/25/89)

In article <843@cf-cm.UUCP> ralph@computing-maths.cardiff.ac.uk (Ralph Martin) writes:
>If you look at Inside Mac, it clearly says that coordinates refer to
>points at the corner of pixels, not the pixels themselves. Thus, it
>seems to me that any code like moveto(x,y) lineto(x,y) should draw a
>line of zero length, ie nothing at all. It seems to me that all of you
>have it wrong when you do this (including you guys at Apple, who
>actually apparently make such code not draw a line of zero length, but
>a single pixel).  I've always used (the equivalent of) moveto(x,y),
>lineto(x+1,y+1) to set a given pixel.

You forgot about the pen size.  The call 'lineto(x,y)' should be interpreted
as:  'put pen down at the current position', 'move pen to (x,y)',
'pick it up'.  Even if the move does not change the position, the mark
remains.  See Inside Mac vol 1, page 155, fig 15.

KK
-- 
Kris Kozminski   kk@mcnc.org
"The party was a masquerade; the guests were all wearing their faces."

oster@dewey.soe.berkeley.edu (David Phillip Oster) (08/25/89)

Many people think they can optimise single pixel drawing by just drawing
directly into screen memory, and you can, bu tlook at the problems:

(i) your drawing isn't clipped against screen boundaries, the boundaries of
windows above the one you are trying to draw into, or drawing over the
image of the cursor. (circa 1985)

(ii) If the user has color QuickDraw, the screen could be an unusual size,
shape, and depth. In addition, since a window may span multiple screens,
you can't depend on the basAddr of the pixmap pointing anywhere in
particular, you have to work your way down the list of gDevices, looking
at screen rectangles in global coordinates. (circa 1987)

(iii) If the user has 32-bit Color Quickdraw, the screen may be in another
world entirely: when you call QuickDraw with 32-bit color quickdraw
installed, it flips the system into 32-bit mode, thereby radically
changing the memory map. If you try direct memory access through the
basAddr of a  gDevice directly, from an ordinary program, the system will
probably crash with a bus error. (circa 1989)


Notice, that Apple adds a new,  unanticipatible reason not to do this
every two years or so. Do everything right today to directly twiddle
screen memory, and it is likely that Apple will still kill your program
within two years from now.

Conclusion: directly bit-twiddle an off-screen bitmap, then call CopyBits
to display it for you. It will save you much prsent pain, and still more
future pain.
--- According to the Constitution, the Constitution is unconstitutional:
--- David Phillip Oster            --U.S.Constitution I.10.1: "No State shall
Arpa: oster@dewey.soe.berkeley.edu --enter into any treaty, alliance, or
Uucp: {uwvax,decvax}!ucbvax!oster%dewey.soe.berkeley.edu -- confederation..."

ralph@computing-maths.cardiff.ac.uk (Ralph Martin) (08/29/89)

OK, I admit that I should'a read the docs more carefully on Coordinates and
Pixels before opening my mouth and shoving my foot in it. I had forgot that
although Apple define a Point as a Mathematical Point (ie of no size), they 
dont define a line as a Mathematical Line (of no size), but as a Real World
Line drawn by a pen of finite thickness. Mea Culpa.