/*************************************************************************** * * NAME * Pack_Frame -- store packed frame to disk * * SYNOPSIS * if (!Pack_Frame( file, bitmapold, bitmapnew, colormap )) * * BPTR file; * struct BitMap *bitmapold, *bitmapnew; * UWORD *colormap; * * DESCRIPTION * Packs an image that is part of an animation in RAM * by saving the XOR of every other frame * and exploiting frame coherence. * * copyright (c) 1987 Martin D. Hash * * LAST EDITED * Martin Hash 22 Aug 1987 * * EDIT HISTORY * 25 Mar 1987 MH Created. * 22 May Changed df1: to frames: * 9 Jun Speeded up playback. * 17 Jul Disk Full. * **********************************************************************/ #include #include #include #include #include "df1:FileCons.h" #include "df1:ANIMCons.h" /* EXTERNAL FUNCTIONS */ BOOL UserRequest(); /* LOCAL CONSTANTS */ #define Abort() goto Write_Error_Exit /* FILE VARIABLES */ static int sizedummy1, sizedummy2; static UWORD *dummy2, *dummy1; /* FUNCTION */ BOOL Pack_Frame( file, bitmapold, bitmapnew, colormap ) BPTR file; struct BitMap *bitmapold, *bitmapnew; UWORD *colormap; { /* LOCAL VARIABLES */ UWORD *offsetptr, value, *ptr1, *ptr2, *position, *dataptr; int width, plane, i, number, maxrows, column, row; ULONG data[8], offset[8], firstpointer = POINTERBLOCK, CMAPsize, FORMsize, DLTAsize; BOOL done, first; ColorReg colorreg; /* CODE */ sizedummy1 = bitmapnew->BytesPerRow/sizeof(UWORD) *bitmapnew->Rows*sizeof(UWORD); if ((dummy1 = (UWORD *)AllocMem( sizedummy1, 0 )) == NULL) { UserRequest( " NOT ENOUGH MEMORY!" ); return FALSE; } sizedummy2 = bitmapold->BytesPerRow/sizeof(UWORD) *bitmapold->Rows*sizeof(UWORD)*1.5; if ((dummy2 = (UWORD *)AllocMem( sizedummy2, 0 )) == NULL) { FreeMem( (UBYTE *)dummy1, sizedummy1 ); UserRequest( " NOT ENOUGH MEMORY!" ); return FALSE; } for (i = 0; i < 8; ++i) { data[i] = 0; offset[i] = 0; } width = bitmapold->BytesPerRow >>1; maxrows = bitmapold->Rows; dataptr = dummy1; offsetptr = dummy2; for (plane = 0; plane < bitmapold->Depth; ++plane) { ptr1 = (UWORD *)bitmapold->Planes[plane]; ptr2 = (UWORD *)bitmapnew->Planes[plane]; done = FALSE; column = 1; row = 1; while (TRUE) { while ((*ptr1 ^ *ptr2) == 0) { ptr1 += width; ptr2 += width; if (++row > maxrows) { row = 1; ptr1 = (UWORD *)bitmapold->Planes[plane] + column; ptr2 = (UWORD *)bitmapnew->Planes[plane] + column; if (++column > width) { *offsetptr = 0xFFFF; done = TRUE; break; } } } if (done) { ++offsetptr; break; } first = TRUE; number = 0; while ((value = *ptr1 ^ *ptr2) != 0) { *dataptr++ = value; if (first) { first = FALSE; position = ptr1; } ptr1 += width; ptr2 += width; ++number; if (++row > maxrows) { row = 1; ptr1 = (UWORD *)bitmapold->Planes[plane] + column; ptr2 = (UWORD *)bitmapnew->Planes[plane] + column; if (++column > width) { done = TRUE; *(offsetptr+2) = 0xFFFF; } break; } } *offsetptr++ = position - (UWORD *)bitmapold->Planes[plane]; *offsetptr++ = number; if (done) { ++offsetptr; break; } } data[plane] = POINTERBLOCK + dataptr - dummy1; offset[plane] = offsetptr - dummy2; } if (Write( file, "FORM", 4*sizeof(char)) == -1) Abort(); DLTAsize = (data[plane-1] + offset[plane-1]) * sizeof(UWORD); FORMsize = (HEADERSIZE*sizeof(char) + HEADERSIZE*sizeof(char) + sizeof(ULONG) + sizeof(ColorReg)*COLORS + HEADERSIZE*sizeof(char) + sizeof(ULONG) + DLTAsize); if (Write( file, &FORMsize, sizeof(ULONG)) == -1) Abort(); if (Write( file, "ILBMCMAP", 8*sizeof(char)) == -1) Abort(); CMAPsize = sizeof(ColorReg)*COLORS; if (Write( file, &CMAPsize, sizeof(ULONG)) == -1) Abort(); for (i = 0; i < COLORS; ++i) { colorreg.red = (*colormap>>4) & 0xF0; colorreg.green = *colormap & 0xF0; colorreg.blue = (*colormap<<4) & 0xF0; if (Write( file, (UBYTE *)&colorreg, sizeof(ColorReg)) == -1) Abort(); ++colormap; } if (Write( file, "DLTA", 4*sizeof(char)) == -1) Abort(); if (Write( file, &DLTAsize, sizeof(ULONG)) == -1) Abort(); for (i = 0; i < plane; ++i) offset[i] += data[plane-1]; if (Write( file, &firstpointer, sizeof(ULONG)) == -1) Abort(); if (Write( file, &data[0], 7*sizeof(ULONG)) == -1) Abort(); if (Write( file, &data[plane-1], sizeof(ULONG)) == -1) Abort(); if (Write( file, &offset[0], 7*sizeof(ULONG)) == -1) Abort(); if (Write( file, dummy1, (data[plane-1]-POINTERBLOCK)*sizeof(UWORD))== -1) Abort(); if (Write( file, dummy2, (offset[plane-1]-data[plane-1])*sizeof(UWORD)) == -1) Abort(); FreeMem((UBYTE *)dummy1, sizedummy1 ); FreeMem((UBYTE *)dummy2, sizedummy2 ); return TRUE; Write_Error_Exit: FreeMem((UBYTE *)dummy1, sizedummy1 ); FreeMem((UBYTE *)dummy2, sizedummy2 ); return FALSE; }