home *** CD-ROM | disk | FTP | other *** search
- /* $Revision Header * Header built automatically - do not edit! *************
- *
- * (C) Copyright 1985-1990 by Jim Kent & Olaf `Olsen' Barthel
- *
- * Name .....: SaveILBM.c
- * Created ..: Monday 21-Jan-91 20:12
- * Revision .: 0
- *
- * Date Author Comment
- * ========= ======== ====================
- * 21-Jan-91 Olsen Modified this file!
- *
- * $Revision Header ********************************************************/
-
- #include "TermGlobal.h"
-
- /* This is basically Jim Kent's IFF-ILBM writer. Changes I made:
- *
- * - Put all support files into a single file.
- * - Added iffparse.library function calls.
- * - Added the CAMG chunk and implemented 32 bit viewmode IDs.
- * - Wrote a small routine to save the data.
- * - Changed the way the original source code was indented and
- * the names of some variables.
- */
-
- /* A bitmap header. */
-
- struct BitMapHeader
- {
- UWORD w, h; /* raster width & height in pixels */
- UWORD x, y; /* position for this image */
- UBYTE nPlanes; /* # source bitplanes */
- UBYTE masking; /* masking technique */
- UBYTE compression; /* compression algoithm */
- UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/
- UWORD transparentColor; /* transparent "color number" */
- UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */
- WORD pageWidth, pageHeight; /* source "page" size in pixels */
- };
-
- /* Compression status. */
-
- #define DUMP 0
- #define RUN 1
-
- /* Run length encoding constants. */
-
- #define MINRUN 3
- #define MAXRUN 128
- #define MAXDAT 128
-
- /* Size of the IFF write cache. */
-
- #define IFF_SIZE 4096
-
- /* Cache and cache index. */
-
- STATIC UBYTE IFFBuffer[IFF_SIZE];
- STATIC SHORT IFFSize;
-
- /* FlushIFF(struct IFFHandle *IFFHandle):
- *
- * Flush the contents of the IFF write cache.
- */
-
- STATIC BYTE
- FlushIFF(struct IFFHandle *IFFHandle)
- {
- if(IFFSize)
- {
- if(WriteChunkBytes(IFFHandle,IFFBuffer,IFFSize) != IFFSize)
- {
- IFFSize = 0;
- return(FALSE);
- }
-
- IFFSize = 0;
- }
-
- return(TRUE);
- }
-
- /* PutIFF(struct IFFHandle *IFFHandle,UBYTE c):
- *
- * Send a single byte to the IFF write cache.
- */
-
- STATIC BYTE
- PutIFF(struct IFFHandle *IFFHandle,UBYTE c)
- {
- if(IFFSize == IFF_SIZE)
- if(!FlushIFF(IFFHandle))
- return(FALSE);
-
- IFFBuffer[IFFSize++] = c;
-
- return(TRUE);
- }
-
- /* WriteIFF(struct IFFHandle *IFFHandle,UBYTE *Data,SHORT Size):
- *
- * Write a buffer to the IFF cache.
- */
-
- STATIC BYTE
- WriteIFF(struct IFFHandle *IFFHandle,UBYTE *Data,LONG Size)
- {
- LONG Len;
-
- while(Size)
- {
- if(IFFSize == IFF_SIZE)
- if(!FlushIFF(IFFHandle))
- return(FALSE);
-
- if((Len = Size) > IFF_SIZE - IFFSize)
- Len = IFF_SIZE - IFFSize;
-
- CopyMem(&Data[0],&IFFBuffer[IFFSize],Len);
-
- IFFSize += Len;
- Size -= Len;
-
- Data = &Data[Len];
- }
-
- return(TRUE);
- }
-
- STATIC LONG
- PackRow(struct IFFHandle *FileHandle,UBYTE *Source,LONG Size)
- {
- UBYTE c,LastByte = 0;
- BYTE CompMode = DUMP;
- SHORT InBuf = 1; /* number of chars in buffer */
- SHORT RunStart = 0; /* buffer index current run starts */
- LONG PutSize = 0;
- UBYTE LineBuf[MAXDAT*3/2]; /* I think MAXDAT+1 would suffice */
-
- LineBuf[0] = LastByte = *Source++; /* so have valid LastByte */
- Size--; /* since one byte eaten. */
-
- for( ; Size ; --Size)
- {
- LineBuf[InBuf++] = c = *Source++;
-
- switch(CompMode)
- {
- case DUMP: /* If the buffer is full, write the length byte, then the data */
-
- if(InBuf > MAXDAT)
- {
- if(!PutIFF(FileHandle,InBuf-2))
- return(FALSE);
-
- if(!WriteIFF(FileHandle,LineBuf,InBuf-1))
- return(0);
-
- PutSize += InBuf;
- LineBuf[0] = c;
- InBuf = 1;
- RunStart = 0;
- break;
- }
-
- if(c == LastByte)
- {
- if(InBuf - RunStart >= MINRUN)
- {
- if(RunStart > 0)
- {
- if(!PutIFF(FileHandle,RunStart-1))
- return(FALSE);
-
- if(!WriteIFF(FileHandle,LineBuf,RunStart))
- return(0);
-
- PutSize += RunStart+1;
- }
-
- CompMode = RUN;
- }
- else
- {
- if(!RunStart)
- CompMode = RUN;
- }
-
- /* no dump in progress, so can't lose by making
- these 2 a run. */
- }
- else
- RunStart = InBuf - 1;/* first of run */
-
- break;
-
- case RUN: if((c != LastByte) ||(InBuf - RunStart > MAXRUN))
- {
- /* output run */
-
- if(!PutIFF(FileHandle,-(InBuf - RunStart - 2)))
- return(FALSE);
-
- if(!PutIFF(FileHandle,LastByte))
- return(FALSE);
-
- PutSize += 2;
-
- LineBuf[0] = c;
- InBuf = 1;
- RunStart = 0;
- CompMode = DUMP;
- }
-
- break;
- }
-
- LastByte = c;
- }
-
- switch(CompMode)
- {
- case DUMP: if(!PutIFF(FileHandle,InBuf-1))
- return(FALSE);
-
- if(!WriteIFF(FileHandle,LineBuf,InBuf))
- return(FALSE);
-
- PutSize += InBuf+1;
- break;
-
- case RUN: if(!PutIFF(FileHandle,-(InBuf - RunStart - 1)))
- return(FALSE);
-
- if(!PutIFF(FileHandle,LastByte))
- return(FALSE);
-
- PutSize += 2;
- break;
- }
-
- return(PutSize);
- }
-
- STATIC LONG
- PackBitMap(struct IFFHandle *FileHandle,struct BitMap *BitMap,LONG Height)
- {
- LONG i,j,RowLength,CompressedLength = 0,PlaneOffset = 0;
-
- for(i = 0 ; i < Height ; i++)
- {
- for(j = 0 ; j < BitMap -> Depth ; j++)
- {
- if(!(RowLength = PackRow(FileHandle,BitMap -> Planes[j] + PlaneOffset,BitMap -> BytesPerRow)))
- return(0);
-
- CompressedLength += RowLength;
- }
-
- PlaneOffset += BitMap -> BytesPerRow;
- }
-
- return(CompressedLength);
- }
-
- STATIC BYTE
- WriteILBM(UBYTE *FileName,UBYTE *Colours,struct BitMap *BitMap,LONG OffsetX,BYTE OffsetY,LONG Width,LONG Height,LONG Compressed,LONG PageWidth,LONG PageHeight,ULONG ViewModes)
- {
- struct IFFHandle *FileHandle;
- struct BitMapHeader BitMapHeader;
- LONG RowOffset;
- LONG i,j;
- SHORT NumColours = 32;
- BYTE Success = TRUE;
-
- if(BitMap)
- {
- if((NumColours = 1 << BitMap -> Depth) > 32)
- NumColours = 32;
-
- if(ViewModes & HAM)
- NumColours = 16;
- }
-
- if(FileHandle = AllocIFF())
- {
- if(FileHandle -> iff_Stream = Open(FileName,MODE_NEWFILE))
- {
- InitIFFasDOS(FileHandle);
-
- if(!OpenIFF(FileHandle,IFFF_WRITE))
- {
- /* say its a FORM ILBM */
-
- if(!PushChunk(FileHandle,'ILBM','FORM',IFFSIZE_UNKNOWN))
- {
- /* initialize the BitMapHeader to normal values */
-
- BitMapHeader . masking = 0;
- BitMapHeader . pad1 = 0;
- BitMapHeader . transparentColor = 0;
-
- if(Compressed)
- BitMapHeader . compression = 1;
- else
- BitMapHeader . compression = 0;
-
- BitMapHeader . pageWidth = PageWidth;
- BitMapHeader . pageHeight = PageHeight;
- BitMapHeader . yAspect = 11;
-
- /* mask out all unwanted bits. */
-
- ViewModes &= ~(SPRITES | VP_HIDE | GENLOCK_AUDIO | GENLOCK_VIDEO);
-
- if((ViewModes & HIRES) && (ViewModes & LACE))
- BitMapHeader . xAspect = 10;
-
- if(!(ViewModes & HIRES) && (ViewModes & LACE))
- BitMapHeader . xAspect = 20;
-
- if((ViewModes & HIRES) && !(ViewModes & LACE))
- BitMapHeader . xAspect = 5;
-
- if(!(ViewModes & HIRES) && !(ViewModes & LACE))
- BitMapHeader . xAspect = 10;
-
- /* if it's not just a color map give the dimensions of rasters */
-
- if(BitMap)
- {
- BitMapHeader . w = Width;
- BitMapHeader . h = Height;
- BitMapHeader . nPlanes = BitMap -> Depth;
- BitMapHeader . x = OffsetX;
- BitMapHeader . y = OffsetY;
- }
-
- if(!PushChunk(FileHandle,0,'BMHD',IFFSIZE_UNKNOWN))
- {
- if(WriteChunkBytes(FileHandle,&BitMapHeader,sizeof(BitMapHeader)) == sizeof(BitMapHeader))
- {
- if(!PopChunk(FileHandle))
- {
- if(!PushChunk(FileHandle,0,'CMAP',IFFSIZE_UNKNOWN))
- {
- if(WriteChunkBytes(FileHandle,Colours,3 * NumColours) == 3 * NumColours)
- {
- if(!PopChunk(FileHandle))
- {
- if(!PushChunk(FileHandle,0,'CAMG',IFFSIZE_UNKNOWN))
- {
- if(WriteChunkBytes(FileHandle,&ViewModes,sizeof(ULONG)) == sizeof(ULONG))
- {
- if(!PopChunk(FileHandle))
- {
- if(!PushChunk(FileHandle,0,'BODY',IFFSIZE_UNKNOWN))
- {
- if(Compressed)
- {
- if(!PackBitMap(FileHandle,BitMap,Height))
- Success = FALSE;
- else
- {
- if(!FlushIFF(FileHandle))
- Success = FALSE;
- }
- }
- else
- {
- i = Height;
- RowOffset = 0;
-
- while(--i >= 0 && Success)
- {
- for(j = 0 ; j < BitMap -> Depth ; j++)
- {
- if(WriteChunkBytes(FileHandle,BitMap -> Planes[j] + RowOffset,Height) != Height)
- {
- Success = FALSE;
- break;
- }
-
- RowOffset += BitMap -> BytesPerRow;
- }
- }
- }
-
- if(PopChunk(FileHandle))
- Success = FALSE;
- }
- else
- Success = FALSE;
- }
- else
- Success = FALSE;
- }
- else
- Success = FALSE;
- }
- else
- Success = FALSE;
- }
- else
- Success = FALSE;
- }
- else
- Success = FALSE;
- }
- else
- Success = FALSE;
- }
- else
- Success = FALSE;
- }
- else
- Success = FALSE;
- }
- else
- Success = FALSE;
-
- if(PopChunk(FileHandle))
- Success = FALSE;
- }
- else
- Success = FALSE;
- }
- else
- Success = FALSE;
-
- Close(FileHandle -> iff_Stream);
- }
- else
- Success = FALSE;
-
- FreeIFF(FileHandle);
- }
- else
- Success = FALSE;
-
- return(Success);
- }
-
- /* SaveRPort():
- *
- * Save the contents of a given RastPort to an IFF-ILBM
- * file, use iffparse.library to get the job done.
- */
-
- LONG
- SaveRPort(struct RastPort *RPort,struct ViewPort *VPort,LONG LeftEdge,LONG TopEdge,LONG Width,LONG Height,LONG ParentWidth,LONG ParentHeight,LONG Cookie,STRPTR Name)
- {
- UBYTE ColTable[32 * 3];
- struct BitMap DstMap,*SMap = RPort -> BitMap;
- LONG IFF_Result,i,r,g,b;
-
- LONG PacketDims[4];
- BYTE ClosedWindow = FALSE;
-
- /* It is impossible to drag the packet window to
- * a place where it doesn't overlap the main window.
- * To avoid unpleasant effects we'll close it
- * and reopen it after saving the main window
- * contents.
- */
-
- if(PacketWindow)
- {
- PacketDims[0] = PacketWindow -> LeftEdge;
- PacketDims[1] = PacketWindow -> TopEdge;
- PacketDims[2] = PacketWindow -> Width;
- PacketDims[3] = PacketWindow -> Height;
-
- PacketWindow -> Flags |= WFLG_RMBTRAP;
-
- ClearMenuStrip(PacketWindow);
-
- CloseWindow(PacketWindow);
-
- PacketWindow = NULL;
-
- ClosedWindow = TRUE;
- }
-
- /* Reset buffer counter. */
-
- IFFSize = 0;
-
- /* Perform `cookie cut'? */
-
- if(LeftEdge || TopEdge || Cookie)
- {
- Cookie = TRUE;
-
- InitBitMap(&DstMap,SMap -> Depth,Width,Height);
-
- for(i = 0 ; i < SMap -> Depth ; i++)
- {
- if(!(DstMap . Planes[i] = (PLANEPTR)AllocMem(DstMap . BytesPerRow * DstMap . Rows,MEMF_CHIP | MEMF_CLEAR)))
- {
- IFF_Result = FALSE;
- goto Stop;
- }
- }
-
- BltBitMap(SMap,LeftEdge,TopEdge,&DstMap,0,0,Width,Height,0xC0,0xFF,NULL);
-
- SMap = &DstMap;
- }
-
- /* Convert the colours. */
-
- for(i = 0 ; i < 32 ; i++)
- {
- UWORD TmpCol = GetRGB4(VPort -> ColorMap,i);
-
- r = (TmpCol >> 8) & 0xF;
- g = (TmpCol >> 4) & 0xF;
- b = (TmpCol ) & 0xF;
-
- ColTable[i * 3 + 0] = r << 4;
- ColTable[i * 3 + 1] = g << 4;
- ColTable[i * 3 + 2] = b << 4;
- }
-
- /* Write the IFF-ILBM file. */
-
- IFF_Result = WriteILBM(Name,ColTable,SMap,LeftEdge,TopEdge,Width,Height,TRUE,ParentWidth,ParentHeight,GetVPModeID(VPort));
-
- /* Free the display cookie. */
-
- Stop: if(Cookie)
- {
- for(i = 0 ; i < DstMap . Depth ; i++)
- {
- if(DstMap . Planes[i])
- FreeMem(DstMap . Planes[i],DstMap . BytesPerRow * DstMap . Rows);
- }
- }
-
- /* Delete truncated file or set the `not executable' bit
- * if successful.
- */
-
- if(!IFF_Result)
- DeleteFile(Name);
- else
- SetProtection(Name,FIBF_EXECUTE);
-
- /* Be a good boy and reopen the packet window. */
-
- if(ClosedWindow)
- {
- if(PacketWindow = OpenWindowTags(NULL,
- WA_Left, PacketDims[0],
- WA_Top, PacketDims[1],
-
- WA_Width, PacketDims[2],
- WA_Height, PacketDims[3],
-
- WA_Activate, TRUE,
- WA_DragBar, TRUE,
- WA_DepthGadget, TRUE,
- WA_CloseGadget, TRUE,
- WA_RMBTrap, TRUE,
- WA_SizeGadget, TRUE,
- WA_MinWidth, 80,
- WA_MinHeight, 27,
- WA_MaxWidth, Screen -> Width,
- WA_MaxHeight, 27,
- WA_CustomScreen,Screen,
-
- WA_IDCMP, STRINGIDCMP | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_ACTIVEWINDOW | IDCMP_RAWKEY,
-
- WA_Title, "Packet Window",
- TAG_DONE))
- {
- AddGList(PacketWindow,PacketGadgetList,(UWORD)-1,(UWORD)-1,NULL);
- RefreshGList(PacketGadgetList,PacketWindow,NULL,(UWORD)-1);
- GT_RefreshWindow(PacketWindow,NULL);
-
- SetMenuStrip(PacketWindow,PacketMenu);
-
- PacketWindow -> Flags &= ~WFLG_RMBTRAP;
- }
- else
- DeletePacketWindow();
- }
-
- return(IFF_Result);
- }
-