home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 1 / FFMCD01.bin / bbs / libdisks / d700t799 / disk793.lha / Snap / src.lha / src / saveilbm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-15  |  5.5 KB  |  209 lines

  1. /* Auto: make
  2. */
  3. #include <setjmp.h>
  4.  
  5. #define SAFE(cond, jmp_buf)  { if (!(cond)) longjmp(jmp_buf,-1); }
  6.  
  7. IMPORT BYTE TranspBuf[];
  8.  
  9. #define ID(a,b,c,d) ((a << 24L) | (b << 16L) | (c << 8L) | (d))
  10.  
  11. struct ckHdr {
  12.     LONG ChunkName;
  13.     LONG ChunkSize;
  14. };
  15.  
  16. struct BitMapHeader
  17. {
  18.    UWORD w,h;
  19.    WORD  x,y;
  20.    UBYTE nPlanes;
  21.    UBYTE masking;
  22.    UBYTE compression;
  23.    UBYTE pad1;
  24.    UWORD transparentColor;
  25.    UBYTE xAspect, yAspect;
  26.    WORD  pageWidth, pageHeight;
  27. };
  28.  
  29. struct ckHdr FORM = {
  30.     ID('F','O','R','M'),
  31.     0L
  32. };
  33. LONG TYPE = ID('I','L','B','M');
  34.  
  35. struct ckHdr BMHD = {
  36.     ID('B','M','H','D'),
  37.     sizeof(struct BitMapHeader)
  38. };
  39. struct BitMapHeader BMHdr = {
  40.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  41. };
  42.  
  43. struct ckHdr CAMG = {
  44.     ID('C','A','M','G'),
  45.     4L
  46. };
  47. ULONG ViewMode = NULL;
  48.  
  49. struct ckHdr CMAP = {
  50.     ID('C','M','A','P'),
  51.     0L
  52. };
  53.  
  54. struct ckHdr BODY = {
  55.     ID('B','O','D','Y'),
  56.     0L
  57. };
  58.  
  59. UBYTE *buf;
  60. WORD bufcnt;
  61. ULONG totalsize;
  62.  
  63. WORD bump(struct CBFHandle *CBFH, WORD cnt, UBYTE *dataptr, WORD size)
  64. {
  65.     REGISTER LONG tsize = size;
  66.     if (tsize) {
  67.         totalsize += tsize + 1;     /* Don't forget the count-byte */
  68.     }
  69.     if (bufcnt + tsize + 1 >= 4096 || tsize == 0) {
  70.         if (CBFWrite(CBFH, (char *)buf, (LONG)bufcnt) == -1L) {
  71.             return 0;
  72.         }
  73.         bufcnt = 0;
  74.     }
  75.     buf[bufcnt++] = cnt;
  76.     CopyMem((char *)dataptr, (char *)&buf[bufcnt], tsize);
  77.     bufcnt += tsize;
  78.     return 1;
  79. }
  80.  
  81. ULONG WriteBody(BM, CBFH)
  82. struct BitMap *BM;
  83. struct CBFHandle *CBFH;
  84. {
  85.     WORD scanline, plane;
  86.     REGISTER WORD bpr = BM->BytesPerRow;
  87.     REGISTER WORD i, j;
  88.     LONG offset = 0L;
  89.     REGISTER UBYTE data;
  90.     REGISTER UBYTE *bd;
  91.     jmp_buf failure;
  92.  
  93.     totalsize = 0L;
  94.  
  95.     if (!(buf = AllocMem(4096L, MEMF_PUBLIC))) {
  96.         return NULL;
  97.     }
  98.  
  99.     if (setjmp(failure)) {
  100.         FreeMem(buf, 4096L);
  101.         return NULL;
  102.     }
  103.  
  104.     bufcnt = 0;
  105.     for (scanline = 0; scanline < BM->Rows; ++scanline) {
  106.         for (plane = 0; plane < BM->Depth; ++plane) {
  107.             bd = BM->Planes[plane]+offset;
  108.             i = 1;
  109.             j = bpr - 1;
  110.             data = bd[0];
  111.             while (j) {
  112.                 if (bd[i] == data) {        /* Equal bytes? */
  113.                     --i;                    /* First equal byte */
  114.                     if (i > 0) {            /* Old "random" data to save */
  115.                         SAFE(bump(CBFH, (WORD)(i - 1), bd, i), failure);
  116.                     }
  117.                     bd = &bd[i];        /* Start of equal bytes */
  118.                     i = 2;              /* 0 & 1 is equal       */
  119.                     --j;
  120.                     while (i < 128 && j && bd[i] == data) {
  121.                         ++i;
  122.                         --j;
  123.                     }
  124.                     SAFE(bump(CBFH, (WORD)-(i - 1), &bd[i - 1], (WORD)1), failure);
  125.                     goto new_block;
  126.                 } else {                    /* Not equal. Check block range */
  127.                     if (i == 128) {         /* Block limit                  */
  128.                         SAFE(bump(CBFH, (WORD)(i - 1), bd, i), failure);
  129. new_block:
  130.                         bd = &bd[i];  /* Start new block              */
  131.                         i = 0;
  132.                         if (j == 0) {
  133.                             break;
  134.                         }
  135.                     }
  136.                 }
  137.                   /* Different byte or a new start */
  138.                 data = bd[i];               /* New possible equal       */
  139. next_byte:
  140.                 ++i;
  141.                 --j;
  142.             }
  143.             if (i != 0) {                   /* Data to save */
  144.                 SAFE(bump(CBFH, (WORD)(i - 1), bd, i), failure);
  145.             }
  146.         }
  147.         offset += BM->BytesPerRow;
  148.     }
  149.       /* Flush any bytes left if the buffer */
  150.     SAFE(bump(CBFH, (WORD)0, NULL, (WORD)0), failure);
  151.     FreeMem(buf, 4096L);
  152.     return totalsize;
  153. }
  154.  
  155. WORD SaveGS(GS, CBFH)
  156. struct GfxSnap *GS;
  157. struct CBFHandle *CBFH;
  158. {
  159.     ULONG BODYPos;
  160.     UBYTE *oldtitle;
  161.     jmp_buf failure;
  162.  
  163.     oldtitle = GS->window->Title;
  164.     SetWindowTitles(GS->window, "Saving...", (char *)-1);
  165.  
  166.     BMHdr.w = GS->BM.BytesPerRow * 8;
  167.     BMHdr.h = GS->height;
  168.     BMHdr.x = BMHdr.y = 0;
  169.     BMHdr.nPlanes = GS->depth;
  170.     BMHdr.masking = 0;
  171.     BMHdr.compression = 1;
  172.     BMHdr.transparentColor = dectoint(TranspBuf);
  173.     BMHdr.xAspect = BMHdr.xAspect = 1;
  174.     BMHdr.pageWidth = GS->pagew;
  175.     BMHdr.pageHeight = GS->pageh;
  176.     ViewMode = GS->viewmode;
  177.  
  178.     CMAP.ChunkSize = (LONG)3 * (GS->viewmode & HAM ? 16 : 1L << GS->depth);
  179.  
  180.     CBFInit(CBFH);
  181.  
  182.     if (setjmp(failure)) {
  183.         CBFEndWrite(CBFH);
  184.         return 0;
  185.     }
  186.  
  187.     SAFE(CBFWrite(CBFH, (char *)&FORM,
  188.       (LONG)(sizeof(FORM) + sizeof(TYPE) +
  189.              sizeof(BMHD) + sizeof(BMHdr) +
  190.              sizeof(CAMG) + sizeof(ViewMode) +
  191.              sizeof(CMAP))) != -1L, failure);
  192.     SAFE(CBFWrite(CBFH, (char *)&GS->rgb[0], CMAP.ChunkSize) != -1L, failure);
  193.     BODYPos = CBFSeek(CBFH, 0L, OFFSET_CURRENT);
  194.     SAFE(CBFWrite(CBFH, (char *)&BODY, (LONG)sizeof(BODY)) != -1L, failure);
  195.     SAFE(BODY.ChunkSize = WriteBody(&GS->BM, CBFH), failure);
  196.     FORM.ChunkSize = BODYPos - sizeof(FORM) + sizeof(BODY) + BODY.ChunkSize;
  197.     if (FORM.ChunkSize & 1) {                       /* Odd size */
  198.         SAFE(CBFWrite(CBFH, "X", 1L) != -1L, failure);
  199.         ++FORM.ChunkSize;
  200.     }
  201.     CBFSeek(CBFH, 0L, OFFSET_BEGINNING);
  202.     CBFWrite(CBFH, (char *)&FORM, (LONG)sizeof(FORM));
  203.     CBFSeek(CBFH, BODYPos, OFFSET_BEGINNING);
  204.     CBFWrite(CBFH, (char *)&BODY, (LONG)sizeof(BODY));
  205.     CBFEndWrite(CBFH);
  206.     SetWindowTitles(GS->window, (char *)oldtitle, (char *)-1);
  207.     return 1;
  208. }
  209.