/* GEM-View 3.00 SAVING Modul: Bild im Tag-Image-File-Format speichern
   (c) 22.10.1993 by Dieter Fiebelkorn
                     Grner Weg 29a
                     D-45768 Marl
                     (GERMANY)
*/

#include <stdio.h>
#include "image.h"
#include "moduls.h"
#include "tiff.h"

#define Write(a,b,c,d)  write(d,c,a)

#define SPLIT_STRIP 1

#define TRUE   1
#define FALSE  0

#define INFO1_LEN          14L
#define INFO2_LEN           0L
#define INFO3_LEN           0L
#define INFO1_DEC           ((INFO3_LEN ? 0 : 1))
#define INFO2_DEC           ((INFO3_LEN ? 0 : 1) + (INFO1_LEN ? 0 : 1))
#define INFO3_DEC           ((INFO3_LEN ? 0 : 1) + (INFO1_LEN ? 0 : 1) + (INFO2_LEN ? 0 : 1))

#define OSUBFILETYPE        1
#define IMAGEWIDTH          2
#define IMAGELENGTH         3
#define BITSPERSAMPLE       4
#define PHOTOMETRIC         6
#define IMAGEDESCRIPTION   10
#define STRIPOFFSETS      (11 - INFO1_DEC)
#define SAMPLESPERPIXEL   (13 - INFO1_DEC)
#define ROWSPERSTRIP      (14 - INFO1_DEC)
#define STRIPBYTECOUNTS   (15 - INFO1_DEC)
#define MINSAMPLEVALUE    (16 - INFO1_DEC)
#define MAXSAMPLEVALUE    (17 - INFO1_DEC)
#define PLANARCONFIG      (18 - INFO1_DEC)
#define SOFTWARE          (19 - INFO1_DEC)
#define DATETIME          (20 - INFO2_DEC)
#define COLORMAP          (21 - INFO3_DEC)

#define NORMAL_TAGS       (21 - INFO3_DEC)
#define PALETTE_TAGS      (22 - INFO3_DEC)

#define ADDITIONAL_LEN     14L
#define SHIFT_SHORT        16

#define START0            (0)
#define PART_0            (STRIPBYTECOUNTS + 1)

#define START2            (OSUBFILETYPE)
#define PART_2            (PHOTOMETRIC     - START2 + 1)
#define START3            (STRIPOFFSETS)
#define PART_3            (STRIPBYTECOUNTS - START3 + 1)
#define SKIPTAGS           4L


static
TIFFHeader   tiffHeader   = {TIFF_BIGENDIAN, TIFF_VERSION, 0x00000008L};
static
TIFFDirEntry tiffTags[PALETTE_TAGS] = { 
                              {TIFFTAG_SUBFILETYPE     , TIFF_LONG ,  1, 0x00000000L},
                              {TIFFTAG_OSUBFILETYPE    , TIFF_SHORT,  1, 0x00010000L},
                              {TIFFTAG_IMAGEWIDTH      , TIFF_SHORT,  1, 0x00000000L}, /* [ 2] */
                              {TIFFTAG_IMAGELENGTH     , TIFF_SHORT,  1, 0x00000000L}, /* [ 3] */
                              {TIFFTAG_BITSPERSAMPLE   , TIFF_SHORT,  1, 0x00000000L}, /* [ 4] */
                              {TIFFTAG_COMPRESSION     , TIFF_SHORT,  1, 0x00010000L},
                              {TIFFTAG_PHOTOMETRIC     , TIFF_SHORT,  1, 0x00000000L}, /* [ 6] */
                              {TIFFTAG_THRESHHOLDING   , TIFF_SHORT,  1, 0x00010000L},
                              {TIFFTAG_CELLWIDTH       , TIFF_SHORT,  1, 0x00010000L},
                              {TIFFTAG_CELLLENGTH      , TIFF_SHORT,  1, 0x00010000L},
#if INFO3_LEN
                              {TIFFTAG_IMAGEDESCRIPTION, TIFF_ASCII,  0, 0x00000000L}, /* [10] */
#endif
                              {TIFFTAG_STRIPOFFSETS    , TIFF_LONG ,  1, 0x00000000L}, /* [11] */
                              {TIFFTAG_ORIENTATION     , TIFF_SHORT,  1, 0x00010000L},
                              {TIFFTAG_SAMPLESPERPIXEL , TIFF_SHORT,  1, 0x00000000L}, /* [13] */
                              {TIFFTAG_ROWSPERSTRIP    , TIFF_LONG ,  1, 0x00000000L}, /* [14] */
                              {TIFFTAG_STRIPBYTECOUNTS , TIFF_LONG ,  1, 0x00000000L}, /* [15] */
                              {TIFFTAG_MINSAMPLEVALUE  , TIFF_SHORT,  1, 0x00000000L}, /* [16] */
                              {TIFFTAG_MAXSAMPLEVALUE  , TIFF_SHORT,  1, 0x00000000L}, /* [17] */
                              {TIFFTAG_PLANARCONFIG    , TIFF_SHORT,  1, 0x00010000L},
#if INFO1_LEN
                              {TIFFTAG_SOFTWARE        , TIFF_ASCII,  0, 0x00000000L}, /* [18] */
#endif
#if INFO2_LEN
                              {TIFFTAG_DATETIME        , TIFF_ASCII,  0, 0x00000000L}, /* [19] */
#endif
                              {TIFFTAG_COLORMAP        , TIFF_SHORT,  0, 0x00000000L}  /* [20] */
                            };
