home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- * *
- * iffpack *
- * *
- * Routines for loading and saving pictures with windows *
- * using the old formats and the new compression format *
- * *
- **************************************************************************/
- #include <intuition/intuition.h>
- #include <functions.h>
- #include <stdio.h>
-
- #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;y<rows;y++) {
- for(p=0;p<depth;p++) {
- for(x=0;x<bytes;x++) {
- if((c=getc(fp))==EOF) return(BAD_IFF);
- MyBm.Planes[p][x]=c;
- }
- }
- ClipBlit(&MyRast,0L,0L,rp,0L,(long)y,(long)TempX,1L,192L);
- WaitBlit();
- }
- } else if(cmode==1) { /* Compression mode 1: normal compression */
- for(y=0;y<rows;y++) {
- for(p=0;p<depth;p++) {
- for(x=0;x<bytes;x++) {
- if((c=compget(fp))==EOF) return(BAD_IFF);
- if(c<256) {
- MyBm.Planes[p][x]=c;
- }
- }
- }
- ClipBlit(&MyRast,0L,0L,rp,0L,(long)y,(long)TempX,1L,192L);
- WaitBlit();
- }
- } else if(cmode==2) { /* Compression mode 2: new compression */
- for(x=0;x<bytes;x++) {
- for(p=0;p<depth;p++) {
- for(y=0;y<rows;y++) {
- if((c=compget(fp))==EOF) return(BAD_IFF);
- if(c<256) {
- MyBm.Planes[p][y<<1]=c;
- }
- }
- }
- ClipBlit(&MyRast,0L,0L,rp,(long)(x<<3),0L,8L,(long)TempY,192L);
- WaitBlit();
- }
- }
- IFFCleanup();
- return(0);
- }
-
- /**************************************************************************
- * *
- * WriteWindow(fp,w,mode): *
- * *
- * Write the window win to the file with FILE-Pointer fp using the *
- * compression method mode *
- * *
- **************************************************************************/
-
- WriteWindow(fp,w,mode)
- FILE *fp;
- struct Window *w;
- short mode;
- {
- if(mode<0 || mode>2) 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<size;a++) {
- if((r=getc(fp))==EOF) return(1);
- if((g=getc(fp))==EOF) return(1);
- if((b=getc(fp))==EOF) return(1);
- r&=0xf0;
- g&=0xf0;
- b&=0xf0;
- colors[a]=(r<<4)|g|(b>>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<<anz;
- if(anz>32) anz=32;
- size=3*anz;
- if(!fwrite(&size,4,1,fp)) return(1);
-
- for(i=0;i<anz;i++) {
- col=GetRGB4(s->ViewPort.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<bytes;x++) {
- if(x) {
- ClipBlit(rp,(x-1L)<<3L,0L,&MyRast,0L,0L,16L,(long)TempY,192L);
- WaitBlit();
- } else {
- ClipBlit(rp,0L,0L,&MyRast,8L,0L,8L,(long)TempY,192L);
- WaitBlit();
- }
- for(p=0;p<depth;p++) {
- if(comprow(fp,rows,x,p)) return(1);
- }
- }
- } else if(mode==1) {
- for(y=0;y<rows;y++) {
- if(y) {
- ClipBlit(rp,0L,(long)y-1L,&MyRast,0L,0L,(long)TempX,2L,192L);
- WaitBlit();
- } else {
- ClipBlit(rp,0L,0L,&MyRast,0L,1L,(long)TempX,1L,192L);
- WaitBlit();
- }
- for(p=0;p<depth;p++) {
- if(compline(fp,bytes,y,p)) return(1);
- }
- }
- } else {
- for(y=0;y<rows;y++) {
- ClipBlit(rp,0L,(long)y,&MyRast,0L,0L,(long)TempX,1L,192L);
- WaitBlit();
- for(p=0;p<depth;p++) {
- plane=MyBm.Planes[p];
- for(x=0;x<bytes;x++) {
- if(putc((int)(plane[x]),fp)==EOF) return(1);
- }
- }
- }
- }
-
- size=ftell(fp);
- bodysize=size-pos;
- if(fseek(fp,pos-4L,0)) return(1);
- if(!fwrite(&bodysize,4,1,fp)) return(1);
- if(fseek(fp,4L,0)) return(1);
- size-=8;
- if(!fwrite(&size,4,1,fp)) return(1);
- return(0);
- }
-
- /* compress one line */
-
- static compline(fp,bytes,y,p)
- FILE *fp;
- short bytes;
- short y,p;
- {
- short x,x2,x3,lx;
- short found;
- short a;
- UBYTE * ptr;
- UBYTE *lptr;
-
- ptr=&MyBm.Planes[p][bytes];
- lptr=MyBm.Planes[p];
- lx=0;
- for(x=0;x<bytes;x++) {
- x2=x;
- found=0; /* count bytes with equal value */
- while(ptr[x2]==ptr[x2+1] && x2<bytes-1 && x2-x<127) x2++;
- x2++;
- if((x-lx)==0 && x2-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<x;a++) if(putc((int)ptr[a],fp)==EOF) return(1);
- }
- /* save compressed bytes */
- if(putc(x-x2+1,fp)==EOF) return(1);
- if(putc((int)ptr[x],fp)==EOF) return(1);
- x=x2-1;
- found=1;
- }
- if(found) {
- lx=x+1;
- } else {
- if(x-lx==127) {
- /* save uncompressed bytes */
- if(fputc(127,fp)==EOF) return(1);
- for(a=lx;a<=x;a++) if(putc(ptr[a],fp)==EOF) return(1);
- lx=x+1;
- }
- }
- }
- if(lx<bytes) {
- if(putc(bytes-lx-1,fp)==EOF) return(1);
- for(a=lx;a<bytes;a++) if(putc((int)ptr[a],fp)==EOF) return(1);
- }
- return(0);
- }
-
- /* compress one column (width: 8 bit) */
-
- static comprow(fp,rows,x,p)
- FILE *fp;
- short rows;
- short x,p;
- {
- short y,y2,y3,ly;
- short found;
- short a;
- UBYTE * ptr;
-
- ptr=MyBm.Planes[p];
- ly=0;
- for(y=0;y<rows;y++) {
- y3=y2=y;
- found=0; /* count bytes with equal value */
- while(ptr[(y2<<1)+1]==ptr[(y2<<1)+3] && y2<rows-1 &&
- y2-y<127) y2++;
- y2++;
- if(x) {
- /* compare with previous column */
- while(ptr[y3<<1]==ptr[(y3<<1)+1] && y3<rows &&
- y3-y<256) y3++;
- }
- if(y2>=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<y;a++)
- if(putc((int)ptr[(a<<1)+1],fp)==EOF) return(1);
- }
- /* write compressed data: Byte-Run */
- if(putc(y-y2+1,fp)==EOF) return(1);
- if(putc((int)ptr[(y<<1)+1],fp)==EOF) return(1);
- y=y2-1;
- found=1;
- }
- } else {
- if(!y-ly && y3-y>=2 || y3-y>=3) {
- if(y-ly) {
- /* write uncompressed data */
- if(putc(y-ly-1,fp)==EOF) return(1);
- for(a=ly;a<y;a++)
- if(putc((int)ptr[(a<<1)+1],fp)==EOF) return(1);
- }
- /* write compressed data: copy previous column */
- if(putc(128,fp)==EOF) return(1);
- if(putc(y3-y-1,fp)==EOF) return(1);
- y=y3-1;
- found=1;
- }
- }
- if(found) {
- ly=y+1;
- } else {
- if(y-ly==127) {
- /* write uncompressed data */
- if(fputc(127,fp)==EOF) return(1);
- for(a=ly;a<=y;a++)
- if(putc(ptr[(a<<1)+1],fp)==EOF) return(1);
- ly=y+1;
- }
- }
- }
- if(ly<rows) {
- if(putc(rows-ly-1,fp)==EOF) return(1);
- for(a=ly;a<rows;a++)
- if(putc((int)ptr[(a<<1)+1],fp)==EOF) return(1);
- }
- return(0);
- }
-
- /* init compression */
-
- static initcomp(width,height,depth,mode)
- short width,height,depth,mode;
- {
- short a;
- if(TempX) IFFCleanup();
- if(mode!=2) {
- TempX=width;
- TempY=2;
- InitRastPort(&MyRast);
- InitBitMap(&MyBm,(long)depth,(long)width,2L);
- for(a=0;a<8;a++) MyBm.Planes[a]=0;
- for(a=0;a<depth;a++) {
- if(!(MyBm.Planes[a]=AllocRaster((long)width,2L))) return(NO_MEMORY);
- }
- } else {
- TempX=16;
- TempY=height;
- InitRastPort(&MyRast);
- InitBitMap(&MyBm,(long)depth,16L,(long)height);
- for(a=0;a<8;a++) MyBm.Planes[a]=0;
- for(a=0;a<depth;a++) {
- if(!(MyBm.Planes[a]=AllocRaster(16L,(long)height))) return(NO_MEMORY);
- }
- }
- MyRast.BitMap=&MyBm;
- count=ptr=0;
- runlen=1;
- return(0);
- }
-
- /* uncompress bitplanes */
-
- static compget(fp)
- FILE *fp;
- {
- int c;
- char cc;
- UBYTE val;
- if(ptr>=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<count;c++) buf[c]=256;
- } else if(cc>=0) { /* read uncompressed data */
- count=cc+1;
- for(c=0;c<count;c++) if((buf[c]=getc(fp))==EOF) return(EOF);
- } else {
- count=-cc+1; /* read compressed data and uncompress it */
- if((c=getc(fp))==EOF) return(EOF);
- val=c;
- for(c=0;c<count;c++) buf[c]=val;
- }
- }
- if(ptr>=count) return(EOF);
- return(buf[ptr++]);
- }
-
-
-