/*->c.tiff */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>

#include "h.os"
#include "h.wimp"
#include "h.bbc"
#include "h.flex"

#include "h.DrawLevel0"

#include "h.def"
#include "h.wos"
#include "h.main"
#include "h.mym"
#include "h.serial"
#include "h.strdef"
#include "h.ram"
#include "h.file"
#include "h.pr"
#include "h.key"
#include "h.script"
#include "h.dir"
#include "h.batch"
#include "h.fsx"
#include "h.timex"
#include "h.view"

#include "h.tiff"



/*****************************************************************************/

#define TIFFSHORT 3
#define TIFFLONG  4
#define TIFFRAT   5

os_error * tiff_hdr(int fh)
{
 os_error * ep;
 static char hdr[8]={
                    'I' ,'I',
                    0x2A,0x0,
                    0x8 ,0x0,0x0,0x0};

 ep=fs_write(fh,hdr,8);

 return(ep);
}



os_error * tiff_readhdr(int fh)
{
 os_error * ep;
 char       hdr[4];
 int        offset;

 ep=fs_readerr(fh,hdr,4);
 if(!ep) ep=fs_readerr(fh,&offset,4);
 if(!ep) ep=fs_seek(fh,offset);

 return(ep);
}





/* tag, 16 bit tag number */
/* type 
     1 = BYTE.      8-bit unsigned integer.
     2 = ASCII.     8-bit bytes that store ASCII codes; the last byte must
                     be null.
     3 = SHORT.     A 16-bit (2-byte) unsigned integer.
     4 = LONG.      A 32-bit (4-byte) unsigned integer.
     5 = RATIONAL.  Two LONGs: the first represents the numerator of a
                     fraction, the second the denominator.
*/

/* length, number of vals of type */
/* offset, where they are. or if fit in 4 bytes value, left justified */



static os_error * tiff_tag(int fh,int tag,int type,int length,int offset)
{
 os_error * ep;
 int        temp[3];

 temp[0]=tag+(type<<16);
 temp[1]=length;
 temp[2]=offset;

 ep=fs_write(fh,temp,12);

 return(ep);
}



static os_error * tiff_readtag(int fh,int * tag,int* type,int * length,
                                                          int * offset)
{
 os_error * ep;
 int        temp[3];

 ep=fs_readerr(fh,temp,12);

 *tag   =temp[0] & 0xFFFF;
 *type  =temp[0] >> 16;
 *length=temp[1];
 *offset=temp[2];

 return(ep);
}




/* n is the number of entries */

static os_error * tiff_startifd(int fh,int n)
{
 os_error * ep;

 ep=fs_write(fh,&n,2);

 return(ep);
}



/* n is the number of entries */

static os_error * tiff_readifd(int fh,int * n)
{
 os_error * ep;

 *n=0;

 ep=fs_readerr(fh,n,2);

 return(ep);
}




/* offset of next ifd */

static os_error * tiff_endifd(int fh,int offset)
{
 os_error * ep;

 ep=fs_write(fh,&offset,4);

 return(ep);
}



static os_error * tiff_readendifd(int fh,int * offset)
{
 os_error * ep;

 ep=fs_readerr(fh,offset,4);

 return(ep);
}



static os_error * tiff_subfiletype255(int fh,int type)
{
 return(tiff_tag(fh,255,TIFFSHORT,1,type));
}


static os_error * tiff_imagewidth256(int fh,int width)
{
 return(tiff_tag(fh,256,TIFFLONG,1,width));
}


static os_error * tiff_imageheight257(int fh,int height)
{
 return(tiff_tag(fh,257,TIFFLONG,1,height));
}


static os_error * tiff_bitspersample258(int fh,int bps)
{
 return(tiff_tag(fh,258,TIFFSHORT,1,bps));
}


static os_error * tiff_compression259(int fh,int type)
{
 return(tiff_tag(fh,259,TIFFSHORT,1,type));
}


static os_error * tiff_interp262(int fh,int type)
{
 return(tiff_tag(fh,262,TIFFSHORT,1,type));
}


static os_error * tiff_stripoffset273(int fh,int offset)
{
 return(tiff_tag(fh,273,TIFFLONG,1,offset));
}


/* samples per pixel */

static os_error * tiff_spp277(int fh,int spp)
{
 return(tiff_tag(fh,277,TIFFSHORT,1,spp));
}


static os_error * tiff_g3opts292(int fh,int opts)
{
 return(tiff_tag(fh,292,TIFFLONG,1,opts));
}


static os_error * tiff_rowsperstrip278(int fh,int rps)
{
 return(tiff_tag(fh,278,TIFFLONG,1,rps));
}


static os_error * tiff_stripbytecounts279(int fh,int sbc)
{
 return(tiff_tag(fh,279,TIFFLONG,1,sbc));
}


static os_error * tiff_xres282(int fh,int offset)
{
 return(tiff_tag(fh,282,TIFFRAT,1,offset));   /* was long */
}


static os_error * tiff_yres283(int fh,int offset)
{
 return(tiff_tag(fh,283,TIFFRAT,1,offset));  /* was long */
}


static os_error * tiff_rational(int fh,int num,int denom)
{
 os_error * ep;
                                                                                         ep=fs_write(fh,&num,4);
 if(!ep) ep=fs_write(fh,&denom,4);

 return(ep);
}


