/************************************************************************** * * * iffpack * * * * Routines for loading and saving pictures with windows * * using the old formats and the new compression format * * * **************************************************************************/ #include #include #include #define NOERRORTEXT #include "iffpack.h" #define BADFLAGS (SPRITES|VP_HIDE|GENLOCK_AUDIO|GENLOCK_VIDEO) #define FLAGMASK (~BADFLAGS) #define CAMGMASK (FLAGMASK & 0xffffL) struct BMHD { ULONG Size; USHORT Width,Height; SHORT LeftEdge,TopEdge; UBYTE Depth; UBYTE Mask; UBYTE Compression; UBYTE Pad; USHORT Transparent; UBYTE XAspect,YAspect; SHORT ScrWidth,ScrHeight; }; static USHORT buf[256]; static short count,runlen,ptr; static short rows,bytes,depth; static cmode; static short TempY=0,TempX=0; static struct BitMap MyBm; static struct RastPort MyRast; static short anzcolors; static USHORT colors[32]; /************************************************************************** * * * SetColors(vp): * * * * Set the colors, that were previously loaded with ReadPicSize * * * * vp: Viewport of the Screen * * * **************************************************************************/ SetColors(vp) struct ViewPort *vp; { LoadRGB4(vp,colors,(long)anzcolors); } /************************************************************************** * * * ReadPicSize(fp,winx,winy,srcx,srcy,depth,vmode * * * * Read the size and viewmode of the picture and load the colors to an * * internal buffer * * * * fp: FILE-Pointer of stdio * * winx,winy: references to the size of the window * * srcx,srcy: references to the size of the screen * * depth: reference to the depth of the screen * * vmode: reference to Viewmode * * * * ReadPicSize sets the values of the referenced parameters * * * * the result of ReadPicSize is 0 if no error occured or an error-code * * defined in iffpack.h * * * **************************************************************************/ ReadPicSize(fp,winx,winy,scrx,scry,depth,vmode) FILE *fp; SHORT *winx,*winy; SHORT *scrx,*scry; SHORT *depth; USHORT *vmode; { struct BMHD bmhd; int err; if(err=ReadHeader(fp,&bmhd,vmode)) return(err); *winx=bmhd.Width; *winy=bmhd.Height; *scrx=bmhd.ScrWidth; *scry=bmhd.ScrHeight; *depth=bmhd.Depth; return(0); } /************************************************************************** * * * ReadBody: read the bitmap data to a rastport * * * * rp: pointer to rastport * * * * fp: FILE-Pointer of stdio * * * **************************************************************************/ ReadBody(rp,fp) struct RastPort *rp; FILE *fp; { long size; short x,y,p; int c; if(!fread(&size,4,1,fp)) return(BAD_IFF); if(cmode==0) { /* Compression mode 0: no compression */ for(y=0;y2) return(UNKNOWN_COMPRESSION); if(WriteBMHD(w,fp,mode)) return(WRITE_ERROR); if(WriteCMAP(w->WScreen,fp)) return(WRITE_ERROR); if(WriteCAMG(w->WScreen,fp)) return(WRITE_ERROR); if(initcomp((short)w->Width,(short)w->Height,(short)w->WScreen->BitMap.Depth, mode)) return(NO_MEMORY); if(WriteBODY(w,fp,mode)) return(WRITE_ERROR); IFFCleanup(); return(0); } /************************************************************************** * * * IFF-Cleanup: frees all allocated memory * * * **************************************************************************/ IFFCleanup() { short a; if(TempX) { for(a=0;a<8;a++) { if(MyBm.Planes[a]) FreeRaster(MyBm.Planes[a],(long)TempX,(long)TempY); } } TempX=TempY=0; } /*********************************** * * * internal functions: * * * ***********************************/ /* ReadHeader: read size-information, viewmode and colors */ static ReadHeader(fp,bmhd,viewmode) FILE *fp; struct BMHD *bmhd; USHORT *viewmode; { short status=0; long id[3],sid,size; if(!fread(id,12,1,fp)) return(BAD_IFF); if(id[0]!='FORM') return(BAD_IFF); if(id[2]!='ILBM') return(BAD_IFF); *viewmode=0; do { if(!fread(&sid,4,1,fp)) return(BAD_IFF); if(sid=='CMAP') { if(status&1) return(BAD_IFF); /* doppelt */ if(ReadCMAP(fp)) return(BAD_IFF); status|=1; } else if(sid=='CAMG') { if(status&2) return(BAD_IFF); /* doppelt */ if(ReadCAMG(fp,viewmode)) return(BAD_IFF); status|=2; } else if(sid=='BMHD') { if(status&4) return(BAD_IFF); /* doppelt */ if(ReadBMHD(fp,bmhd,viewmode)) return(BAD_IFF); status|=4; } else if(sid!='BODY') { if(!fread(&size,4,1,fp)) return(BAD_IFF); size+=size&1; if(fseek(fp,size,1)) return(BAD_IFF); } } while(sid!='BODY'); if(!(status&1) || !(status&4)) return(BAD_IFF); /* Daten fehlen */ if(initcomp((short)bmhd->Width,(short)bmhd->Height,(short)bmhd->Depth, (short)bmhd->Compression)) return(NO_MEMORY); rows=bmhd->Height; bytes=((bmhd->Width+15)>>3)&0xfffe; depth=bmhd->Depth; cmode=bmhd->Compression; if(cmode<0 || cmode>2) return(UNKNOWN_COMPRESSION); return(0); } /* Read chunk BMHD */ static ReadBMHD(fp,bmhd,vmode) FILE *fp; struct BMHD *bmhd; USHORT *vmode; { if(!fread(bmhd,sizeof(struct BMHD),1,fp)) return(BAD_IFF); if(bmhd->Size!=20) return(BAD_IFF); *vmode=0; if(bmhd->Width>400 && bmhd->Depth<=4) *vmode|=HIRES; if(bmhd->Height>300) *vmode|=LACE; if(bmhd->Depth>6) *vmode|=HAM; return(0); } /* read colormap */ static ReadCMAP(fp) FILE *fp; { long size; short a; int r,g,b; if(!fread(&size,4,1,fp)) return(1); if(size % 3) return(1); size/=3; anzcolors=size; for(a=0;a>4); } return(0); } /* read viewmode */ static ReadCAMG(fp,vmode) FILE *fp; USHORT *vmode; { long a; long size; if(!fread(&size,4,1,fp)) return(1); if(size!=4) return(1); if(!fread(&a,4,1,fp)) return(1); *vmode=a&CAMGMASK; return(0); } /* write BMHD */ static WriteBMHD(w,fp,mode) struct Window *w; FILE *fp; short mode; { struct BMHD bm; if(!fwrite("FORM ILBMBMHD",16,1,fp)) return(1); bm.Size=20; bm.Width=w->Width; bm.Height=w->Height; bm.ScrWidth=w->WScreen->Width; bm.ScrHeight=w->WScreen->Height; bm.LeftEdge=bm.TopEdge=0; bm.Depth=w->WScreen->BitMap.Depth; bm.Mask=bm.Pad=0; bm.Compression=mode; bm.Transparent=0; bm.YAspect=11; bm.XAspect=10; if((w->WScreen->ViewPort.Modes&LACE) && !(w->WScreen->ViewPort.Modes&HIRES)) bm.XAspect=20; if(!(w->WScreen->ViewPort.Modes&LACE) && (w->WScreen->ViewPort.Modes&HIRES)) bm.XAspect=5; if(!fwrite(&bm,sizeof(struct BMHD),1,fp)) return(1); return(0); } /* write colormap */ static WriteCMAP(s,fp) struct Screen *s; FILE *fp; { long size; short anz,col; short i; int c; if(!fwrite("CMAP",4,1,fp)) return(1); anz=s->BitMap.Depth; anz=1<32) anz=32; size=3*anz; if(!fwrite(&size,4,1,fp)) return(1); for(i=0;iViewPort.ColorMap,(long)i); c=((col>>8)&0xf)<<4; if(putc(c,fp)==EOF) return(1); c=((col>>4)&0xf)<<4; if(putc(c,fp)==EOF) return(1); c=(col&0xf)<<4; if(putc(c,fp)==EOF) return(1); } return(0); } /* write viewmode */ static WriteCAMG(s,fp) struct Screen *s; FILE *fp; { long a; if(!fwrite("CAMG",4,1,fp)) return(1); a=4; if(!fwrite(&a,4,1,fp)) return(1); a=s->ViewPort.Modes; a&=CAMGMASK; if(!fwrite(&a,4,1,fp)) return(1); return(0); } /* write bitmaps */ static WriteBODY(w,fp,mode) struct Window *w; FILE *fp; short mode; { struct RastPort *rp; struct BitMap *bm; short bytes,rows; long pos; long size,bodysize,depth; short x,y,p; UBYTE *plane; rp=w->RPort; if(!fwrite("BODY ",8,1,fp)) return(1); pos=ftell(fp); bm=MyRast.BitMap; bytes=((w->Width+15)>>3) & 0xfffe; rows=w->Height; depth=bm->Depth; if(mode==2) { for(x=0;x=2 || x2-x>=3) { if(x-lx) { /* save uncompressed bytes */ if(putc((int)(x-lx-1),fp)==EOF) return(1); for(a=lx;a=y3) { if(y-ly==0 && y2-y>=2 || y2-y>=3) { if(y-ly) { /* write uncompressed data */ if(putc(y-ly-1,fp)==EOF) return(1); for(a=ly;a=2 || y3-y>=3) { if(y-ly) { /* write uncompressed data */ if(putc(y-ly-1,fp)==EOF) return(1); for(a=ly;a=count) { if((c=getc(fp))==EOF) return(EOF); cc=c; ptr=0; if(c==128) { /* code for copying columns */ if((c=getc(fp))==EOF) return(EOF); count=c+1; /* count shorts of 256 (value indicating copy mode) */ for(c=0;c=0) { /* read uncompressed data */ count=cc+1; for(c=0;c=count) return(EOF); return(buf[ptr++]); }