[comp.sys.mac.programmer] A Mac novice & C

rpaul@dasys1.UUCP (Rod Paul) (09/16/89)

OK, so I picked up the best of both worlds, THINK C and AZTEC C, one for
my MAC moods and one for my Unix'ish moods.

I finally found a couple of decent books regarding C on a Mac, as the
manuals supplied with the above products aren't much use for starting
out (well for the price you can't complain) and my Pascal is rusty by 
about 5 years.

As graphics is my living, I decided it would be nice to be able to
view some of those 32-bit images I render at work, and at least view
them in 8-bits at home, so my first application...

I must admit, I started grumbling a little when I first started
investigating the Mac libraries (Managers), but after a while I began
to appreciate how fast you can put something together.

So after one night, I can find, read and display PICT files.

OK, so what if I wan't to process the data before displaying it on the
screen. QDprocs look a little hairy to start messing with right off the bat, 
and anyway my ultimate goal with this application is to convert image formats 
that I work in and display them on the Mac.

This is where I've run into a brick wall, could some kind soul give me
some tips on how to go about say, displaying a 256x256 type char array 
on the screen?

Other libraries I work with on my Unix machines have routines like 
writeRGB(xres, rbuf, gbuf, bbuf) for scanlines or similar routines
for rectangular areas.

Now I realize the Mac is a different environment, but there must be a
fairly simple way to accomplish this feat.

Any help will be greatly appreciated.

-- 
Rodian Paul
Big Electric Cat Public UNIX
..!cmcl2!hombre!dasys1!rpaul

oster@dewey.soe.berkeley.edu (David Phillip Oster) (09/20/89)

In article <10715@dasys1.UUCP> rpaul@dasys1.UUCP (Rod Paul) writes:
>This is where I've run into a brick wall, could some kind soul give me
>some tips on how to go about say, displaying a 256x256 type char array 
>on the screen?

Once again, here is my simple program for reacing in an ascii file of
hexbytes, and displaying it on the screen. Some things you'll need to
change to use this program:

It reads a file of postscript data, at 4 bits per pixel. You'll need
to make the pixmap longer to get 256 bits per pixel, and you'll need to
change the read routine. Postscript images are upside down compared to mac
images, so you'll need to remove the image inversion routine.

/* ShowBush.c - short program to display a postscript picture of Bush.
	 in color quickdraw. You also get Bush on your clipboard.
   by David Phillip Oster.

   Copy and use this in any way you see fit.

	Basically an example of the pain you have to go through to actually
	use color quickdraw.

	In old quickdraw, you had some data and a window, and you CopyBit()s the data to
		the window.

	In color quickdraw, you have as your source:
		a.) the data.
		b.) a color table.
		c.) a "pixmap" that connects the data to the color table.
	as your destination, you have:
		a.) a color window
		b.) a palette, that informs the window manager of which colors you'll be
			using, so the color manager can change the color table in the video
			board to make those color available.

	This program works best with at least 16 colors!

 */
#include <ColorToolbox.h>

#define HEIGHT 200
#define WIDTH  200

#define NIL 0L
#define NOT !

SysEnvRec *world;
Handle			myPixels;
WindowPtr		myWin;
PixMapHandle	myPixMap;
CTabHandle		myCTable;
PaletteHandle	myPm;

enum {
	READERROR = 1,
	NEEDSCOLORQD,	/* this demo needs color quickdraw */
	NOPIXMAP,
	NOPIXELS,
	NOCTABLE,
	NOPALETTE,
	PIXDATACHANGED
};

enum {
	UNDOI = 1,
	COPYI = UNDOI + 1
};

main(){
	EventRecord myEvent;

	Init();
	for(;;){
		if(GetNextEvent(everyEvent, &myEvent)){
			HandleEvent(&myEvent);
		}
	}
}


Init(){
	PaletteHandle oldPm;

	FlushEvents(everyEvent, NIL);
	InitGraf( (Ptr) &thePort);
	InitFonts();
	InitWindows();
	InitCursor();
	InitDialogs(NIL);
	InitMenus();
	TEInit();

	world = (SysEnvRec *) NewPtr(sizeof(SysEnvRec));
	SysEnvirons(1, world);
	if( NOT world->hasColorQD){
		Error(NEEDSCOLORQD, "");
	}

	myWin = GetNewCWindow(128, NIL, -1L);				/* set up the window */
	SetPort(myWin);
	ClipRect(&thePort->portRect);

	myPixMap = NewPixMap();								/* allocate the pixmap */
	if(NIL == myPixMap){
		Error(NOPIXMAP, "");
	}
	myPixels = NewHandle( ((long) HEIGHT/2)*WIDTH);		/* allocate the pixel data */
	if(NIL == myPixels){
		Error(NOPIXELS, "");
	}													/* allocate the color table */
	myCTable = (CTabHandle) NewHandle(sizeof(ColorTable) + 15L*sizeof(ColorSpec));
	if(NIL == myCTable){
		Error(NOCTABLE, "");
	}
	InitPixels(myPixels);								/* set up the pixel data */
	InitCTable(myCTable);								/* set up the color table */

	(**myPixMap).bounds.left = 0;						/* set up the pixmap */
	(**myPixMap).bounds.top = 0;
	(**myPixMap).bounds.right = WIDTH;
	(**myPixMap).bounds.bottom = HEIGHT;
	(**myPixMap).rowBytes = 0x8000 | (WIDTH/2);
	if(NIL != (**myPixMap).pmTable)
		DisposHandle((**myPixMap).pmTable);
	(**myPixMap).pmTable = myCTable;
	(**myPixMap).pixelSize = 4;

	myPm = NewPalette(16, myCTable, pmTolerant, 0);		/* set up the palette */
	if(NIL == myPm){
		Error(NOPALETTE, "");
	}
	
	if(NIL != (oldPm = GetPalette(thePort))){
		DisposePalette(oldPm);
	}
	SetPalette(thePort, myPm, TRUE);
	ActivatePalette(thePort);
}

/* SwapMove - copy from src to dest, moving scan lines from top to bottom
	as you go (postscript images are upside down compared to quickdraw images)
 */
SwapMove(src, dest, cnt)Ptr src, dest;long cnt;{
	register short i, j;

	for(i = 0;i <200;i++){
		BlockMove(src + (i*(WIDTH/2)), dest  + ((199-i)*(WIDTH/2)), WIDTH/2);
	}
}

/* InitPixels- initialize our handle to the bush data
	SwapMove since Postscript is upside down from Mac.
 */
InitPixels(h)Handle h;{
	register Ptr p, pMax;
	register short i;
	Handle h2, GetBush();

	h2 = GetBush();
	SwapMove(*h2, *h, GetHandleSize(h));
}


/* InitCTable - initialize our color table to uniform gray
 */
InitCTable(ct)CTabHandle ct;{
	short i;

	(**ct).ctSeed = GetCTSeed();
	(**ct).ctFlags = 0;
	(**ct).ctSize  = 16 - 1;
	for(i = 0;i < 16;i++){
		(**ct).ctTable[i].value = i;
		(**ct).ctTable[i].rgb.red = 
		(**ct).ctTable[i].rgb.green = 
		(**ct).ctTable[i].rgb.blue  = (unsigned) i * 16*257;
	}
}

/* Error - print the error message
 */
Error(i, s1)short i;Str255 s1;{
	Str255 s;

	GetIndString(s, 128, i);
	ParamText(s, s1, "", "");
	Alert(129, NIL);
	ExitToShell();
}

/* HandleEvent - quit on mouse or key event
 */
HandleEvent(event)EventRecord *event;{
	switch(event->what){
	case mouseDown:
	case keyDown:	ExitToShell();
	case updateEvt:	GoUpdate(event);	break;
	}
}

/* GoUpdate - handle update event, paste it to clipboard
 */
GoUpdate(event)EventRecord *event;{
	SetPort(event->message);
	BeginUpdate(thePort);
	CopyMyBits();
	EndUpdate(thePort);
}

/* CopyMyBits - put bits to screen, put bits to clipboard
 */
CopyMyBits(){
	Rect r, r2;
	PicHandle ph;

	HLock(myPixels);
	HLock(myPixMap);
	(**myPixMap).baseAddr = *myPixels;
	r.left = 0;
	r.top = 0;
	r.right = WIDTH;
	r.bottom = HEIGHT;
	r2 = r;
	r2.top *= 2;
	r2.left *= 2;
	r2.right *= 2;
	r2.bottom *= 2;

	ph = OpenPicture(&r);
	CopyBits(*myPixMap, &thePort->portBits, &r, &r, srcCopy, NIL);
	ClosePicture();
	CopyBits(*myPixMap, &thePort->portBits, &r, &r2, srcCopy, NIL);

	HUnlock(myPixMap);
	HUnlock(myPixels);

	ZeroScrap();
	HLock(ph);
	PutScrap(GetHandleSize(ph), 'PICT', *ph);
	SystemEdit(COPYI-1);	/* so multifinder will take the scrap */
	KillPicture(ph);
}

/* GetBush
 */
Handle GetBush(){
	OSErr	val;
	short	ref;
	Handle	h;
	long	len;
	Str255	s;

	ref = 0;
	h = NIL;
	val = FSOpen("\pbush.ps", 0, &ref);
	if(noErr == val)val = GetEOF(ref, &len);
	if(noErr == val)h = NewHandle(len - 4);
	if(noErr == val && NIL != h){
		HLock(h);
		len = GetHandleSize(h);
		if(noErr == val)val = FSRead(ref, &len, *h);
		HexToBin(h);
		HUnlock(h);
	}
	if(0 != ref){
		FSClose(ref);
	}
	if(noErr != val){
		NumToString(val, s);
		Error(READERROR, s);
		if(NIL != h){
			DisposHandle(h);
			h = NIL;
		}
	}
	return h;
}

/* SkipHeader - advance p to point to data
 */
unsigned char *SkipHeader(p)register unsigned char *p;{
	while( NOT (p[0] == '\r' && p[1] == '0'))
		p++;

	return &p[1];
}

/* HexToBin - h is a locked handle containing text. turn it into binary
	Sorry about this. It is a quick and dirty hex ascii to binary routine.
 */
HexToBin(h)Handle h;{
	register unsigned char *src, *srcMax, *dest;

	src  = dest = (unsigned char *) *h;
	src = SkipHeader(src);
	srcMax = src + GetHandleSize(h);
	while(src < srcMax){
		if(*src >= '0' && *src <= '9'){
			*dest = (*src++ - '0') << 4;

			if(*src >= '0' && *src <= '9'){
				*dest++ |= *src++ - '0';
			}else if(*src >= 'A' && *src <= 'F'){
				*dest++ |= *src++ - 'A' + 10;	
			}else if(*src >= 'a' && *src <= 'f'){
				*dest++ |= *src++ - 'a' + 10;
			}
		}else if(*src >= 'A' && *src <= 'F'){
			*dest = (*src++ - 'A' + 10) << 4;

			if(*src >= '0' && *src <= '9'){
				*dest++ |= *src++ - '0';
			}else if(*src >= 'A' && *src <= 'F'){
				*dest++ |= *src++ - 'A' + 10;	
			}else if(*src >= 'a' && *src <= 'f'){
				*dest++ |= *src++ - 'a' + 10;
			}
		}else if(*src >= 'a' && *src <= 'f'){
			*dest = (*src++ - 'a' + 10) << 4;

			if(*src >= '0' && *src <= '9'){
				*dest++ |= *src++ - '0';
			}else if(*src >= 'A' && *src <= 'F'){
				*dest++ |= *src++ - 'A' + 10;	
			}else if(*src >= 'a' && *src <= 'f'){
				*dest++ |= *src++ - 'a' + 10;
			}
		}else{
			src++;
		}
	}
	SetHandleSize(h, dest - (unsigned char *) *h);
}

bach@vax1.acs.udel.EDU (Baskaran Subramaniam) (09/20/89)

Hi netters,

I am just starting out programming the mac.  I have think c4.0 and think pascal.
But the manuals that came with them are no help to me to start writing
programs for the mac.  Could you please suggest some books that might help.

thanks a lot in advance,

baskaran.