static os_error * tiff_readrational(int fh,int * num,int * denom)
{
 os_error * ep;
                                                                                         ep=fs_readerr(fh,num,4);
 if(!ep) ep=fs_readerr(fh,denom,4);

 return(ep);
}



static os_error * tiff_planarconfiguration284(int fh,int planes)
{
 return(tiff_tag(fh,284,TIFFSHORT,1,planes));
}

static os_error * tiff_resolutionunit296(int fh,int unit)
{
 return(tiff_tag(fh,296,TIFFSHORT,1,unit));
}

static os_error * tiff_pagenumber297(int fh,int pn,int tot)
{
 return(tiff_tag(fh,297,TIFFSHORT,2,pn+(tot<<16)));
}


#define     TIFFTAG_GROUP3OPTIONS        292     /* 32 flag bits */
#define     GROUP3OPT_2DENCODING        0x1     /* 2-dimensional coding */
#define     GROUP3OPT_UNCOMPRESSED      0x2     /* data not compressed */
#define     GROUP3OPT_FILLBITS          0x4     /* fill to byte boundary */


#define TIFFMULTI    3
#define TIFFPOSITIVE 1


#define FAXELEMS 16


os_error * faxifd(int fh,int xpx,int ypx,int xres,int yres,int len,
                  int comp,int pn,int tot)
{
 os_error * ep;
 int        offset;
 int        opts;

 opts=0;
 if(comp==FAXCCITT4) 
 {
  comp=FAXCCITT3;
  opts|=GROUP3OPT_2DENCODING;
 }

         ep=fs_tell(fh,&offset);

 if(!ep) ep=tiff_startifd(fh,FAXELEMS);
 if(!ep) ep=tiff_subfiletype255(fh,TIFFMULTI);
 if(!ep) ep=tiff_imagewidth256(fh,xpx);
 if(!ep) ep=tiff_imageheight257(fh,ypx);
 if(!ep) ep=tiff_bitspersample258(fh,1);
 if(!ep) ep=tiff_compression259(fh,comp);
 if(!ep) ep=tiff_interp262(fh,TIFFPOSITIVE);
 if(!ep) ep=tiff_stripoffset273(fh,offset+2+4+12*FAXELEMS+16);
 if(!ep) ep=tiff_spp277(fh,1);
 if(!ep) ep=tiff_rowsperstrip278(fh,ypx);      /* was 1 */
 if(!ep) ep=tiff_stripbytecounts279(fh,len);

 if(!ep) ep=tiff_xres282(fh,offset+2+4+12*FAXELEMS);
 if(!ep) ep=tiff_yres283(fh,offset+2+4+12*FAXELEMS+8);

 if(!ep) ep=tiff_planarconfiguration284(fh,1);

 if(!ep) ep=tiff_g3opts292(fh,opts);
 if(!ep) ep=tiff_resolutionunit296(fh,2);
 if(!ep) ep=tiff_pagenumber297(fh,pn,tot);

 if(!ep) 
 {
  if(pn<tot) ep=tiff_endifd(fh,offset+2+4+12*FAXELEMS+16+len);
  else       ep=tiff_endifd(fh,0);
 }

 if(!ep) ep=tiff_rational(fh,xres,1);
 if(!ep) ep=tiff_rational(fh,yres,1);

 return(ep);
}



os_error * faxifdwr(int fh,framestr * fx)
{
 os_error * err;

 err=faxifd(fh,fx->xpix,fx->ypix,fx->xres,fx->yres,fx->length,
                  fx->compression,fx->pn,fx->tot);
 return(err);
}




os_error * tiff_readframe(int fh,framestr * fx)
{
 os_error * ep;
 int        n;
 int        i;
 int        tag;
 int        type;
 int        length;
 int        offset;
 int        temp;
 int        num;
 int        denom;
 int        options;



 options=0;

 fx->bitrev=0;

 ep=tiff_readifd(fh,&n);
 if(!ep)
 {
  for(i=0;i<n;i++)
  {

   ep=tiff_readtag(fh,&tag,&type,&length,&offset);
   if(ep) break;

   switch(tag)
   {
    case 259: 
             fx->compression=offset;
             break;

    case 256:
             fx->xpix=offset;
             break;

    case 257:
             fx->ypix=offset;
             break;

    case 266:
             fx->bitrev=(offset==2);  /* 2== rev, 1==normal */
             break;

    case 279:
             fx->length=offset;
             break;

    case 297:
             fx->pn=offset & 0xFFFF;
             fx->tot=offset>>16;
             break;

    case 282:
                     ep=fs_tell(fh,&temp);
             if(!ep) ep=fs_seek(fh,offset);
             if(!ep) ep=tiff_readrational(fh,&num,&denom);
             if(!ep) ep=fs_seek(fh,temp);
             if(denom==0) denom=1;
             fx->xres=num/denom;
             break;

    case 283:
                     ep=fs_tell(fh,&temp);
             if(!ep) ep=fs_seek(fh,offset);
             if(!ep) ep=tiff_readrational(fh,&num,&denom);
             if(!ep) ep=fs_seek(fh,temp); 
             if(denom==0) denom=1;
             fx->yres=num/denom;
             break;

    case 273:
             fx->strip=offset;
             break;

    case 292:
             options=offset;
             break;

   }
  }

  if(!ep) ep=tiff_readendifd(fh,&fx->next);
 }

 if(fx->compression==FAXCCITT3 && (options & GROUP3OPT_2DENCODING))
                                                   fx->compression=FAXCCITT4;

 return(ep);
}

