ftp.nice.ch/pub/next/unix/graphics/urt.3.0.s.tar.gz#/urt.3.0.s/get/getmac/getmac.c

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.