[comp.sys.mac.programmer] Generating Bitmap PICTs

tim@hoptoad.uucp (Tim Maroney) (04/09/90)

In article <2105@mit-amt.MEDIA.MIT.EDU> jow@mit-amt.MEDIA.MIT.EDU
(Joel Wachman) writes:
>Hi, can someone please help me out?  I am trying to write a program
>that converts a bitmap stored as ASCII data (actually, an X11 icon)
>into a PICT.  I figured I could do this by putting the bitmap data 
>into a BitMap structure, then doing an OpenPicture(),CopyBits(),
>ClosePicture(), but instead of seeing my bitmap, I see garbage.
>Furthermore, the garbage is different every time I run the program.
>
>It might just be that somewhere else, my code is broken, but I have
>checked the BitMap just before the CopyBits() and the baseAddr, rowBytes and
>bounds fields are all correct.  The data pointed to by baseAddr is
>also correct.

Seems like that's a little difficult to check other than by drawing the
thing.  I recommend doing so in a test version.

>	(SETRECT() is a macro to set the fields of a Rect)

Why?  The overhead of calling the trap is trivial unless you're doing
it many, many, many times inside a loop.

>     unsigned char *imagedata,*GetImageData();
>     short xsize,ysize;
>     Window newwindow;
>     Rect pictureRect;
>     PicHandle picture;
>     BitMap bitMap;
>
>     window  = GetNewWindow(PICT_WINDOW_ID,nil,(WindowPtr)-1);

It would be better if you would give us your actual code rather than fixing
it up, as the use of "window" rather than "newwindow" here shows.  You may
be hiding the bug in the process of editing.

>     imagedata = GetImageData(iconFile,&xsize,&ysize);

For obvious reasons (namely, that I can't see it), I'm suspicious of
the GetImageData call!  Draw what it returns to make sure it's OK.

>     SETRECT(&pictureRect,0,0,xsize,ysize);
>     SETRECT(&bitMap.bounds,0,0,xsize,ysize);
>     bitMap.baseAddr = imagedata;
>     /* make sure rowBytes is even			*/
>     bitMap.rowBytes = (xsize & 1 ? xsize - 1 : xsize);

I think this could be a big part of the problem.  First of all, you're using
xsize as a pixel measurement in the SetRect calls, but here, you're using it
as a byte measurement.  There's a factor of eight difference between the two.
Furthermore, you're trimming rowBytes when you should be growing it.  This
strategy would lead to losing your last byte from each row, which would cause
a sort of progressive horizontal drift in the bitmap.  The statement should
read something like:

	bitMap.rowBytes = ((xsize / 8) & 1 ? (xsize / 8) + 1 : (xsize / 8));

Not sure that's exactly correct, but it should be closer to it.

You may also have to wind up doing some sort of data conversion on the
bitmap data, if the X11 bitmap data doesn't live up to the Mac's somewhat
restrictive requirements.  That is, it may be leaving off the padding
from the end of each row, so that you need to do a row-by-row copy of
the X11 bitmap into the Mac bitmap.

>     /* draw the bitmap into the window while the picture recorder is on */
>     picture = OpenPicture(&pictureRect);

OK, but first, do a ClipRect to the picture rectangle.

>     CopyBits(&bitMap,(BitMap *)(&(newwindow->portBits)),

Why the conversion?  It is redundant and misleading.

>	      &pictureRect,&pictureRect,0,NULL);

The CopyBits looks OK, so your bitmap must be set up wrong.

>     ClosePicture();
>     DrawPicture(picture,&pictureRect);

Looks OK.  Again, try drawing your bitmap correctly first, without drawing
it into a picture.  If you can do that, then the rest of this should work
(provided you put in the ClipRect).  I use fairly similar code to turn
bitmaps into PICTs myself.  Interestingly, a PICT of a bitmap of any
significant size is often smaller than the bitmap; it appears that the
QD picture code compresses saved bitmaps using the usual MacPaintish
PackBits and UnpackBits calls.
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

"The Diabolonian position is new to the London playgoer of today, but not to
 lovers of serious literature.  From Prometheus to the Wagnerian Siegfried,
 some enemy of the gods, unterrified champion of those oppressed by them, has
 always towered among the heroes of the loftiest poetry."
    - Shaw, "On Diabolonian Ethics"