/* ** ** $Id: GrabScreen.c,v 21.1 92/05/18 01:05:18 chris Exp $ ** $Revision: 21.1 $ ** ** $Filename: Examples/GrabScreen.c $ ** $Author: Christian A. Weber $ ** $Release: 21.1 $ ** $Date: 92/05/18 01:05:18 $ ** ** IFF library example program. Compile with Lattice C 5.x. ** This program saves the contents of the frontmost screen as an IFF file ** with filename 'RAM:grabscreen.pic'. ** This example makes use of the IFFL_PushChunk() / IFFL_WriteChunkBytes() / ** IFFL_PopChunk() functions, it does not use IFFL_SaveBitMap(). ** ** COPYRIGHT (C) 1987-1992 BY CHRISTIAN A. WEBER, BRUGGERWEG 2, ** CH-8037 ZUERICH, SWITZERLAND. ** THIS FILE MAY BE FREELY DISTRIBUTED. USE AT YOUR OWN RISK. ** */ #include #include #include #include #include #include #include #include #include /* IFF library include file */ /* ** Flags that should be masked out of old 16-bit CAMG before save or use. ** Note that 32-bit mode id (non-zero high word) bits should not be twiddled */ #define OLDCAMGMASK (~(SPRITES|VP_HIDE|GENLOCK_AUDIO|GENLOCK_VIDEO)) #define MAXSAVEDEPTH 24 #define BODYBUFSIZE 10000 #define MAXPACKEDSIZE(s) ((s)*2) /* ** Masking techniques */ #define mskNone 0 #define mskHasMask 1 #define mskHasTransparentColor 2 #define mskLasso 3 /* ** Compression techniques */ #define cmpNone 0 #define cmpByteRun1 1 /**************************************************************************** ** Globals */ struct Library *IFFBase; char version[] = "\0$VER: GrabScreen 21.2 by Christian A. Weber"; /**************************************************************************** ** This is an example implementation of an IFF writer. It writes the ** contents of a screen to an IFF ILBM file. ** Basically, this routine does the same as IFFL_SaveBitMap(), but it is ** here anyway to show you how to write an IFF file using iff.library's ** generic write functions. */ BOOL MySaveScreen(struct Screen *screen,char *filename) { IFFL_HANDLE iff; struct BitMap *bitmap = &screen->BitMap; BOOL result = FALSE; /* ** Open the file for writing */ if(iff = IFFL_OpenIFF(filename,IFFL_MODE_WRITE)) { struct IFFL_BMHD bmhd; ULONG modeid; UBYTE *colortable; int count; /* ** Prepare the BMHD structure */ bmhd.w = screen->Width; bmhd.h = screen->Height; bmhd.x = screen->LeftEdge; /* Not very useful :-) */ bmhd.y = screen->TopEdge; bmhd.nPlanes = bitmap->Depth; bmhd.masking = mskNone; bmhd.compression = cmpByteRun1; bmhd.pad1 = 0; bmhd.transparentColor = 0; bmhd.xAspect = screen->Width; bmhd.yAspect = screen->Height; bmhd.pageWidth = screen->Width; bmhd.pageHeight = screen->Height; /* ** Create the BMHD chunk. (goto considered useful :-)) */ if(IFFL_PushChunk(iff,ID_ILBM,ID_BMHD)) { if(!IFFL_WriteChunkBytes(iff,&bmhd,sizeof(bmhd))) { printf("Error writing BMHD data.\n"); goto error; } if(!IFFL_PopChunk(iff)) { printf("Error closing BMHD chunk.\n"); goto error; } } else { printf("Error creating BMHD chunk.\n"); goto error; } /* ** Create the CMAP chunk. */ count = screen->ViewPort.ColorMap->Count; if(colortable = AllocMem(count * 3, MEMF_ANY)) { int i; for(i=0; iViewPort.ColorMap,i); colortable[i*3+0] = (rgb4 >> 4) & 0xF0; colortable[i*3+0] |= colortable[i*3+0] >> 4; colortable[i*3+1] = (rgb4 ) & 0xF0; colortable[i*3+1] |= colortable[i*3+1] >> 4; colortable[i*3+2] = (rgb4 << 4) & 0xF0; colortable[i*3+2] |= colortable[i*3+2] >> 4; } if(IFFL_PushChunk(iff,ID_ILBM,ID_CMAP)) { if(!IFFL_WriteChunkBytes(iff,colortable,count * 3)) { printf("Error writing CMAP data.\n"); goto error; } if(!IFFL_PopChunk(iff)) { printf("Error closing CMAP chunk.\n"); goto error; } } else { printf("Error creating CMAP chunk.\n"); goto error; } FreeMem(colortable,count * 3); } /* ** Get the viewport's modes for the CAMG chunk. */ modeid = (GfxBase->LibNode.lib_Version >= 36) ? GetVPModeID(&screen->ViewPort) : (screen->ViewPort.Modes&OLDCAMGMASK); if(IFFL_PushChunk(iff,ID_ILBM,ID_CAMG)) { if(!IFFL_WriteChunkBytes(iff,&modeid,sizeof(modeid))) { printf("Error writing CAMG data.\n"); goto error; } if(!IFFL_PopChunk(iff)) { printf("Error closing CAMG chunk.\n"); goto error; } } else { printf("Error creating CAMG chunk.\n"); goto error; } /* ** Generate BODY */ if(IFFL_PushChunk(iff,ID_ILBM,ID_BODY)) { UBYTE *bodybuf; if(bodybuf = AllocMem(BODYBUFSIZE,MEMF_ANY)) { UBYTE *planes[MAXSAVEDEPTH]; int row,rowbytes,iplane,bodysize=0; rowbytes = bitmap->BytesPerRow; /* ** Copy the plane pointers into the local array "planes" */ for(iplane=0; iplane < bmhd.nPlanes; ++iplane) { planes[iplane] = bitmap->Planes[iplane]; } for(row=0; row < bmhd.h; ++row) { for(iplane=0; iplane < bmhd.nPlanes; ++iplane) { int comprsize; /* ** To speed up things, we collect as much data ** as possible in bodybuf before we write it out. */ if(bodysize > (BODYBUFSIZE-MAXPACKEDSIZE(rowbytes))) { if(!IFFL_WriteChunkBytes(iff,bodybuf,bodysize)) { printf("Error writing BODY data.\n"); goto error; } bodysize = 0; } /* ** Compress the next row */ if(!(comprsize = IFFL_CompressBlock(planes[iplane], bodybuf+bodysize,rowbytes,IFFL_COMPR_BYTERUN1))) { printf("Error compressing BODY data.\n"); goto error; } bodysize += comprsize; planes[iplane] += rowbytes; } } /* ** Now we're done, so flush the body data buffer */ if(bodysize) { if(!IFFL_WriteChunkBytes(iff,bodybuf,bodysize)) { printf("Error writing BODY data.\n"); goto error; } } FreeMem(bodybuf,BODYBUFSIZE); } else { printf("No memory for BODY buffer.\n"); goto error; } if(!IFFL_PopChunk(iff)) { printf("Error closing BODY chunk.\n"); goto error; } /* ** If we get here, everything was fine. */ result = TRUE; } else { printf("Error creating BODY chunk.\n"); goto error; } error: IFFL_CloseIFF(iff); } return result; } /**************************************************************************** ** Main program */ int main(int argc, char **argv) { int result = RETURN_FAIL; if(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)) { if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)) { /* ** For the new functions we need at least version 21 of iff.library. */ if(IFFBase = OpenLibrary(IFFNAME,21)) { /* ** Note that we don't lock the screen, so it might go away while ** we're writing its contents to the file, and the picture may ** then contain garbage. */ MySaveScreen(IntuitionBase->FirstScreen,"RAM:grabscreen.pic"); result = RETURN_OK; CloseLibrary(IFFBase); } else printf("Can't open iff.library V21+\n"); CloseLibrary(IntuitionBase); } else printf("Can't open intuition.library!\n"); CloseLibrary(GfxBase); } else printf("Can't open graphics.library!\n"); return result; }