This is getmac.c in view mode; [Download] [Up]
/* * showImage.c - Read an RLE file and show it on the Mac screen under MPW * * Author: Spencer Thomas (LSC version) * University of Utah * * Port to MPW by * John Peterson * Apple Computer Inc. * Date: Mon Apr 11 1988 * * 17-Jul-89 - Fixed to run with 32 Bit Quickdraw and MPW 3.0 * */ #define __ALLNU__ /* Enable IM v.5 stuff. Gag. */ #include <QuickDraw.h> #include <Windows.h> #include <Dialogs.h> #include <Menus.h> #include <Events.h> #include <Packages.h> #include <Desk.h> #include <CursorCtl.h> #include <math.h> #include <stdio.h> #include <rle.h> /* * Global variables */ GrafPtr screenPort; /* Window manager's port */ Point dlogOrg; /* Where to put dialog windows */ FILE * rleFile; /* input file */ char rleName[64]; /* Name of input file */ Boolean doneFlag; Boolean dodither; /* Dither or not? */ char * malloc(); /* Needs to be said */ /* Restrict new color to 0::255 for dithering */ #define ADJUST( amt ) ( (amt) < 0 ? 0 : ((amt) > 255 ? 255 : (amt)) ) struct imgBuffers { rle_pixel *buffers[3]; CGrafPort imgPort; int pixMaxY; GDHandle pixDevice; }; static WindowPtr imageWin = nil; WindowPtr makeWindow(); /* * The existence of this macro provides some clue as to how ghastly * debugging Macintosh programs is. Real memory management is coming * one of these years... */ #ifdef DEBUG # define MSG(msg) fprintf(stderr, "Debug--> %s\n", msg) #else # define MSG(msg) #endif int disp_y = -1; /* How far we got before being interrupted */ showImage() { if ( imageWin != nil ) { imgWinClose(); imageWin = nil; } rle_dflt_hdr.rle_file = rleFile; if ( rle_get_error( rle_get_setup( &rle_dflt_hdr ), "GetMac", rleName ) ) return; RLE_CLR_BIT( rle_dflt_hdr, RLE_ALPHA ); if ((rle_dflt_hdr.ncolors != 1) && (rle_dflt_hdr.ncolors != 3)) { fprintf(stderr, "getmac: Sorry - only monochrome and RGB images\n"); exit(-1); } MSG("opened the_hdr"); if ( (imageWin = makeWindow( &rle_dflt_hdr )) == nil ) return; MSG("made window"); readImage( &rle_dflt_hdr ); MSG("Drawing image"); disp_y = 0; drawImage( &rle_dflt_hdr ); } redrawImage() { if ( disp_y == -1 ) { disp_y = 0; } } imgWinUpdate() { disp_y = 0; drawImage( &rle_dflt_hdr ); } imgWinClose() { struct imgBuffers *buffers; int i; if ( imageWin ) { buffers = (struct imgBuffers *)((WindowPeek)imageWin)->refCon; for (i = 0; i < rle_dflt_hdr.ncolors; i++) free( buffers->buffers[i] ); if ( buffers->pixMaxY > 0 ) { free( (*buffers->imgPort.portPixMap)->baseAddr ); CloseCPort( &buffers->imgPort ); } free( buffers ); CloseWindow( imageWin ); imageWin = nil; } } myWindowClobber() { WindowPtr theWindow; GetPort( &theWindow ); DisposeWindow( theWindow ); } imgWinMouse( thePoint ) Point thePoint; { int xsize, ysize; long idx; struct imgBuffers *buffers = (struct imgBuffers *)((WindowPeek)imageWin)->refCon; int r, g, b; RGBColor theColor; ysize = rle_dflt_hdr.ymax; xsize = rle_dflt_hdr.xmax + 1; idx = (long)xsize * (long)(ysize - thePoint.v) + (long)thePoint.h; r = buffers->buffers[0][idx]; if (rle_dflt_hdr.ncolors == 3) { g = buffers->buffers[1][idx]; b = buffers->buffers[2][idx]; } else g = b = buffers->buffers[0][idx]; GetCPixel( thePoint.h, thePoint.v, &theColor ); fprintf( stderr, "Pixel at ( %d, %d ) = [ %u, %u, %u ] -> [ %u, %u, %u ]\n", thePoint.h, ysize - thePoint.v, r<<8, g<<8, b<<8, theColor.red, theColor.green, theColor.blue ); #ifdef notdef if ( buffers->pixMaxY > 0 ) { GetPort( &oldPort ); SetPort( &buffers->imgPort ); pixcol.rgb = theColor; pixcol.value = Color2Index( &pixcol.rgb );; gotcol.value = pixcol.value; Index2Color( gotcol.value, &gotcol.rgb ); fprintf( stderr, " color maps to index %d -> [ %u, %u, %u ]\n", pixcol.value, gotcol.rgb.red, gotcol.rgb.green, gotcol.rgb.blue ); SetPort( oldPort ); } #endif }; imgWinIdle() { if ( disp_y != -1 ) drawImage( &rle_dflt_hdr ); } WindowPtr makeWindow( the_hdr ) rle_hdr * the_hdr; { WindowPtr win; Rect wRect; Str255 wTitle; int xsize, ysize; struct imgBuffers *buffers; int i; the_hdr->xmax -= the_hdr->xmin; the_hdr->xmin = 0; the_hdr->ymax -= the_hdr->ymin; the_hdr->ymin = 0; xsize = the_hdr->xmax - the_hdr->xmin + 1; ysize = the_hdr->ymax - the_hdr->ymin + 1; MSG("Allocating buffers"); buffers = (struct imgBuffers *) malloc( sizeof(struct imgBuffers) ); for ( i = 0; i < 3; i++ ) buffers->buffers[i] = nil; for ( i = 0; i < the_hdr->ncolors; i++) buffers->buffers[i] = (rle_pixel *)malloc( (long)xsize * (long)(ysize+1) ); buffers->pixMaxY = -1; /* Nothing there yet */ MSG("Got buffers"); if ( buffers->buffers[0] == nil || ((the_hdr->ncolors == 3) && (buffers->buffers[1] == nil || buffers->buffers[2] == nil ))) { if ( buffers->buffers[0] != nil ) free( buffers->buffers[0] ); if ( buffers->buffers[1] != nil ) free( buffers->buffers[1] ); free( buffers ); fprintf( stderr, "Not enough memory to save image\n" ); return nil; } MSG("Really got buffers"); wRect.left = 10; wRect.top = 40; wRect.right = wRect.left + xsize; wRect.bottom = wRect.top + ysize; strcpy( wTitle, rleName ); c2pstr( wTitle ); MSG("Making new window"); /* wTitle doesn't work for some reason. */ win = NewCWindow( nil, &wRect, wTitle, true, noGrowDocProc, (WindowPtr) -1, true, (long) buffers ); MSG("Window made"); if ( win == nil ) return nil; return win; } readImage( the_hdr ) rle_hdr * the_hdr; { struct imgBuffers *buffers = (struct imgBuffers *)((WindowPeek)imageWin)->refCon; rle_pixel *scans[3]; int y, i, xsize; fprintf(stderr, "Reading file..." ); xsize = the_hdr->xmax + 1; for ( y = 0; y <= the_hdr->ymax; y++ ) { SpinCursor( (short) 1 ); for ( i = 0; i < the_hdr->ncolors; i++ ) scans[i] = &buffers->buffers[i][(long)y * (long)xsize]; rle_getrow( the_hdr, scans ); } fprintf( stderr, "\n" ); } drawImage( the_hdr ) rle_hdr * the_hdr; { int ysize, xsize, x, y; register int cval; struct imgBuffers *buffers = (struct imgBuffers *)((WindowPeek)imageWin)->refCon; register rle_pixel *rptr, *gptr, *bptr; long rdiff, gdiff, bdiff; EventRecord theEvent; CGrafPtr oldPort; Rect srcDestRect; ColorSpec pixcol, gotcol; GDHandle oldDevice; long pixidx; int pixoffset, mask, depth; char * pixel; ysize = the_hdr->ymax; xsize = the_hdr->xmax + 1; if ( buffers->pixMaxY < ysize ) { MSG("GetOldPort"); GetPort( (GrafPtr *) &oldPort ); MSG("Got Port"); oldDevice = GetGDevice(); MSG("Got port & device"); if ( buffers->pixMaxY == -1 ) createPix( buffers, xsize, ysize + 1 ); if ( buffers->pixMaxY != -2 ) { if ( buffers->pixMaxY >= 0 ) { SetRect( &srcDestRect, 0, ysize - buffers->pixMaxY, xsize, ysize + 1 ); CopyBits( (BitMap *)(*buffers->imgPort.portPixMap), &imageWin->portBits, &srcDestRect, &srcDestRect, 64, nil ); disp_y = buffers->pixMaxY + 1; } SetPort( (GrafPtr) &buffers->imgPort ); /* Set theGDevice to device with maximum pixel depth */ SetGDevice( buffers->pixDevice ); } else SetPort( (GrafPtr) oldPort ); MSG("Set up Port"); if (disp_y < ysize) fprintf( stderr, "Drawing Image...\n" ); rptr = &buffers->buffers[0][disp_y*xsize]; if (the_hdr->ncolors == 3) { gptr = &buffers->buffers[1][disp_y*xsize]; bptr = &buffers->buffers[2][disp_y*xsize]; } else { gptr = rptr; bptr = rptr; /* Mild kludge to get monochrome */ } depth = (*buffers->imgPort.portPixMap)->pixelSize; mask = ((1 << depth) - 1); if (depth == 32) /* Hi Bruce! (32 bit QD) */ { for (y = disp_y; y <= ysize; y++ ) { SpinCursor( (short) -1 ); pixidx = ((long)(ysize - y) * (long)((*buffers->imgPort.portPixMap)->rowBytes & 0x7fff)); pixel = (char *)((*buffers->imgPort.portPixMap)->baseAddr) + pixidx; for ( x = 0; x < xsize; x++ ) { *pixel++ = 0; /* QD32 ignores alpha */ *pixel++ = *rptr++; *pixel++ = *gptr++; *pixel++ = *bptr++; } if ( buffers->pixMaxY != -2 ) { SetRect( &srcDestRect, 0, ysize - y, xsize, ysize - y + 1 ); CopyBits( (BitMap *)(*buffers->imgPort.portPixMap), &imageWin->portBits, &srcDestRect, &srcDestRect, 64, nil ); buffers->pixMaxY = y; } if ( EventAvail( (short) mDownMask|mUpMask|keyDownMask, &theEvent)) { disp_y = y + 1; /* for later continuation */ break; } } } else for ( y = disp_y; y <= ysize; y++ ) { SpinCursor( (short) -1 ); pixidx = ((long)(ysize - y) * (long)((*buffers->imgPort.portPixMap)->rowBytes & 0x7fff)); pixel = (char *)((*buffers->imgPort.portPixMap)->baseAddr) + pixidx; pixoffset = 8; for ( x = 0; x < xsize; x++ ) { pixcol.rgb.red = *rptr++ << 8; pixcol.rgb.green = *gptr++ << 8; pixcol.rgb.blue = *bptr++ << 8; pixcol.value = (short) Color2Index( &pixcol.rgb ); pixoffset -= depth; if ( pixoffset < 0 ) { pixoffset += 8; pixel++; } *pixel &= ~mask << pixoffset; *pixel |= (pixcol.value & mask) << pixoffset; if ( dodither ) { Index2Color( pixcol.value, &gotcol.rgb ); rdiff = (((long)gotcol.rgb.red - (long)pixcol.rgb.red) / 3) >> 8; gdiff = (((long)gotcol.rgb.green - (long)pixcol.rgb.green) / 3) >> 8; bdiff = (((long)gotcol.rgb.blue - (long)pixcol.rgb.blue) / 3) >> 8; cval = (int)*(rptr + xsize - 1) - rdiff; *(rptr + xsize - 1) = ADJUST( cval ); cval = (int)*(gptr + xsize - 1) - gdiff; *(gptr + xsize - 1) = ADJUST( cval ); cval = (int)*(bptr + xsize - 1) - bdiff; *(bptr + xsize - 1) = ADJUST( cval ); cval = (int)*(rptr) - rdiff; *(rptr) = ADJUST( cval ); cval = (int)*(gptr) - gdiff; *(gptr) = ADJUST( cval ); cval = (int)*(bptr) - bdiff; *(bptr) = ADJUST( cval); cval = (int)*(rptr + xsize) - rdiff; *(rptr + xsize) = ADJUST( cval ); cval = (int)*(gptr + xsize) - gdiff; *(gptr + xsize) = ADJUST( cval ); cval = (int)*(bptr + xsize) - bdiff; *(bptr + xsize) = ADJUST( cval ); } } if ( buffers->pixMaxY != -2 ) { SetRect( &srcDestRect, 0, ysize - y, xsize, ysize - y + 1 ); CopyBits( (BitMap *)(*buffers->imgPort.portPixMap), &imageWin->portBits, &srcDestRect, &srcDestRect, 64, nil ); buffers->pixMaxY = y; } if ( EventAvail( (short) mDownMask|mUpMask|keyDownMask, &theEvent)) { disp_y = y + 1; /* for later continuation */ break; } } SetGDevice( oldDevice ); SetPort( (GrafPtr) oldPort ); if ( y >= ysize ) { disp_y = -1; } } else { SetRect( &srcDestRect, 0, 0, xsize, ysize + 1 ); CopyBits( (BitMap *)(*buffers->imgPort.portPixMap), &imageWin->portBits, &srcDestRect, &srcDestRect, 64, nil ); disp_y = -1; } } /* Code from TN120 */ createPix( buffers, xsize, ysize ) struct imgBuffers * buffers; int xsize, ysize; { Rect globRect, bRect; Ptr myBits; long sizeOfOff, offRowBytes; int theDepth, i, err; CTabHandle ourCMHandle; GDHandle theMaxDevice, oldDevice; PixMap * myPix; MSG("createPix"); /* Way big for many screens. May lose if screens are on the left. */ SetRect( &globRect, -3000, -3000, 3000, 3000 ); SetRect( &bRect, 0, 0, xsize, ysize ); /* Figure out how much space we need * Call GetMaxDevice and get the pixel map from that -- * we do this to cover the case where the pixel image * spans multiple devices (of possibly different depths */ theMaxDevice = GetMaxDevice( &globRect ); buffers->pixDevice = theMaxDevice; /* Set theGDevice to device with maximum pixel depth */ oldDevice = GetGDevice(); SetGDevice( theMaxDevice ); /* Open a CGrafPort for offscreen drawing */ OpenCPort( &buffers->imgPort ); theDepth = (*buffers->imgPort.portPixMap)->pixelSize; /* Calculate size of pixel image */ offRowBytes = ((((long)theDepth * (long)xsize) + 15L) / 16L) * 2L; sizeOfOff = (long)ysize * offRowBytes; myBits = (Ptr)malloc( sizeOfOff ); if ( myBits == nil) { fprintf( stderr, "Not enough memory for pixmap\n" ); buffers->pixMaxY = -2; /* No Pixmap at all */ goto done; } /* Fix up location/size info */ myPix = *buffers->imgPort.portPixMap; myPix->baseAddr = myBits; myPix->rowBytes = offRowBytes | 0x8000; /* Mark as pixmap */ myPix->bounds = bRect; /* Clone color table from MaxDevice */ ourCMHandle = (*(*theMaxDevice)->gdPMap)->pmTable; err = HandToHand((Handle *)&ourCMHandle); if ( err != 0 ) { fprintf( stderr, "Error cloning color table: %d\n", err ); free( myBits ); buffers->pixMaxY = -2; goto done; } for ( i = 0; i <= (*ourCMHandle)->ctSize; i++ ) (*ourCMHandle)->ctTable[i].value = i; /* Put in indices */ /* Clear high bit of transIndex to indicate it's a PixMap color table */ (*ourCMHandle)->ctFlags &= 0x7fff; (*buffers->imgPort.portPixMap)->pmTable = ourCMHandle; /* Put color table into offscreen map */ done: /* Restore GDevice */ SetGDevice( oldDevice ); } /* * Process Mac events. Spencer (wisely) did all of this with the TranSkel * package. I've re-invented it here to reduce the volume of distributed * source code. * * Friends, let me quote from the MPW manual: * * "The creation of windows, use of graphics, and event processing by tools is * largely unexplored area in the MPW environment. MPW aims to support these * types of tools; however, little work has been done so far in this area, and * unknown restrictions may exist." * * Makes ya feel good, huh? */ #define GrayRgn (*((RgnHandle *) 0x9ee)) /* Indulge. Have a magic cookie. */ processEvent( theEvent ) EventRecord * theEvent; { Point evtPt; GrafPtr evtPort, tmpPort; short evtPart; Rect r; evtPt = theEvent->where; switch ( theEvent->what ) { case nullEvent: break; case mouseDown: evtPart = FindWindow( evtPt, (WindowPtr *) &evtPort ); switch ( evtPart ) { case inSysWindow: SystemClick( theEvent, evtPort ); break; case inGrow: /* DoGrow */ break; case inDrag: r = (*GrayRgn)->rgnBBox; InsetRect( &r, 4, 4 ); DragWindow( evtPort, evtPt, &r ); break; case inGoAway: doneFlag = true; break; case inContent: { if (evtPort != FrontWindow() ) SelectWindow( evtPort ); else imgWinMouse( evtPt ); break; } } case keyDown: if ((theEvent->message & charCodeMask) == 'q') { doneFlag = true; } case updateEvt: /* Note - while running as an MPW tool, this will get update events * for MPW windows. Since it can't update them for MPW, it * ignores them until them until it exits. */ GetPort( &tmpPort ); SetPort( imageWin ); BeginUpdate( imageWin ); imgWinUpdate (); EndUpdate( imageWin ); SetPort( tmpPort ); break; case activateEvt: SetPort( imageWin ); break; } } main( argc, argv, env ) int argc; char **argv; char **env; { Boolean haveEvent; EventRecord theEvent; short eventMask = everyEvent; int ditherFlag = 0; char * filename = NULL; doneFlag = false; /* FlushEvents (everyEvent - diskMask, 0 ); */ InitGraf (&qd.thePort); InitCursorCtl( NULL ); if (! scanargs( argc, argv, "% d%- rlefile%s", &ditherFlag, &filename )) exit(-1); dodither = (Boolean) ! ditherFlag; if (filename) { rleFile = fopen( argv[1], "r" ); strcpy( rleName, argv[1] ); } else { rleFile = stdin; strcpy( rleName, "RLE Image" ); } if (! rleFile) { fprintf( stderr, "Can't open %s\n", argv[1] ); exit(-1); } showImage (); fclose( rleFile ); doneFlag = false; Show_Cursor( ARROW_CURSOR ); while ( ! doneFlag ) { SystemTask(); haveEvent = GetNextEvent( eventMask, &theEvent ); if (haveEvent) processEvent( &theEvent ); } imgWinClose(); fprintf( stderr, "Done.\n" ); exit( 0 ); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.