home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 500-599 / ff589.lza / Term / TermSrc.lha / SaveILBM.c < prev    next >
C/C++ Source or Header  |  1991-10-03  |  13KB  |  610 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1985-1991 by Jim Kent & Olaf `Olsen' Barthel
  4.  *
  5.  *    Name .....: SaveILBM.c
  6.  *    Created ..: Monday 21-Jan-91 20:12
  7.  *    Revision .: 0
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    21-Jan-91       Olsen           Modified this file!
  12.  *
  13.  * $Revision Header ********************************************************/
  14.  
  15. #include "TermGlobal.h"
  16.  
  17.     /* This is basically Jim Kent's IFF-ILBM writer. Changes I made:
  18.      *
  19.      * - Put all support files into a single file.
  20.      * - Added iffparse.library function calls.
  21.      * - Added the CAMG chunk and implemented 32 bit viewmode IDs.
  22.      * - Wrote a small routine to save the data.
  23.      * - Added the ANNO version chunk.
  24.      * - Changed the way the original source code was indented and
  25.      *   the names of some variables.
  26.      */
  27.  
  28.     /* A bitmap header. */
  29.  
  30. struct BitMapHeader
  31. {
  32.     UWORD w, h;            /* raster width & height in pixels */
  33.     UWORD x, y;            /* position for this image */
  34.     UBYTE nPlanes;            /* # source bitplanes */
  35.     UBYTE masking;            /* masking technique */
  36.     UBYTE compression;        /* compression algoithm */
  37.     UBYTE pad1;            /* UNUSED.  For consistency, put 0 here.*/
  38.     UWORD transparentColor;        /* transparent "color number" */
  39.     UBYTE xAspect, yAspect;        /* aspect ratio, a rational number x/y */
  40.     WORD pageWidth, pageHeight;    /* source "page" size in pixels */
  41. };
  42.  
  43.     /* Compression status. */
  44.  
  45. #define DUMP    0
  46. #define RUN    1
  47.  
  48.     /* Run length encoding constants. */
  49.  
  50. #define MINRUN    3
  51. #define MAXRUN    128
  52. #define MAXDAT    128
  53.  
  54.     /* Size of the IFF write cache. */
  55.  
  56. #define IFF_SIZE    4096
  57.  
  58.     /* Cache and cache index. */
  59.  
  60. STATIC UBYTE    IFFBuffer[IFF_SIZE];
  61. STATIC WORD    IFFSize;
  62.  
  63.     /* FlushIFF(struct IFFHandle *IFFHandle):
  64.      *
  65.      *    Flush the contents of the IFF write cache.
  66.      */
  67.  
  68. STATIC BYTE
  69. FlushIFF(struct IFFHandle *IFFHandle)
  70. {
  71.     if(IFFSize)
  72.     {
  73.         if(WriteChunkBytes(IFFHandle,IFFBuffer,IFFSize) != IFFSize)
  74.         {
  75.             IFFSize = 0;
  76.             return(FALSE);
  77.         }
  78.  
  79.         IFFSize = 0;
  80.     }
  81.  
  82.     return(TRUE);
  83. }
  84.  
  85.     /* PutIFF(struct IFFHandle *IFFHandle,UBYTE c):
  86.      *
  87.      *    Send a single byte to the IFF write cache.
  88.      */
  89.  
  90. STATIC BYTE
  91. PutIFF(struct IFFHandle *IFFHandle,UBYTE c)
  92. {
  93.     if(IFFSize == IFF_SIZE)
  94.         if(!FlushIFF(IFFHandle))
  95.             return(FALSE);
  96.  
  97.     IFFBuffer[IFFSize++] = c;
  98.  
  99.     return(TRUE);
  100. }
  101.  
  102.     /* WriteIFF(struct IFFHandle *IFFHandle,UBYTE *Data,WORD Size):
  103.      *
  104.      *    Write a buffer to the IFF cache.
  105.      */
  106.  
  107. STATIC BYTE
  108. WriteIFF(struct IFFHandle *IFFHandle,UBYTE *Data,LONG Size)
  109. {
  110.     LONG Len;
  111.  
  112.     while(Size)
  113.     {
  114.         if(IFFSize == IFF_SIZE)
  115.             if(!FlushIFF(IFFHandle))
  116.                 return(FALSE);
  117.  
  118.         if((Len = Size) > IFF_SIZE - IFFSize)
  119.             Len = IFF_SIZE - IFFSize;
  120.  
  121.         CopyMem(&Data[0],&IFFBuffer[IFFSize],Len);
  122.  
  123.         IFFSize    += Len;
  124.         Size    -= Len;
  125.  
  126.         Data = &Data[Len];
  127.     }
  128.  
  129.     return(TRUE);
  130. }
  131.  
  132. STATIC LONG
  133. PackRow(struct IFFHandle *FileHandle,UBYTE *Source,LONG Size)
  134. {
  135.     UBYTE    c,LastByte    = 0;
  136.     BYTE    CompMode    = DUMP;
  137.     WORD    InBuf        = 1;        /* number of chars in buffer */
  138.     WORD    RunStart    = 0;        /* buffer index current run starts */
  139.     LONG    PutSize        = 0;
  140.  
  141.     UBYTE    LineBuf[MAXDAT * 3 / 2];    /* I think MAXDAT+1 would suffice */
  142.  
  143.     LineBuf[0] = LastByte = *Source++;    /* so have valid LastByte */
  144.     Size--;                    /* since one byte eaten. */
  145.  
  146.     for( ; Size ; --Size)
  147.     {
  148.         LineBuf[InBuf++] = c = *Source++;
  149.  
  150.         switch(CompMode)
  151.         {
  152.             case DUMP:    /* If the buffer is full, write the length byte, then the data */
  153.  
  154.                     if(InBuf > MAXDAT)
  155.                     {
  156.                         if(!PutIFF(FileHandle,InBuf-2))
  157.                             return(FALSE);
  158.  
  159.                         if(!WriteIFF(FileHandle,LineBuf,InBuf-1))
  160.                             return(0);
  161.  
  162.                         PutSize += InBuf;
  163.  
  164.                         LineBuf[0]    = c;
  165.                         InBuf        = 1;
  166.                         RunStart    = 0;
  167.  
  168.                         break;
  169.                     }
  170.  
  171.                     if(c == LastByte)
  172.                     {
  173.                         if(InBuf - RunStart >= MINRUN)
  174.                         {
  175.                             if(RunStart > 0)
  176.                             {
  177.                                 if(!PutIFF(FileHandle,RunStart-1))
  178.                                     return(FALSE);
  179.  
  180.                                 if(!WriteIFF(FileHandle,LineBuf,RunStart))
  181.                                     return(0);
  182.  
  183.                                 PutSize += RunStart+1;
  184.                             }
  185.  
  186.                             CompMode = RUN;
  187.                         }
  188.                         else
  189.                         {
  190.                             if(!RunStart)
  191.                                 CompMode = RUN;
  192.                         }
  193.  
  194.                             /* no dump in progress, so can't lose by making
  195.                                these 2 a run. */
  196.                     }
  197.                     else
  198.                         RunStart = InBuf - 1;/* first of run */
  199.  
  200.                     break;
  201.  
  202.             case RUN:    if((c != LastByte) ||(InBuf - RunStart > MAXRUN))
  203.                     {
  204.                         /* output run */
  205.  
  206.                         if(!PutIFF(FileHandle,-(InBuf - RunStart - 2)))
  207.                             return(FALSE);
  208.  
  209.                         if(!PutIFF(FileHandle,LastByte))
  210.                             return(FALSE);
  211.  
  212.                         PutSize += 2;
  213.  
  214.                         LineBuf[0]    = c;
  215.                         InBuf        = 1;
  216.                         RunStart    = 0;
  217.                         CompMode    = DUMP;
  218.                     }
  219.  
  220.                     break;
  221.         }
  222.  
  223.         LastByte = c;
  224.     }
  225.  
  226.     switch(CompMode)
  227.     {
  228.         case DUMP:    if(!PutIFF(FileHandle,InBuf-1))
  229.                     return(FALSE);
  230.  
  231.                 if(!WriteIFF(FileHandle,LineBuf,InBuf))
  232.                     return(FALSE);
  233.  
  234.                 PutSize += InBuf+1;
  235.                 break;
  236.  
  237.         case RUN:    if(!PutIFF(FileHandle,-(InBuf - RunStart - 1)))
  238.                     return(FALSE);
  239.  
  240.                 if(!PutIFF(FileHandle,LastByte))
  241.                     return(FALSE);
  242.  
  243.                 PutSize += 2;
  244.                 break;
  245.     }
  246.  
  247.     return(PutSize);
  248. }
  249.  
  250. STATIC LONG
  251. PackBitMap(struct IFFHandle *FileHandle,struct BitMap *BitMap,LONG Height)
  252. {
  253.     LONG i,j,RowLength,CompressedLength = 0,PlaneOffset = 0;
  254.  
  255.     for(i = 0 ; i < Height ; i++)
  256.     {
  257.         for(j = 0 ; j < BitMap -> Depth ; j++)
  258.         {
  259.             if(!(RowLength = PackRow(FileHandle,BitMap -> Planes[j] + PlaneOffset,BitMap -> BytesPerRow)))
  260.                 return(0);
  261.  
  262.             CompressedLength += RowLength;
  263.         }
  264.  
  265.         PlaneOffset += BitMap -> BytesPerRow;
  266.     }
  267.  
  268.     return(CompressedLength);
  269. }
  270.  
  271. STATIC BYTE
  272. WriteILBM(UBYTE *FileName,UBYTE *Colours,struct BitMap *BitMap,LONG OffsetX,BYTE OffsetY,LONG Width,LONG Height,LONG Compressed,LONG PageWidth,LONG PageHeight,ULONG ViewModes)
  273. {
  274.     struct IFFHandle    *FileHandle;
  275.     struct BitMapHeader     BitMapHeader;
  276.     LONG             RowOffset;
  277.     LONG             i,j;
  278.     WORD             NumColours = 32;
  279.     BYTE             Success = TRUE;
  280.  
  281.     if(BitMap)
  282.     {
  283.         if((NumColours = 1 << BitMap -> Depth) > 32)
  284.             NumColours = 32;
  285.  
  286.         if(ViewModes & HAM)
  287.             NumColours = 16;
  288.     }
  289.  
  290.     if(FileHandle = AllocIFF())
  291.     {
  292.         if(FileHandle -> iff_Stream = Open(FileName,MODE_NEWFILE))
  293.         {
  294.             InitIFFasDOS(FileHandle);
  295.  
  296.             if(!OpenIFF(FileHandle,IFFF_WRITE))
  297.             {
  298.                 /* say its a FORM ILBM */
  299.  
  300.                 if(!PushChunk(FileHandle,'ILBM','FORM',IFFSIZE_UNKNOWN))
  301.                 {
  302.                     /* initialize the BitMapHeader to normal values */
  303.  
  304.                     BitMapHeader . masking        = 0;
  305.                     BitMapHeader . pad1        = 0;
  306.                     BitMapHeader . transparentColor    = 0;
  307.  
  308.                     if(Compressed)
  309.                         BitMapHeader . compression = 1;
  310.                     else
  311.                         BitMapHeader . compression = 0;
  312.  
  313.                     BitMapHeader . pageWidth    = PageWidth;
  314.                     BitMapHeader . pageHeight    = PageHeight;
  315.                     BitMapHeader . yAspect        = 11;
  316.  
  317.                     /* mask out all unwanted bits. */
  318.  
  319.                     ViewModes &= ~(SPRITES | VP_HIDE | GENLOCK_AUDIO | GENLOCK_VIDEO);
  320.  
  321.                     if((ViewModes & HIRES) && (ViewModes & LACE))
  322.                         BitMapHeader . xAspect = 10;
  323.  
  324.                     if(!(ViewModes & HIRES) && (ViewModes & LACE))
  325.                         BitMapHeader . xAspect = 20;
  326.  
  327.                     if((ViewModes & HIRES) && !(ViewModes & LACE))
  328.                         BitMapHeader . xAspect = 5;
  329.  
  330.                     if(!(ViewModes & HIRES) && !(ViewModes & LACE))
  331.                         BitMapHeader . xAspect = 10;
  332.  
  333.                     /* if it's not just a color map give the dimensions of rasters */
  334.  
  335.                     if(BitMap)
  336.                     {
  337.                         BitMapHeader . w    = Width;
  338.                         BitMapHeader . h    = Height;
  339.                         BitMapHeader . nPlanes    = BitMap -> Depth;
  340.                         BitMapHeader . x    = OffsetX;
  341.                         BitMapHeader . y    = OffsetY;
  342.                     }
  343.  
  344.                     if(!PushChunk(FileHandle,0,'BMHD',IFFSIZE_UNKNOWN))
  345.                     {
  346.                         if(WriteChunkBytes(FileHandle,&BitMapHeader,sizeof(BitMapHeader)) == sizeof(BitMapHeader))
  347.                         {
  348.                             if(!PopChunk(FileHandle))
  349.                             {
  350.                                 if(!PushChunk(FileHandle,0,'ANNO',IFFSIZE_UNKNOWN))
  351.                                 {
  352.                                     extern UBYTE VersTag[];
  353.  
  354.                                     if(WriteChunkBytes(FileHandle,&VersTag[1],strlen(&VersTag[1])) != strlen(&VersTag[1]))
  355.                                         Success = FALSE;
  356.  
  357.                                     if(PopChunk(FileHandle))
  358.                                         Success = FALSE;
  359.                                 }
  360.  
  361.                                 if(Success && !PushChunk(FileHandle,0,'CMAP',IFFSIZE_UNKNOWN))
  362.                                 {
  363.                                     if(WriteChunkBytes(FileHandle,Colours,3 * NumColours) == 3 * NumColours)
  364.                                     {
  365.                                         if(!PopChunk(FileHandle))
  366.                                         {
  367.                                             if(!PushChunk(FileHandle,0,'CAMG',IFFSIZE_UNKNOWN))
  368.                                             {
  369.                                                 if(WriteChunkBytes(FileHandle,&ViewModes,sizeof(ULONG)) == sizeof(ULONG))
  370.                                                 {
  371.                                                     if(!PopChunk(FileHandle))
  372.                                                     {
  373.                                                         if(!PushChunk(FileHandle,0,'BODY',IFFSIZE_UNKNOWN))
  374.                                                         {
  375.                                                             if(Compressed)
  376.                                                             {
  377.                                                                 if(!PackBitMap(FileHandle,BitMap,Height))
  378.                                                                     Success = FALSE;
  379.                                                                 else
  380.                                                                 {
  381.                                                                     if(!FlushIFF(FileHandle))
  382.                                                                         Success = FALSE;
  383.                                                                 }
  384.                                                             }
  385.                                                             else
  386.                                                             {
  387.                                                                 i = Height;
  388.                                                                 RowOffset = 0;
  389.  
  390.                                                                 while(--i >= 0 && Success)
  391.                                                                 {
  392.                                                                     for(j = 0 ; j < BitMap -> Depth ; j++)
  393.                                                                     {
  394.                                                                         if(WriteChunkBytes(FileHandle,BitMap -> Planes[j] + RowOffset,Height) != Height)
  395.                                                                         {
  396.                                                                             Success = FALSE;
  397.                                                                             break;
  398.                                                                         }
  399.  
  400.                                                                         RowOffset += BitMap -> BytesPerRow;
  401.                                                                     }
  402.                                                                 }
  403.                                                             }
  404.  
  405.                                                             if(PopChunk(FileHandle))
  406.                                                                 Success = FALSE;
  407.                                                         }
  408.                                                         else
  409.                                                             Success = FALSE;
  410.                                                     }
  411.                                                     else
  412.                                                         Success = FALSE;
  413.                                                 }
  414.                                                 else
  415.                                                     Success = FALSE;
  416.                                             }
  417.                                             else
  418.                                                 Success = FALSE;
  419.                                         }
  420.                                         else
  421.                                             Success = FALSE;
  422.                                     }
  423.                                     else
  424.                                         Success = FALSE;
  425.                                 }
  426.                                 else
  427.                                     Success = FALSE;
  428.                             }
  429.                             else
  430.                                 Success = FALSE;
  431.                         }
  432.                         else
  433.                             Success = FALSE;
  434.                     }
  435.                     else
  436.                         Success = FALSE;
  437.  
  438.                     if(PopChunk(FileHandle))
  439.                         Success = FALSE;
  440.                 }
  441.                 else
  442.                     Success = FALSE;
  443.             }
  444.             else
  445.                 Success = FALSE;
  446.  
  447.             Close(FileHandle -> iff_Stream);
  448.         }
  449.         else
  450.             Success = FALSE;
  451.  
  452.         FreeIFF(FileHandle);
  453.     }
  454.     else
  455.         Success = FALSE;
  456.  
  457.     return(Success);
  458. }
  459.  
  460.     /* SaveRPort():
  461.      *
  462.      *    Save the contents of a given RastPort to an IFF-ILBM
  463.      *    file, use iffparse.library to get the job done.
  464.      */
  465.  
  466. LONG
  467. SaveRPort(struct RastPort *RPort,struct ViewPort *VPort,LONG LeftEdge,LONG TopEdge,LONG Width,LONG Height,LONG ParentWidth,LONG ParentHeight,LONG Cookie,STRPTR Name)
  468. {
  469.     UBYTE         ColTable[32 * 3];
  470.     struct BitMap     DstMap,*SMap = RPort -> BitMap;
  471.     LONG         IFF_Result,i,r,g,b;
  472.  
  473.     LONG         PacketDims[4];
  474.     BYTE         ClosedWindow = FALSE;
  475.  
  476.         /* It is impossible to drag the packet window to
  477.          * a place where it doesn't overlap the main window.
  478.          * To avoid unpleasant effects we'll close it
  479.          * and reopen it after saving the main window
  480.          * contents.
  481.          */
  482.  
  483.     if(PacketWindow)
  484.     {
  485.         PacketDims[0] = PacketWindow -> LeftEdge;
  486.         PacketDims[1] = PacketWindow -> TopEdge;
  487.         PacketDims[2] = PacketWindow -> Width;
  488.         PacketDims[3] = PacketWindow -> Height;
  489.  
  490.         PacketWindow -> Flags |= WFLG_RMBTRAP;
  491.  
  492.         ClearMenuStrip(PacketWindow);
  493.  
  494.         CloseWindow(PacketWindow);
  495.  
  496.         PacketWindow = NULL;
  497.  
  498.         ClosedWindow = TRUE;
  499.     }
  500.  
  501.         /* Reset buffer counter. */
  502.  
  503.     IFFSize = 0;
  504.  
  505.         /* Perform `cookie cut'? */
  506.  
  507.     if(LeftEdge || TopEdge || Cookie)
  508.     {
  509.         Cookie = TRUE;
  510.  
  511.         memset(&DstMap,0,sizeof(struct BitMap));
  512.  
  513.         InitBitMap(&DstMap,SMap -> Depth,Width,Height);
  514.  
  515.         for(i = 0 ; i < SMap -> Depth ; i++)
  516.         {
  517.             if(!(DstMap . Planes[i] = (PLANEPTR)AllocVec(DstMap . BytesPerRow * DstMap . Rows,MEMF_CHIP | MEMF_CLEAR)))
  518.             {
  519.                 IFF_Result = FALSE;
  520.                 goto Stop;
  521.             }
  522.         }
  523.  
  524.         BltBitMap(SMap,LeftEdge,TopEdge,&DstMap,0,0,Width,Height,0xC0,0xFF,NULL);
  525.  
  526.         SMap = &DstMap;
  527.     }
  528.  
  529.         /* Convert the colours. */
  530.  
  531.     for(i = 0 ; i < 32 ; i++)
  532.     {
  533.         UWORD TmpCol = GetRGB4(VPort -> ColorMap,i);
  534.  
  535.         r = (TmpCol >> 8) & 0xF;
  536.         g = (TmpCol >> 4) & 0xF;
  537.         b = (TmpCol     ) & 0xF;
  538.  
  539.         ColTable[i * 3 + 0] = r << 4;
  540.         ColTable[i * 3 + 1] = g << 4;
  541.         ColTable[i * 3 + 2] = b << 4;
  542.     }
  543.  
  544.         /* Write the IFF-ILBM file. */
  545.  
  546.     IFF_Result = WriteILBM(Name,ColTable,SMap,LeftEdge,TopEdge,Width,Height,TRUE,ParentWidth,ParentHeight,GetVPModeID(VPort));
  547.  
  548.         /* Free the display cookie. */
  549.  
  550. Stop:    if(Cookie)
  551.     {
  552.         for(i = 0 ; i < DstMap . Depth ; i++)
  553.         {
  554.             if(DstMap . Planes[i])
  555.                 FreeVec(DstMap . Planes[i]);
  556.         }
  557.     }
  558.  
  559.         /* Delete truncated file or set the `not executable' bit
  560.          * if successful.
  561.          */
  562.  
  563.     if(!IFF_Result)
  564.         DeleteFile(Name);
  565.     else
  566.         SetProtection(Name,FIBF_EXECUTE);
  567.  
  568.         /* Be a good boy and reopen the packet window. */
  569.  
  570.     if(ClosedWindow)
  571.     {
  572.         if(PacketWindow = OpenWindowTags(NULL,
  573.             WA_Left,    PacketDims[0],
  574.             WA_Top,        PacketDims[1],
  575.  
  576.             WA_Width,    PacketDims[2],
  577.             WA_Height,    PacketDims[3],
  578.  
  579.             WA_Activate,    TRUE,
  580.             WA_DragBar,    TRUE,
  581.             WA_DepthGadget,    TRUE,
  582.             WA_CloseGadget,    TRUE,
  583.             WA_RMBTrap,    TRUE,
  584.             WA_SizeGadget,    TRUE,
  585.             WA_MinWidth,    80,
  586.             WA_MinHeight,    27,
  587.             WA_MaxWidth,    Screen -> Width,
  588.             WA_MaxHeight,    27,
  589.             WA_CustomScreen,Screen,
  590.  
  591.             WA_IDCMP,    STRINGIDCMP | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_ACTIVEWINDOW | IDCMP_RAWKEY,
  592.  
  593.             WA_Title,    "Packet Window",
  594.         TAG_DONE))
  595.         {
  596.             AddGList(PacketWindow,PacketGadgetList,(UWORD)-1,(UWORD)-1,NULL);
  597.             RefreshGList(PacketGadgetList,PacketWindow,NULL,(UWORD)-1);
  598.             GT_RefreshWindow(PacketWindow,NULL);
  599.  
  600.             SetMenuStrip(PacketWindow,PacketMenu);
  601.  
  602.             PacketWindow -> Flags &= ~WFLG_RMBTRAP;
  603.         }
  604.         else
  605.             DeletePacketWindow();
  606.     }
  607.  
  608.     return(IFF_Result);
  609. }
  610.