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