/* GEM-View 3.00 SAVING Modul: Bild als IFF-Bild 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 "iff.h"

#define Write(a,b,c,d)  write(d,c,a)

#define TRUE   1
#define FALSE  0



void Save_iff (SAVE_Structure *saveS, unsigned int verbose)
{
  Image          *image;
  char           *filename;
  unsigned int    windepth;
  int             fd;
  char           *data, out, mask, set;
  long            col, line, plane,
                  RealLine, i;
  unsigned char  *raster[24];
  IFF_HEADER      iff_header;
  CHUNK_HEADER    chunk_header;
  BITMAP_HEADER   bitmap_header;
  long            width, height,
                  num_colors;
  short           planes;

  image      = saveS->image;
  filename   = saveS->out_filename;
  windepth   = saveS->screen_depth;
  
  width      = image->width;
  height     = image->height;
  planes     = image->depth;
  num_colors = (image->rgb.used < (1UL << planes)) ? image->rgb.used : (1UL << planes);

  *(long*)&iff_header.form_id = 'FORM';
  iff_header.lenght  = 2 * sizeof(CHUNK_HEADER) + sizeof(BITMAP_HEADER) +
                       width * height * planes / 8L + 4L;
  if (num_colors)
    iff_header.lenght += sizeof(CHUNK_HEADER) + num_colors * 3L;
  *(long*)&iff_header.file_id = 'ILBM';
  
  bitmap_header.width             = image->unalignwidth ? image->unalignwidth : image->width;
  bitmap_header.height            = (unsigned int) height;
  bitmap_header.off_x             = 0;
  bitmap_header.off_y             = 0;
  bitmap_header.planes            = planes;
  bitmap_header.mask              = 0;
  bitmap_header.compressed        = 0;
  bitmap_header.unused            = 0;
  bitmap_header.transparent_color = 0;
  bitmap_header.x_aspect          = 0;
  bitmap_header.y_aspect          = 0;
  bitmap_header.page_width        = bitmap_header.width;
  bitmap_header.page_height       = (unsigned int)height;
  
  saveS->print.printout ("  Saving IFF Imagefile '%s' ... ", filename);

  if ((fd = saveS->output.open(filename)) > 0) {
    if (saveS->output.Write(&iff_header, 1L, sizeof(iff_header), fd) != sizeof(iff_header))
      goto CloseAndRemove;

    *(long*)&chunk_header.chunk_id = 'BMHD';
    chunk_header.lenght   = sizeof(bitmap_header);
    if (saveS->output.Write(&chunk_header, 1L, sizeof(chunk_header), fd) != sizeof(chunk_header))
      goto CloseAndRemove;
    if (saveS->output.Write(&bitmap_header, 1L, sizeof(bitmap_header), fd) != sizeof(bitmap_header))
      goto CloseAndRemove;

    if (num_colors) {
      *(long*)&chunk_header.chunk_id = 'CMAP';
      chunk_header.lenght   = num_colors * 3L;
      if (saveS->output.Write(&chunk_header, 1L, sizeof(chunk_header), fd) != sizeof(chunk_header))
        goto CloseAndRemove;
      for (col = 0; col < num_colors; col++) {
        out = (char)(image->rgb.red[col] >> 8);
        if (saveS->output.Write(&out, 1L, 1L, fd) != 1L)
          goto CloseAndRemove;
        out = (char)(image->rgb.green[col] >> 8);
        if (saveS->output.Write(&out, 1L, 1L, fd) != 1L)
          goto CloseAndRemove;
        out = (char)(image->rgb.blue[col] >> 8);
        if (saveS->output.Write(&out, 1L, 1L, fd) != 1L)
          goto CloseAndRemove;
      }
    }

    *(long*)&chunk_header.chunk_id = 'BODY';
    chunk_header.lenght   = width * height * planes / 8L;
    if (saveS->output.Write(&chunk_header, 1L, sizeof(chunk_header), fd) != sizeof(chunk_header))
      goto CloseAndRemove;


    if (MONOCHROMEP(image)) {
      RealLine = (image->width >> 4) + ((image->width & 0x000F) ? 1 : 0);
      RealLine += RealLine;

      for (line = 0; line < height; line++) {
        raster[0] = image->data + ((long)line * RealLine);

        if (saveS->output.Write(raster[0], 1L, RealLine, fd) != RealLine)
          goto CloseAndRemove;
      }
    }
    
    if (ATARI_RGBP(image)) {
      RealLine = (image->width >> 4) + ((image->width & 0x000F) ? 1 : 0);
      RealLine += RealLine;

      for (line = 0; line < height; line++) {
        raster[0] = image->data + ((long)line * RealLine);
        for (plane = 1; plane < planes; plane++)
          raster[plane] = raster[plane-1] + (long)RealLine * height;

        for (plane = 0; plane < planes; plane++)
          if (saveS->output.Write(raster[plane], 1L, RealLine, fd) != RealLine)
            goto CloseAndRemove;
      }
    }
    
#if 1
    if (RGBP(image)) {
      RealLine = (image->width >> 4) + ((image->width & 0x000F) ? 1 : 0);
      RealLine <<= 4;
      for (line = 0; line < image->height; line++) {
        data = image->data + ((long)line * RealLine);
        for (plane = 0; plane < planes; plane++) {
          mask = 1U << plane;
          out = 0;
          set = 0x80;
          for (i = 0; i < RealLine; i++) {
            if (data[i] & mask)
              out |= set;
            if ((set >>= 1) == 0) {
              if (saveS->output.Write(&out, 1L, 1L, fd) != 1L)
                goto CloseAndRemove;
              out = 0;
              set = 0x80;
            }
          }
        }
      }
    }
#endif
    
#if 1
    if (TRUECOLORP(image)) {
      saveS->error.printerr("not supported TrueColor IFF imagefiles.\n");
      saveS->output.close (fd);
      return;
    }
#endif
    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;
}
