diff options
Diffstat (limited to 'Examples')
-rw-r--r-- | Examples/GrabScreen.c | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/Examples/GrabScreen.c b/Examples/GrabScreen.c new file mode 100644 index 0000000..2575d1c --- /dev/null +++ b/Examples/GrabScreen.c @@ -0,0 +1,337 @@ +/* +** +** $Id: $ +** $Revision: $ +** +** $Filename: Examples/GrabScreen.c $ +** $Author: Christian A. Weber $ +** $Release: 21.1 $ +** $Date: 92/05/18 15:29: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 <proto/exec.h> +#include <exec/memory.h> +#include <proto/graphics.h> +#include <graphics/gfxbase.h> +#include <proto/intuition.h> +#include <intuition/intuitionbase.h> +#include <dos/dos.h> + +#include <stdio.h> + +#include <libraries/iff.h> /* 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.1 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. +*/ + +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; i<count; ++i) + { + UWORD rgb4 = GetRGB4(screen->ViewPort.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; +} |