#include <stdio.h>
#include <fcntl.h>
/*****************************************************************/
/* Compiler-Aufruf (Aztec c)   : cc decompress.c
   Linker-Aufruf:              : ln decompress.o -lc
*/
/**********************************************************************/

/* öffnet/schließt bildfiles ließt bildzeilen
   decompr. bildzeilen */

#define byte unsigned char

int zl,sp,tp;
unsigned int speich,ungerade;
unsigned int andhigh=0xff00;

int filedes;
int buffer_index;
int i_buffer[256];

/************************************************/
int init_lesen(name)
/* öffnet integer-file <name> zum lesen */
char *name;
{  short i;
   struct FileLock *lock;

   /* zuerst prüfen, ob datei noch benutzt wird */


   filedes=open(name,O_RDONLY);

   if (filedes==-1)
   {
      return(0);
   }


   buffer_index=1000;   /* index so initialisieren, dass beim ersten
                           intread der buffer gefüllt wird */
   return(1);
}


/************************************************/
short intread()
/* liefert ein integer aus dem geoeffneten file */
{
   int i;

   if (buffer_index>255)
   {

      i=read(filedes,&i_buffer[0],512);      /* 512 Bytes lesen */

      buffer_index=0;
   }

   return i_buffer[buffer_index++];
}
/******************************************************/
/******************************************************/
int bild_lesen_init(name,zeilen,spalten,typ)
char *name;
int *zeilen,*spalten,*typ;
/* eröffnet ein bild-file zum lesen. ließt die kennung
   und liefert in *zeilen die anzahl zeilen des bildes,
   in *spalten die anzahl spalten und in *typ den
   typ des bildfiles.
   typ=0:      rgb-file
*/
{  int i;

   if (!init_lesen(name))
      return(0);

   i=0;
   if (intread()==83)
      if (intread()==72)
         if (intread()==87)
                  i=1;              /* kennung ok */
   if (i==0)
   {
      close(filedes);
      return(0);
   }

   zl=intread();  *zeilen=zl;
   sp=intread();  *spalten=sp;
   tp=intread();  *typ=tp;
   ungerade=0;

   return(1);
}
/********************************************************************/
int read_byte()
{
   register int b;
   register unsigned int wuwu;

   if (ungerade==0)
   {
      speich=intread();
      ungerade=1;
      b=speich & 255;
   }
   else
   {
      ungerade=0;
      wuwu=speich & 0xff00;
      wuwu>>=8;
      b=wuwu;
   }
   return b;
}
/*******************************************************************/

decompress_zeile(z,fehler)
byte z[1024];
int *fehler;
/* dekomprimiert ein zeile aus def geöffneten datei und
   speichert sie bei z ab.
   falls ein fehler auftritt wird *fehler auf 1 gesetzt */
{
   register int z1,i,j,zi,x1,x2,glaenge;
   int dx,x1r;
   char ch;
   int stop_zeile;


   stop_zeile=0;        /* flag ,ob eine stop_zeile vorliegt.
                           d.h. wenn zu anfang der Zeile die
                           byte-kombination 255 255 0 vorliegt
                           dann ist die Bild-datei hier fertig
                        */

   z1=1;
   *fehler=0;
   x1=read_byte();
   z[0]=x1;

   if (x1==255)
      stop_zeile=1;     /* aha, könnte stop-zeile sein */

   for (;(z1<sp)&&(*fehler==0);)
   {
    glaenge=read_byte();
    if (glaenge!=255)
    {
      stop_zeile=0;        /* sicher keine stop_zeile */
      if (z1+glaenge>=sp)
            *fehler=1;
      else
      {
         x2=read_byte();

         dx=((x2-x1)<<7)/(glaenge+1);  /* steigung der geraden * 128 */
         x1r=x1<<7;
         for (i=0;i<=glaenge;i++)
         {
            x1r+=dx;
            z[z1]=(x1r>>7);
            z1++;
         }

         x1=x2;
         if (x1==255)
            stop_zeile=1;
      }
    }
    else
    {
         dx=read_byte();
         if (dx!=0)           /* stop_zeile, abbrechen */
           stop_zeile=0;


         if ((dx!=0)&&(z1+dx<=sp))
         {
            for (i=1;(i<=dx)&&(*fehler==0);i++)
               z[z1++]=read_byte();

            x1=z[z1-1];
         }
         else
            *fehler=1;
    }
   }

}
/**********************************************************/

main(argc,argv)
int argc;
char *argv[];
{
   /* beispiel zum lesen von BEAMS-RGB-files */
   int i,j,zeilen,spalten,typ,fehler;
   byte rot[2048],gruen[2048],blau[2048];


   if (argc!=2)
      exit();

   if (!bild_lesen_init(argv[1],&zeilen,&spalten,&typ))
   {
      printf("File nicht zu öffnen oder kein RGB-File\n");
      exit();
   }


   for (j=0,fehler=0;(j<zeilen)&&(!fehler);j++)
   {  /* zeilen lesen, reihenfolge rot,gruen,blau */
      printf("Zeile %d\n",j);
      decompress_zeile(rot,&fehler);
      if (!fehler)
      {
         decompress_zeile(gruen,&fehler);
         if (!fehler)
         { 
            decompress_zeile(blau,&fehler);
            if (!fehler)
            { /* hier irgentetwas mit rot,gruen,blau anfangen*/
              /* z.B. eine Grafik-Karte beschreiben */

            }
         }
      }

   } /* for j */
   close(filedes);

}
