/** Revision Header * Header built automatically - do not edit! ************* * * (C) Copyright 1991 by Olaf `Olsen' Barthel, all rights reserved * * Name .....: SaveILBM.c * Created ..: Monday 26-Aug-91 11:20 * Revision .: 1 * * Date Author Comment * ========= ======== ==================== * 26-Aug-91 Olsen Created this file! * ***************************************************************************/ /* This is basically Jim Kent's IFF-ILBM writer code as published * in `Plop', with changes for iffparse.library and 32 bit viewmode * CAMG chunks. I also added a version chunk to be saved with each * image. */ #define DUMP 0 #define RUN 1 #define MINRUN 3 #define MAXRUN 128 #define MAXDAT 128 #define IFF_SIZE 4096 STATIC UBYTE IFFBuffer[IFF_SIZE]; STATIC WORD IFFSize; STATIC BYTE __regargs FlushIFF(struct IFFHandle *IFFHandle) { if(IFFSize) { if(WriteChunkBytes(IFFHandle,IFFBuffer,IFFSize) != IFFSize) { IFFSize = 0; return(FALSE); } IFFSize = 0; } return(TRUE); } STATIC BYTE __regargs PutIFF(struct IFFHandle *IFFHandle,UBYTE c) { if(IFFSize == IFF_SIZE) if(!FlushIFF(IFFHandle)) return(FALSE); IFFBuffer[IFFSize++] = c; return(TRUE); } STATIC BYTE __regargs 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 __regargs PackRow(struct IFFHandle *FileHandle,UBYTE *Source,LONG Size) { UBYTE c,LastByte = 0,LineBuf[MAXDAT * 3 / 2]; BYTE CompMode = DUMP; WORD InBuf = 1,RunStart = 0; LONG PutSize = 0; LineBuf[0] = LastByte = *Source++; Size--; for( ; Size ; --Size) { LineBuf[InBuf++] = c = *Source++; switch(CompMode) { case DUMP: 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; } } else RunStart = InBuf - 1; break; case RUN: if((c != LastByte) || (InBuf - RunStart > MAXRUN)) { 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 __regargs 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 __regargs 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 MandelInfo *MandelInfo) { struct IFFHandle *FileHandle; struct BitMapHeader BitMapHeader; LONG RowOffset; LONG i,j; WORD 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)) { if(!PushChunk(FileHandle,'ILBM','FORM',IFFSIZE_UNKNOWN)) { 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; 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(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,'MAND',IFFSIZE_UNKNOWN)) { if(WriteChunkBytes(FileHandle,MandelInfo,sizeof(struct MandelInfo)) == sizeof(struct MandelInfo)) { if(!PopChunk(FileHandle)) { if(!PushChunk(FileHandle,0,'ANNO',IFFSIZE_UNKNOWN)) { extern UBYTE VersTag[]; UBYTE Len; Len = strlen(&VersTag[1]); if(WriteChunkBytes(FileHandle,&VersTag[1],Len) != Len) Success = FALSE; else { if(PopChunk(FileHandle)) Success = FALSE; } } if(Success) { 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; } 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); } LONG SaveBitMap(struct BitMap *BitMap,struct ViewPort *VPort,LONG LeftEdge,LONG TopEdge,LONG Width,LONG Height,LONG ParentWidth,LONG ParentHeight,STRPTR Name,struct MandelInfo *MandelInfo) { extern struct GfxBase *GfxBase; UBYTE ColTable[32 * 3]; LONG IFF_Result,i,r,g,b; IFFSize = 0; 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; } if(!(IFF_Result = WriteILBM(Name,ColTable,BitMap,LeftEdge,TopEdge,Width,Height,TRUE,ParentWidth,ParentHeight,GetVPModeID(VPort),MandelInfo))) DeleteFile(Name); else SetProtection(Name,FIBF_EXECUTE); return(IFF_Result); }