home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / gifmachine_458.lzh / GIFMachine / Sources / writeiff.c < prev    next >
C/C++ Source or Header  |  1991-02-15  |  10KB  |  433 lines

  1. /* Copyright 1990 by Christopher A. Wichura.
  2.    See file GIFMachine.doc for full description of rights.
  3. */
  4.  
  5. #include "GIFMachine.h"
  6. #include <iff/ILBM.h>
  7. #include <libraries/iffparse.h>
  8. #include <graphics/view.h>
  9. #include <proto/iffparse.h>
  10. #include <dos/datetime.h>
  11.  
  12. extern struct GIFdescriptor gdesc;
  13. EXTERNBITPLANE;
  14.  
  15. extern struct MinList CommentList;
  16.  
  17. extern char *AbortMsg;
  18.  
  19. extern UWORD *SHAMmem;
  20. BYTE *PlaneBuf;
  21.  
  22. BOOL Laced;
  23.  
  24. UBYTE *Planes[24];
  25.  
  26. static UBYTE CompBuf[256];
  27. static ULONG PlanePos;
  28.  
  29. /* our version number stuff */
  30. extern ULONG __far Version;
  31. extern ULONG __far Revision;
  32.  
  33. BOOL WriteIFF(char *tofile, BOOL DeepFlag)
  34. {
  35.     register struct IFFHandle *iff;
  36.     register int index;
  37.     register ULONG ChunkSize;
  38.     register UWORD current;
  39.     char WrittenBy[40];
  40.  
  41.     ColorRegister ColourBuf;
  42.     BitMapHeader  bmh;
  43.  
  44.     PutStr("...Writing IFF file.");
  45.  
  46.     if (!(iff = AllocIFF())) {
  47.         PutStr("\n......Error allocating IFF handle.\n");
  48.         return TRUE;
  49.     }
  50.  
  51.     if (!(iff->iff_Stream = Open(tofile, MODE_NEWFILE))) {
  52.         MyPrintf("\n......Error %ld trying to create %s.", IoErr(), tofile);
  53.         goto EndWriteIFF;
  54.     }
  55.  
  56.     InitIFFasDOS(iff);
  57.  
  58.     if (OpenIFF(iff, IFFF_WRITE)) {
  59.         PutStr("\n......Error writing to IFF.\n");
  60.         goto EndWriteIFF;
  61.     }
  62.  
  63.     if (PushChunk(iff, ID_ILBM, FORM, IFFSIZE_UNKNOWN)) {
  64.         PutStr("\n......Error writing to IFF.\n");
  65.         goto EndWriteIFF;
  66.     }
  67.  
  68.     if (PushChunk(iff, 0L, MakeID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
  69.         PutStr("\n......Error writing to IFF.\n");
  70.         goto EndWriteIFF;
  71.     }
  72.  
  73.     MySPrintf(WrittenBy, "Written by GIFMachine v%ld.%ld on ", Version, Revision);
  74.  
  75.     if (WriteChunkBytes(iff, (APTR)&WrittenBy, strlen(WrittenBy)) != strlen(WrittenBy)) {
  76.         PutStr("\n......Error writing to IFF.\n");
  77.         goto EndWriteIFF;
  78.     }
  79.  
  80.     {
  81.         struct DateTime dat;
  82.         char Date[LEN_DATSTRING + 1];
  83.         int DateLength;
  84.  
  85.         DateStamp(&dat.dat_Stamp);
  86.         dat.dat_Format = FORMAT_DOS;
  87.         dat.dat_Flags = 0;
  88.         dat.dat_StrDay = NULL;
  89.         dat.dat_StrDate = Date;
  90.         dat.dat_StrTime = NULL;
  91.  
  92.         memset(Date, 0, LEN_DATSTRING + 1);
  93.         DateToStr(&dat);
  94.  
  95.         DateLength = strlen(Date) + 1;
  96.         if (WriteChunkBytes(iff, (APTR)&Date, DateLength) != DateLength) {
  97.             PutStr("\n......Error writing to IFF.\n");
  98.             goto EndWriteIFF;
  99.         }
  100.     }
  101.  
  102.     if (PopChunk(iff)) {
  103.         PutStr("\n......Error writing to IFF.\n");
  104.         goto EndWriteIFF;
  105.     }
  106.  
  107.     {
  108.         struct CommentNode *cn;
  109.         char ANNObuf[1];
  110.  
  111. #define C_BLOCK_ID "GIF Comment Block: "
  112.  
  113.         ANNObuf[0] = 0;
  114.  
  115.         while (cn = (struct CommentNode *)RemHead((struct List *)&CommentList)) {
  116.             if (PushChunk(iff, 0L, MakeID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
  117.                 PutStr("\n......Error writing to IFF.\n");
  118.                 goto EndWriteIFF;
  119.             }
  120.  
  121.             if (WriteChunkBytes(iff, (APTR)C_BLOCK_ID, strlen(C_BLOCK_ID)) != strlen(C_BLOCK_ID)) {
  122.                 PutStr("\n......Error writing to IFF.\n");
  123.                 goto EndWriteIFF;
  124.             }
  125.  
  126.             if (WriteChunkBytes(iff, (APTR)cn->cn_Comment, cn->cn_CommentLength) != cn->cn_CommentLength) {
  127.                 PutStr("\n......Error writing to IFF.\n");
  128.                 goto EndWriteIFF;
  129.             }
  130.  
  131.             if (WriteChunkBytes(iff, (APTR)ANNObuf, 1) != 1) {
  132.                 PutStr("\n......Error writing to IFF.\n");
  133.                 goto EndWriteIFF;
  134.             }
  135.  
  136.             if (PopChunk(iff)) {
  137.                 PutStr("\n......Error writing to IFF.\n");
  138.                 goto EndWriteIFF;
  139.             }
  140.         }
  141.     }
  142.  
  143.     if (PushChunk(iff, 0L, ID_BMHD, sizeof(BitMapHeader))) {
  144.         PutStr("\n......Error writing to IFF.\n");
  145.         goto EndWriteIFF;
  146.     }
  147.  
  148.     bmh.w                 = (gdesc.gd_Width & 1) ? gdesc.gd_Width + 1 : gdesc.gd_Width;
  149.     bmh.h                 = (gdesc.gd_Height & 1) ? gdesc.gd_Height + 1 : gdesc.gd_Height;
  150.     bmh.x       = bmh.y  = 0;
  151.     bmh.nPlanes          = (DeepFlag ? 24 : 6);
  152.     bmh.masking          = mskNone;
  153.     bmh.compression      = cmpByteRun1;
  154.     bmh.pad1             = 0;
  155.     bmh.transparentColor = 0;
  156.     bmh.xAspect          = (Laced ? x320x400Aspect : x320x200Aspect);
  157.     bmh.yAspect          = (Laced ? y320x400Aspect : y320x200Aspect);
  158.     bmh.pageWidth        = 320;
  159.     bmh.pageHeight       = (Laced ? 400 : 200);
  160.  
  161.     if (WriteChunkBytes(iff, (APTR)&bmh, sizeof(BitMapHeader)) != sizeof(BitMapHeader)) {
  162.         PutStr("\n......Error writing to IFF.\n");
  163.         goto EndWriteIFF;
  164.     }
  165.  
  166.     if (PopChunk(iff)) {
  167.         PutStr("\n......Error writing to IFF.\n");
  168.         goto EndWriteIFF;
  169.     }
  170.  
  171.     if (PushChunk(iff, 0L, ID_CAMG, 4)) {
  172.         PutStr("\n......Error writing to IFF.\n");
  173.         goto EndWriteIFF;
  174.     }
  175.  
  176.     {
  177.         LONG CAMGbuf[1];
  178.  
  179.         CAMGbuf[0] = (DeepFlag ? 0 : HAM) | (Laced ? LACE : 0);
  180.  
  181.         if (WriteChunkBytes(iff, (APTR)&CAMGbuf, 4) != 4) {
  182.             PutStr("\n......Error writing to IFF.\n");
  183.             goto EndWriteIFF;
  184.         }
  185.     }
  186.  
  187.     if (PopChunk(iff)) {
  188.         PutStr("\n......Error writing to IFF.\n");
  189.         goto EndWriteIFF;
  190.     }
  191.  
  192.     if (!DeepFlag) {
  193.         if (PushChunk(iff, 0L, ID_CMAP, 16 * 3)) {
  194.             PutStr("\n......Error writing to IFF.\n");
  195.             goto EndWriteIFF;
  196.         }
  197.  
  198.         for (index = 0; index < 16; index++) {
  199.             current = SHAMmem[index];
  200.  
  201.             ColourBuf.red   = (current >> 4) & 0xF0;
  202.             ColourBuf.green = current & 0xF0;
  203.             ColourBuf.blue  = (current & 15) << 4;
  204.  
  205.             if (WriteChunkBytes(iff, (APTR)&ColourBuf, sizeofColorRegister) != sizeofColorRegister) {
  206.                 PutStr("\n......Error writing to IFF.\n");
  207.                 goto EndWriteIFF;
  208.             }
  209.         }
  210.  
  211.         if (PopChunk(iff)) {
  212.             PutStr("\n......Error writing to IFF.\n");
  213.             goto EndWriteIFF;
  214.         }
  215.  
  216.         ChunkSize = (Laced ? gdesc.gd_Height / 2 : gdesc.gd_Height) * 16 * sizeof(UWORD);
  217.  
  218.         if (PushChunk(iff, 0L, MakeID('S','H','A','M'), IFFSIZE_UNKNOWN)) {
  219.             PutStr("\n......Error writing to IFF.\n");
  220.             goto EndWriteIFF;
  221.         }
  222.  
  223.         {
  224.             UWORD SHAMversion[1];
  225.  
  226.             SHAMversion[0] = 0;
  227.  
  228.             if (WriteChunkBytes(iff, (APTR)&SHAMversion, sizeof(UWORD)) != sizeof(UWORD)) {
  229.                 PutStr("\n......Error writing to IFF.\n");
  230.                 goto EndWriteIFF;
  231.             }
  232.         }
  233.  
  234.         if (WriteChunkBytes(iff, (APTR)SHAMmem, ChunkSize) != ChunkSize) {
  235.             PutStr("\n......Error writing to IFF.\n");
  236.             goto EndWriteIFF;
  237.         }
  238.  
  239.         if (gdesc.gd_Height & 1) {
  240.             UWORD BlankSHAM[16];
  241.  
  242.             memset((char *)BlankSHAM, 0, sizeof(BlankSHAM));
  243.  
  244.             if (WriteChunkBytes(iff, (APTR)BlankSHAM, sizeof(BlankSHAM)) != sizeof(BlankSHAM)) {
  245.                 PutStr("\n......Error writing to IFF.\n");
  246.                 goto EndWriteIFF;
  247.             }
  248.         }
  249.  
  250.         if (PopChunk(iff)) {
  251.             PutStr("\n......Error writing to IFF.\n");
  252.             goto EndWriteIFF;
  253.         }
  254.     } /* end if (!DeepFlag) */
  255.  
  256.     if (PushChunk(iff, 0L, ID_BODY, IFFSIZE_UNKNOWN)) {
  257.         PutStr("\n......Error writing to IFF.\n");
  258.         goto EndWriteIFF;
  259.     }
  260.  
  261.     /* now we actually write the body chunk out */
  262.     {
  263.         register int plane;
  264.         register int col;
  265.         register UWORD x;
  266.         register UWORD y;
  267.         register int index;
  268.         UBYTE PlaneMask, ColMask;
  269.         UWORD Cols;
  270.  
  271.         PutStr("\n......Line ");
  272.  
  273.         Cols = (bmh.w + 7) / 8;
  274.         if (IS_ODD(Cols))
  275.             Cols++;
  276.  
  277.         for (y = 0; y < ((gdesc.gd_Height & 1) ? gdesc.gd_Height + 1 : gdesc.gd_Height) ; y++) {
  278.             MyPrintf("%5ld", y);
  279.  
  280.             if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
  281.                 MyPrintf("\n%s", AbortMsg);
  282.                 CloseIFF(iff);
  283.                 Close(iff->iff_Stream);
  284.                 FreeIFF(iff);
  285.                 MyExit(ABORTEXITVAL);
  286.             }
  287.  
  288.             if (y != gdesc.gd_Height)
  289.                 for (index = 0; index < (DeepFlag ? 3 : 1); index++) {
  290.                     col = 0;
  291.                     ColMask = 1L << 7;
  292.  
  293.                     for (x = 0; x < gdesc.gd_Width; x++) {
  294.                         if (DeepFlag)
  295.                             current = *((UBYTE *)&BitPlane[y][x]+index);
  296.                         else
  297.                             current = GetValue(x, y);
  298.  
  299.                         PlaneMask = 1;
  300.                         for (plane = 0; plane < (DeepFlag ? 8 : 6); plane++) {
  301.                             if (current & PlaneMask)
  302.                                 Planes[plane + index * 8][col] |= ColMask;
  303.  
  304.                             PlaneMask <<= 1;
  305.                         }
  306.  
  307.                         if (ColMask == 1) {
  308.                             ColMask = 1L << 7;
  309.                             col++;
  310.                         } else
  311.                             ColMask >>= 1;
  312.                     }
  313.                 }
  314.  
  315.             /* now we need to compress the scan line */
  316.  
  317.             {
  318.                 register BOOL state;
  319.                 register char c;
  320.                 register char lastc;
  321.                 register UWORD nbuf;
  322.                 register UWORD rstart;
  323.  
  324.                 for (plane = 0; plane < (DeepFlag ? 24 : 6); plane++) {
  325.  
  326.                     CompBuf[0] = lastc = c = Planes[plane][0];
  327.  
  328.                     state = FALSE;
  329.                     PlanePos = rstart = 0;
  330.                     nbuf = col = 1;
  331.  
  332.                     while (col < Cols) {
  333.                         CompBuf[nbuf++] = c = Planes[plane][col++];
  334.  
  335.                         switch (state) {
  336.                             case FALSE:
  337.                             if (nbuf > 128) {
  338.                                 OutDump(nbuf - 1);
  339.                                 CompBuf[0] = c;
  340.                                 nbuf = 1;
  341.                                 rstart = 0;
  342.                                 break;
  343.                             }
  344.  
  345.                             if (c == lastc) {
  346.                                 if (nbuf - rstart >= 3) {
  347.                                     if (rstart > 0)
  348.                                             OutDump(rstart);
  349.                                     state = TRUE;
  350.                                 } else if (rstart == 0)
  351.                                     state = TRUE;
  352.                             } else
  353.                                 rstart = nbuf - 1;
  354.  
  355.                             break;
  356.  
  357.                             case TRUE:
  358.                             if ((c != lastc) || (nbuf - rstart > 128)) {
  359.                                 OutRun(nbuf - 1 - rstart, lastc);
  360.                                 CompBuf[0] = c;
  361.                                 nbuf = 1;
  362.                                 rstart = 0;
  363.                                 state = FALSE;
  364.                             }
  365.  
  366.                             break;
  367.                         }
  368.  
  369.                         lastc = c;
  370.                     }
  371.  
  372.                     switch (state) {
  373.                         case FALSE:
  374.                         OutDump(nbuf);
  375.                         break;
  376.  
  377.                         case TRUE:
  378.                         OutRun(nbuf - rstart, lastc);
  379.                         break;
  380.                     }
  381.  
  382.                     /* now write the compressed plane out */
  383.                     if (WriteChunkBytes(iff, (APTR)PlaneBuf, PlanePos) != PlanePos) {
  384.                         PutStr("\n......Error writing to IFF.\n");
  385.                         goto EndWriteIFF;
  386.                     }
  387.  
  388.                     memset((char *)Planes[plane], 0, Cols);
  389.                 }
  390.             }
  391.  
  392.             MyPrintf("\x9B" "5D");
  393.         }
  394.  
  395.     }
  396.  
  397.     if (PopChunk(iff)) {
  398.         PutStr("\n......Error writing to IFF.\n");
  399.         goto EndWriteIFF;
  400.     }
  401.  
  402.     if (PopChunk(iff)) {
  403.         PutStr("\n......Error writing to IFF.\n");
  404.         goto EndWriteIFF;
  405.     }
  406.  
  407.     PutStr("\x9B" "5D\x9BKWritten.\n");
  408.  
  409. EndWriteIFF:
  410.     CloseIFF(iff);
  411.     if (iff->iff_Stream)
  412.         Close(iff->iff_Stream);
  413.     FreeIFF(iff);
  414.  
  415.     return TRUE;
  416. }
  417.  
  418. void OutDump(int nn)
  419. {
  420.     register int index;
  421.  
  422.     PlaneBuf[PlanePos++] = nn - 1;
  423.  
  424.     for (index = 0; index < nn; index++)
  425.         PlaneBuf[PlanePos++] = CompBuf[index];
  426. }
  427.  
  428. void OutRun(int nn, int cc)
  429. {
  430.     PlaneBuf[PlanePos++] = -(nn - 1);
  431.     PlaneBuf[PlanePos++] = cc;
  432. }
  433.