#if INFO1_LEN
static
char TIFFInfo1[INFO1_LEN] = "GEM-View 2.30\0";
#endif
#if INFO2_LEN
static
char TIFFInfo2[INFO2_LEN] = "YYYY/MM/DD HH:MM:SS\0";
#endif
#if INFO3_LEN
static
char TIFFInfo3[INFO3_LEN] = "12345678.123\0\0";
#endif



void Save_tiff (SAVE_Structure *saveS, unsigned int verbose, unsigned int save_tc, unsigned int packing)
{
  Image          *image;
  char           *filename;
  unsigned int    windepth;
  int             fd;
  char           *raster[24];
  char           *data, out, mask, out_tc;
  long            line, RealLine, plane, w, i;
  unsigned long   offs_software, offs_bpsample, offs_datetime,
                  offs_imagename, offs_colormap, offs_imagedata, 
                  stripbytecounts, rowsperstrip, stripsperimage,
                  bitspersample, samplesperpixel, null = 0;
  short           tags, color, colors, count_map, planes;
  unsigned short  width, height, bytes;
  
  image      = saveS->image;
  filename   = saveS->out_filename;
  windepth   = saveS->screen_depth;

  if (MONOCHROMEP(image)) {
    colors = image->rgb.used;
    if (colors == 1)
      colors = 2;
    planes = 1;
    bitspersample = 1UL;
    samplesperpixel = 1UL;

    if (colors == 0)
      tiffTags[PHOTOMETRIC].tdir_offset = 0L << SHIFT_SHORT;
    else
      tiffTags[PHOTOMETRIC].tdir_offset = 3UL << SHIFT_SHORT;
    tiffTags[SAMPLESPERPIXEL].tdir_offset = samplesperpixel << SHIFT_SHORT;
    tiffTags[MINSAMPLEVALUE].tdir_offset = 0UL;
    tiffTags[MAXSAMPLEVALUE].tdir_offset = 1UL << SHIFT_SHORT;
  }
  if (PALETTEP(image) && !save_tc) {
    planes = image->depth;
    if (planes <= 1)
      planes = 1;
    if (planes > 1 && planes <= 2)
      planes = 2;
    if (planes > 2 && planes <= 4)
      planes = 4;
    if (planes > 4 && planes <= 8)
      planes = 8;
    if (packing)
      bitspersample = (unsigned long)planes;
    else
      bitspersample = (unsigned long)(planes = 8);
    samplesperpixel = 1UL;
    colors = 1UL << bitspersample;

    tiffTags[PHOTOMETRIC].tdir_offset = 3UL << SHIFT_SHORT;
    tiffTags[SAMPLESPERPIXEL].tdir_offset = samplesperpixel << SHIFT_SHORT;
    tiffTags[MINSAMPLEVALUE].tdir_offset = 0UL;
    tiffTags[MAXSAMPLEVALUE].tdir_offset = (long)(colors - 1) << SHIFT_SHORT;
  }
  if (TRUECOLORP(image) || save_tc) {
    colors = 0;
    planes = 24;
    bitspersample = 8UL;
    samplesperpixel = 3UL;

    tiffTags[PHOTOMETRIC].tdir_offset = 2UL << SHIFT_SHORT;
    tiffTags[SAMPLESPERPIXEL].tdir_offset = samplesperpixel << SHIFT_SHORT;
  }
  
  if (colors == 0)
    tags = NORMAL_TAGS;
  else
    tags = PALETTE_TAGS;
#if !SPLIT_STRIP
  if (!split_strip)
    tags -= SKIPTAGS;
#endif
  if (TRUECOLORP(image) || save_tc)
    tags -= 2;

  count_map = 3 * colors;
  offs_software = ADDITIONAL_LEN + tags * sizeof(TIFFDirEntry);
  offs_bpsample = offs_software + INFO1_LEN;
  offs_datetime = offs_bpsample;
  if (samplesperpixel == 3UL)
    offs_datetime += 4 * sizeof(short);
  else
    offs_bpsample = bitspersample << SHIFT_SHORT;
  offs_imagename= offs_datetime + INFO2_LEN;
  offs_colormap = offs_imagename+ INFO3_LEN;
  offs_imagedata= offs_colormap + sizeof(short) * count_map;

  if (image->unalignwidth != 0)
    width = image->unalignwidth;
  else
    width = image->width;
  if (samplesperpixel * bitspersample == 1)
    width = 16L * (width / 16L + (width % 16L ? 1 : 0));
  if (samplesperpixel * bitspersample == 2)
    width =  8L * (width /  8L + (width %  8L ? 1 : 0));
  if (samplesperpixel * bitspersample == 4)
    width =  4L * (width /  4L + (width %  4L ? 1 : 0));
  if (samplesperpixel * bitspersample == 8)
    width =  2L * (width /  2L + (width %  2L ? 1 : 0));
  height  = image->height;
#if INFO1_LEN
  tiffTags[SOFTWARE].tdir_count          = INFO1_LEN;
  tiffTags[SOFTWARE].tdir_offset         = offs_software;
#endif
#if INFO2_LEN
  tiffTags[DATETIME].tdir_count          = INFO2_LEN;
  tiffTags[DATETIME].tdir_offset         = offs_datetime;
#endif
#if INFO3_LEN
  tiffTags[IMAGEDESCRIPTION].tdir_count  = INFO3_LEN;
  tiffTags[IMAGEDESCRIPTION].tdir_offset = offs_imagename;
#endif
  tiffTags[IMAGEWIDTH].tdir_offset       = (long)width  << SHIFT_SHORT;
  tiffTags[IMAGELENGTH].tdir_offset      = (long)height << SHIFT_SHORT;
  tiffTags[BITSPERSAMPLE].tdir_count     = samplesperpixel;
  tiffTags[BITSPERSAMPLE].tdir_offset    = offs_bpsample;
  tiffTags[COLORMAP].tdir_count          = count_map;
  tiffTags[COLORMAP].tdir_offset         = offs_colormap;
  
  stripbytecounts = (long)width * height * samplesperpixel * bitspersample / 8L;
#if !SPLIT_STRIP
  if (!split_strip || stripbytecounts < 8192L) {
#else
  if (stripbytecounts < 8192L) {
#endif
    rowsperstrip = 0xFFFFFFFFL;
    stripsperimage = 1L;
    tiffTags[STRIPBYTECOUNTS].tdir_type = TIFF_LONG;
  } else {
    rowsperstrip = 8192L / ((long)width * samplesperpixel * bitspersample / 8L);
    stripsperimage = ((long)height + rowsperstrip - 1) / rowsperstrip;
    if (stripsperimage > 2) {
      stripbytecounts = offs_imagedata;
      offs_imagedata += stripsperimage * sizeof(short);
    } else {
      bytes = (int)(rowsperstrip * width * samplesperpixel * bitspersample / 8L);
      null = (unsigned long)bytes << 16;
      stripbytecounts = (long)width * height * samplesperpixel * bitspersample / 8L;
      bytes = (int)(stripbytecounts - ((stripsperimage - 1L) * bytes));
      null |= bytes;
      stripbytecounts = null;
    }
    tiffTags[STRIPBYTECOUNTS].tdir_type = TIFF_SHORT;
  }
  tiffTags[ROWSPERSTRIP].tdir_offset     = rowsperstrip;
  tiffTags[STRIPBYTECOUNTS].tdir_count   = stripsperimage;
  tiffTags[STRIPBYTECOUNTS].tdir_offset  = stripbytecounts;
  tiffTags[STRIPOFFSETS].tdir_count      = stripsperimage;
  tiffTags[STRIPOFFSETS].tdir_offset     = offs_imagedata;

  
  saveS->print.printout ("  Saving TIFF Image '%s' ... ", filename);

  if ((fd = saveS->output.open(filename)) > 0) {
    if (saveS->output.Write(&tiffHeader, 1L, sizeof(TIFFHeader), fd) != sizeof(TIFFHeader))
      goto CloseAndRemove;

    if (saveS->output.Write(&tags, 1L, sizeof(short), fd) != sizeof(short))
      goto CloseAndRemove;
    
#if !SPLIT_STRIP
    if (split_strip) {
#endif
      if (saveS->output.Write(&tiffTags[START0], 1L, sizeof(TIFFDirEntry) * PART_0, fd) != sizeof(TIFFDirEntry) * PART_0)
        goto CloseAndRemove;
#if !SPLIT_STRIP
    } else {
      if (saveS->output.Write(&tiffTags[START2], 1L, sizeof(TIFFDirEntry) * PART_2, fd) != sizeof(TIFFDirEntry) * PART_2)
        goto CloseAndRemove;
#if INFO3_LEN
      if (saveS->output.Write(&tiffTags[IMAGEDESCRIPTION], 1L, sizeof(TIFFDirEntry), fd) != sizeof(TIFFDirEntry))
        goto CloseAndRemove;
#endif
      if (saveS->output.Write(&tiffTags[START3], 1L, sizeof(TIFFDirEntry) * PART_3, fd) != sizeof(TIFFDirEntry) * PART_3)
        goto CloseAndRemove;
    }
#endif
    if (!(TRUECOLORP(image) || save_tc)) {
      if (saveS->output.Write(&tiffTags[MINSAMPLEVALUE], 1L, sizeof(TIFFDirEntry), fd) != sizeof(TIFFDirEntry))
        goto CloseAndRemove;
      if (saveS->output.Write(&tiffTags[MAXSAMPLEVALUE], 1L, sizeof(TIFFDirEntry), fd) != sizeof(TIFFDirEntry))
        goto CloseAndRemove;
    }
    if (saveS->output.Write(&tiffTags[PLANARCONFIG], 1L, sizeof(TIFFDirEntry), fd) != sizeof(TIFFDirEntry))
      goto CloseAndRemove;
#if INFO1_LEN
    if (saveS->output.Write(&tiffTags[SOFTWARE], 1L, sizeof(TIFFDirEntry), fd) != sizeof(TIFFDirEntry))
      goto CloseAndRemove;
#endif
#if INFO2_LEN
    if (saveS->output.Write(&tiffTags[DATETIME], 1L, sizeof(TIFFDirEntry), fd) != sizeof(TIFFDirEntry))
      goto CloseAndRemove;
#endif
    if (colors != 0)
      if (saveS->output.Write(&tiffTags[COLORMAP], 1L, sizeof(TIFFDirEntry), fd) != sizeof(TIFFDirEntry))
        goto CloseAndRemove;
    
    null = 0L;
    if (saveS->output.Write(&null, 1L, sizeof(long), fd) != sizeof(long))
      goto CloseAndRemove;

#if INFO1_LEN
    if (saveS->output.Write(TIFFInfo1, 1L, INFO1_LEN, fd) != INFO1_LEN)
      goto CloseAndRemove;
#endif
    if (samplesperpixel == 3UL) {
      null = 0x00080008L;
      if (saveS->output.Write(&null, 1L, sizeof(long), fd) != sizeof(long))
        goto CloseAndRemove;
      null = 0x00080000L;
      if (saveS->output.Write(&null, 1L, sizeof(long), fd) != sizeof(long))
        goto CloseAndRemove;
    }
#if INFO2_LEN
    if (saveS->output.Write(TIFFInfo2, 1L, INFO2_LEN, fd) != INFO2_LEN)
      goto CloseAndRemove;
#endif
#if INFO3_LEN
    if (saveS->output.Write(TIFFInfo3, 1L, INFO3_LEN, fd) != INFO3_LEN)
      goto CloseAndRemove;
#endif
    
    null = 0;
    for (color = 0; color < colors; color++) {
      if (color < image->rgb.used) {
        if (saveS->output.Write(&image->rgb.red[color], 1L, sizeof(short), fd) != sizeof(short))
          goto CloseAndRemove;
      } else {
        if (saveS->output.Write(&null, 1L, sizeof(short), fd) != sizeof(short))
          goto CloseAndRemove;
      }
    }
    for (color = 0; color < colors; color++) {
      if (color < image->rgb.used) {
        if (saveS->output.Write(&image->rgb.green[color], 1L, sizeof(short), fd) != sizeof(short))
          goto CloseAndRemove;
      } else {
        if (saveS->output.Write(&null, 1L, sizeof(short), fd) != sizeof(short))
          goto CloseAndRemove;
      }
    }
    for (color = 0; color < colors; color++) {
      if (color < image->rgb.used) {
        if (saveS->output.Write(&image->rgb.blue[color], 1L, sizeof(short), fd) != sizeof(short))
          goto CloseAndRemove;
      } else {
        if (saveS->output.Write(&null, 1L, sizeof(short), fd) != sizeof(short))
          goto CloseAndRemove;
      }
    }


    if (stripsperimage > 2) {
      bytes = (int)(rowsperstrip * width * samplesperpixel * bitspersample / 8L);
      for (null = 1; null < stripsperimage; null++) {
        if (saveS->output.Write(&bytes, 1L, sizeof(short), fd) != sizeof(short))
          goto CloseAndRemove;
      }
      stripbytecounts = (long)width * height * samplesperpixel * bitspersample / 8L;
      bytes = (int)(stripbytecounts - ((stripsperimage - 1L) * bytes));
      if (saveS->output.Write(&bytes, 1L, sizeof(short), fd) != sizeof(short))
        goto CloseAndRemove;
    }
    if (stripsperimage > 1) {
      offs_imagedata += stripsperimage * sizeof(long);
      bytes = (int)(rowsperstrip * width * samplesperpixel * bitspersample / 8L);
      for (null = 0; null < stripsperimage; null++) {
        if (saveS->output.Write(&offs_imagedata, 1L, sizeof(long), fd) != sizeof(long))
          goto CloseAndRemove;
        offs_imagedata += bytes;
      }
    }

    
    if (MONOCHROMEP(image)) {
      RealLine = (image->width >> 4) + ((image->width & 0x000F) ? 1 : 0);
      RealLine += RealLine;
      for (line = 0; line < image->height; line++) {
        raster[0] = image->data + ((long)line * RealLine);

        if (saveS->output.Write(raster[0], 1L, width / 8, fd) != width / 8)
          goto CloseAndRemove;
      }
    }
    
    if (ATARI_RGBP(image)) {
      RealLine = (image->width >> 4) + ((image->width & 0x000F) ? 1 : 0);
      RealLine += RealLine;

      for (line = 0; line < image->height; line++) {
        raster[0] = image->data + ((long)line * RealLine);
        for (plane = 1; plane < image->depth; plane++)
          raster[plane] = raster[plane-1] + (long)RealLine * height;

        switch ((int)bitspersample | (save_tc ? 0x80 : 0x00)) {
          case 2:
            mask = 0x80;
            for (i = 0, w = 0; w < width; w+=4) {
              out = 0;
              for (plane = 0; plane < image->depth; plane++) {
                if (raster[plane][i] & mask)
                  out |= (1U << plane);
              }
              out <<= 2;
              mask >>= 1;
              for (plane = 0; plane < image->depth; plane++) {
                if (raster[plane][i] & mask)
                  out |= (1U << plane);
              }
              out <<= 2;
              mask >>= 1;
              for (plane = 0; plane < image->depth; plane++) {
                if (raster[plane][i] & mask)
                  out |= (1U << plane);
              }
              out <<= 2;
              mask >>= 1;
              for (plane = 0; plane < image->depth; plane++) {
                if (raster[plane][i] & mask)
                  out |= (1U << plane);
              }
              mask >>= 1;
              if (saveS->output.Write(&out, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;

              if (mask == 0) {
                mask = 0x80;
                i++;
              }
            }
            break;
          case 4:
            mask = 0x80;
            for (i = 0, w = 0; w < width; w += 2) {
              out = 0;
              for (plane = 0; plane < image->depth; plane++) {
                if (raster[plane][i] & mask)
                  out |= (1U << plane);
              }
              out <<= 4;
              mask >>= 1;
              for (plane = 0; plane < image->depth; plane++) {
                if (raster[plane][i] & mask)
                  out |= (1U << plane);
              }
              mask >>= 1;
              if (saveS->output.Write(&out, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;

              if (mask == 0) {
                mask = 0x80;
                i++;
              }
            }
            break;
          case 8:
            mask = 0x80;
            for (i = 0, w = 0; w < width; w++) {
              out = 0;
              for (plane = 0; plane < image->depth; plane++) {
                if (raster[plane][i] & mask)
                  out |= (1U << plane);
              }
              mask >>= 1;
              if (saveS->output.Write(&out, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;

              if (mask == 0) {
                mask = 0x80;
                i++;
              }
            }
            break;
          case 0x82:
          case 0x84:
          case 0x88:
            mask = 0x80;
            for (i = 0, w = 0; w < width; w++) {
              out = 0;
              for (plane = 0; plane < image->depth; plane++) {
                if (raster[plane][i] & mask)
                  out |= (1U << plane);
              }
              mask >>= 1;
              
              out_tc = (char)(image->rgb.red[out] >> 8);
              if (saveS->output.Write(&out_tc, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;
              out_tc = (char)(image->rgb.green[out] >> 8);
              if (saveS->output.Write(&out_tc, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;
              out_tc = (char)(image->rgb.blue[out] >> 8);
              if (saveS->output.Write(&out_tc, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;

              if (mask == 0) {
                mask = 0x80;
                i++;
              }
            }
            break;
        }
      }
    }
    
    if (RGBP(image)) {
      RealLine = (image->width >> 4) + ((image->width & 0x000F) ? 1 : 0);
      RealLine <<= 4;
      for (line = 0; line < image->height; line++) {
        raster[0] = image->data + ((long)line * RealLine);

        switch ((int)bitspersample | (save_tc ? 0x80 : 0x00)) {
          case 1:
          case 0x81:
            data = raster[0];
            for (w = 0; w < width; w += 8) {
              out  = *data++ << 7;
              out |= *data++ << 6;
              out |= *data++ << 5;
              out |= *data++ << 4;
              out |= *data++ << 3;
              out |= *data++ << 2;
              out |= *data++ << 1;
              out |= *data++;
              if (saveS->output.Write(&out, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;
            }
            break;
          case 2:
            data = raster[0];
            for (w = 0; w < width; w += 4) {
              out = *data++ << 6;
              out |= *data++ << 4;
              out |= *data++ << 2;
              out |= *data++;
              if (saveS->output.Write(&out, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;
            }
            break;
          case 4:
            data = raster[0];
            for (w = 0; w < width; w += 2) {
              out = *data++ << 4;
              out |= *data++;
              if (saveS->output.Write(&out, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;
            }
            break;
          case 8:
            if (saveS->output.Write(raster[0], 1L, width, fd) != width)
              goto CloseAndRemove;
            break;
          case 0x82:
          case 0x84:
          case 0x88:
            data = raster[0];
            for (w = 0; w < width; w++) {
              out_tc = (char)(image->rgb.red[*data] >> 8);
              if (saveS->output.Write(&out_tc, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;
              out_tc = (char)(image->rgb.green[*data] >> 8);
              if (saveS->output.Write(&out_tc, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;
              out_tc = (char)(image->rgb.blue[*data] >> 8);
              if (saveS->output.Write(&out_tc, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;
              data++;
            }
            break;
        }
      }
    }
    
    if (TRUECOLORP(image)) {
      RealLine = (image->width >> 4) + ((image->width & 0x000F) ? 1 : 0);
      RealLine <<= 4;
      RealLine = 3 * RealLine;
      for (line = 0; line < image->height; line++) {
        raster[0] = image->data + ((long)line * RealLine);
        data = raster[0];
        if (saveS->output.Write(data, 1L, 3L * width, fd) != 3L * width)
          goto CloseAndRemove;
      }
    }
    if (saveS->output.close(fd) != 0) {
      fd = 0;
      goto CloseAndRemove;
    }
    saveS->print.printout ("done.\n");
    return;
  }
  
CloseAndRemove:
  saveS->events.alert(1, "[3][ | Error in writing!  | |    Disk full ? ][   OK   ]");
  if (fd > 0)
    saveS->output.close(fd);
  saveS->output.delete(filename);
  saveS->print.printout ("error.\n");
  return;
}



void Save_tiff1(SAVE_Structure *saveS, unsigned int verbose)
{
  Save_tiff(saveS, verbose, FALSE, TRUE);
}
