

/*

________________________________________________________________

        biff2sunraster.c
        $Id: biff2sunraster.c,v 1.35 1997/01/09 16:46:17 svein Exp $
        Copyright 1990, Blab, UiO
        Image processing lab, Department of Informatics
        University of Oslo
        E-mail: blab@ifi.uio.no
________________________________________________________________
  
  Permission to use, copy, modify and distribute this software and its
  documentation for any purpose and without fee is hereby granted, 
  provided that this copyright notice appear in all copies and that 
  both that copyright notice and this permission notice appear in supporting
  documentation and that the name of B-lab, Department of Informatics or
  University of Oslo not be used in advertising or publicity pertaining 
  to distribution of the software without specific, written prior permission.

  B-LAB DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL B-LAB
  BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 

*/

#ifndef lint

static char *Id = "$Id: biff2sunraster.c,v 1.35 1997/01/09 16:46:17 svein Exp $, Blab, UiO";

#endif



#include <xite/includes.h>
#include <xite/biff.h>
#include <xite/sunraster.h>
#include XITE_STDIO_H
#include XITE_UNISTD_H
#include <xite/color.h>
#include <xite/readarg.h>
#include <xite/utils.h>
#include <xite/convert.h>
#include XITE_TYPES_H
#include XITE_FCNTL_H
#include XITE_FILE_H
#include XITE_MALLOC_H
#include "rast.h"


#define ERR_BIFF   1
#define ERR_OPEN   2
#define ERR_WRITE  3
#define ERR_BANDS  4
#define ERR_PIXTYP 5
#define ERR_MALLOC 6

char *biff2sunraster_error[] =
{
  "Ok",
  "Cannot open BIFF-file",
  "Open error on Sun rasterfile",
  "Write error on Sun rasterfile",
  "Biff file must have 1 band",
  "Illegal BIFF pixeltype",
  "Memory allocation error",
};








/*L*

________________________________________________________________

		compress
________________________________________________________________

Name:		compress
Syntax:		
Description:
Return value:
Author:		Otto Milvang
________________________________________________________________

*/



#ifndef FUNCPROTO
static void compress(band, bit_data, depth, threshold)
IBAND band;
unsigned char *bit_data;
int depth, threshold;
#else /* FUNCPROTO */
static void compress(IBAND band, unsigned char *bit_data, int depth, int threshold)
#endif /* FUNCPROTO */
{
  unsigned char *byte_data;
  unsigned short *bit;
  register int count, w;
  register unsigned short pix;
  int xsize, ysize, y;

  xsize = Ixsize(band);
  ysize = Iysize(band);
  bit = (unsigned short *) bit_data;
  for(y=1; y<= ysize; y++)
    {
      byte_data = &band[y][1];
      w = xsize;
      if (depth == 1)
	{
	  count = 16;
	  pix = 0;
	  while (w--)
	    { 
	      pix = pix + pix;
	      if(*byte_data++ >= threshold) pix++;
	      if (--count == 0)
		{
		  *bit++ = pix;
		  count = 16; pix=0;
		}
	    }
	  if (count<16) 
	    {	
	      pix <<= count;
	      *bit++ = pix;
	    }
	} else {
	  while (w--) *bit_data++ = *byte_data++;
	}
    }	
}

#ifndef FUNCPROTO
static int _Iwrite_(fd, ptr, size)
int fd, size;
unsigned char *ptr;
#else /* FUNCPROTO */
static int _Iwrite_(int fd, unsigned char *ptr, int size)
#endif /* FUNCPROTO */
{
  int blokk, total = 0;
  for(;;)
    {
      blokk = write(fd, ptr, size);
      if (blokk <= 0) break;
      ptr = (unsigned char*) (ptr+blokk);
      size -= blokk;
      total += blokk;
      if(size == 0) break;
      }
  return(total);
}





/*F:write_sunraster*

________________________________________________________________

		write_sunraster
________________________________________________________________

Name:		write_sunraster - write BIFF-image to sun_rasterfile

Syntax:         | #include <xite/sunraster.h>
                | #include <xite/color.h>
		| 
                | int write_sunraster( IMAGE img, Color_tab tab,
                |    int len, char* filename, int depth,
                |    int threshold );

Description:	Write a BIFF-image (and a colortable) to a sun_rasterfile.
                'filename' is the name of a sunrasterfile, 'img' is
	        a  BIFF image and 'tab' the colortable.
	        If 'tab' == NULL, no colormap is written.
		'depth' is the depth of the raster image.

Restriction:	Accepts only one-band unsigned byte images.
                Depth must be 1 (binary image) or 8 (pseudocolor).

Return value:	| 0 - Ok
                | 1 - Error in handling BIFF-file
		| 2 - Cannot open Sunrasterfile
		| 3 - Write error on Sunrasterfile
		| 4 - BIFF file must have 1 band
                | 5 - Illegal BIFF pixeltype
		| 6 - Memory allocation error

Author:		Otto Milvang

Id: 		$Id: biff2sunraster.c,v 1.35 1997/01/09 16:46:17 svein Exp $
________________________________________________________________

*/

#ifndef FUNCPROTO
int write_sunraster(img, tab, len, filename, depth, threshold)
IMAGE img;
Color_tab tab;
char *filename;
int len;
int depth, threshold;
#else /* FUNCPROTO */
int write_sunraster(IMAGE img, Color_cell *tab, int len, char *filename, int depth, int threshold)
#endif /* FUNCPROTO */
{
  char *col;
  struct rasterfile ras;
  IBAND b;
  char *bit;
  int fd, i;
  int size, width, height;
  unsigned long p;
  char used[256];

  if (tab)
    {
      ras.ras_maptype   = RMT_EQUAL_RGB;
      ras.ras_maplength = 768;
      ras.ras_depth = depth;
      col = (char *) malloc( (unsigned) 768);
      if (col == NULL) return(ERR_MALLOC);

      for (i=0; i<256; i++) used[i] = 0;
      for (i=0; i<len; i++)
	{
	  p = PseudoBasePart(tab[i].pixel);
	  used[p] = 1;
	  col[ p       ] = ((tab[i].red   >> 8) & 0x0ff);
	  col[ p + 256 ] = ((tab[i].green >> 8) & 0x0ff);
	  col[ p + 512 ] = ((tab[i].blue  >> 8) & 0x0ff);
	}
      for (i=0; i<256; i++) {
	if (!used[i]) {
	  col[i] = 0;
	  col[i+256] = 0;
	  col[i+512] = 0;
	}
      }
    } else {
      ras.ras_maptype   = 0;
      ras.ras_maplength = 0;
      ras.ras_depth = depth;
      col = NULL;
    }


  if (img == NULL) return(ERR_BIFF);
  if (Inbands(img) > 1) return(ERR_BANDS);
  b = img[1];
  if (Ipixtyp(b) != Iu_byte_typ) return(ERR_PIXTYP);
  
  ras.ras_magic     = RAS_MAGIC;
  ras.ras_width     = width  = Ixsize(b);
  ras.ras_height    = height = Iysize(b);
  ras.ras_type      = RT_STANDARD;

  if (depth == 1)
    {
      ras.ras_length    = size   = ((width+15)/16) * height * 2;
      bit =  malloc( (unsigned) size);
      if (bit == NULL) return(ERR_MALLOC);
      compress(b, (unsigned char *) bit, depth, threshold); 
    } else {
      ras.ras_length    = size   = width * height;
      bit = (char *) &b[1][1];
    }

  unlink(tilde_expand(filename));
  fd = open(tilde_expand(filename), O_RDWR | O_CREAT, 0666);
  if (fd == -1) return(ERR_OPEN);
 
  len = _Iwrite_(fd, (unsigned char *) &ras, sizeof(struct rasterfile));
  if (len != sizeof(struct rasterfile)) return(ERR_WRITE);

  if (ras.ras_maplength)
    {
      len  = _Iwrite_(fd, (unsigned char *) col, ras.ras_maplength);
      if (len != ras.ras_maplength) return(ERR_WRITE);
    }

  if (ras.ras_length)
    {
      len  = _Iwrite_(fd, (unsigned char *) bit, ras.ras_length);
      if (len != ras.ras_length) return(ERR_WRITE);
    }
  (void) close(fd);
  return(0);
}




#ifdef MAIN

/*P:biff2sunraster*

________________________________________________________________

		biff2sunraster
________________________________________________________________

Name:		biff2sunraster - convert BIFF-file to sunraster-file

Syntax:		| biff2sunraster [-t <v>] <BIFF-file> <sunraster-file> \\
                |     [<colfile>]

Description:	Convert a 'BIFF-file' to a 'sunraster-file'. Use the BIFF
                colortable in 'colfile' if the 'colfile' argument is
		supplied.

                If the pixeltype of 'BIFF-file' is not unsigned byte, the
		image will be converted to unsigned byte before conversion to
		sunraster. The pixeltype conversion does not imply any
		scaling. Values too large (or to small) to be represented by
		the new pixeltype are set to the maximum (or minimum) possible
		value. A warning is issued to this effect.

Options:        &-t v
                Threshold the input image at the value 'v' and write a
		sunraster file of depth 1. Default: Depth 8, no
		thresholding.

Restrictions:	Images with pixeltype different from unsigned byte will be
                converted to unsigned byte, without any prior scaling.

Return value:	| 0 - Ok
                | 1 - Error in handling BIFF-file
		| 2 - Cannot open Sunrasterfile
		| 3 - Write error on Sunrasterfile
		| 4 - BIFF file must have 1 band
                | 5 - Illegal BIFF pixeltype
		| 6 - Memory allocation error
		| 7 - Illegal command-line

Author:		Otto Milvang

Examples:	| biff2sunraster sun-raster8/andy.im8 andy.img andy.col
                | biff2sunraster -t 120 sun-raster1/andy.im1 andy.img

Id: 		$Id: biff2sunraster.c,v 1.35 1997/01/09 16:46:17 svein Exp $
________________________________________________________________

*/


#ifndef FUNCPROTO
int main(argc,argv)
int argc;
char *argv[];
#else /* FUNCPROTO */
int main(int argc, char **argv)
#endif /* FUNCPROTO */
{
  IMAGE img;
  Color_tab tab;
  int stat, thres, depth, len;
  char *name;

  Iset_message(1);
  Iset_abort(1);
  InitMessage(&argc, argv, xite_app_std_usage_text(
      "Usage: %s  [-t <v>] <BIFF-file> <raster-file> [<colfile>]\n"));

  if (argc == 1) Usage(0, NULL);

  thres = read_iswitch(&argc, argv, "-t", -1);
  if (argc != 3 && argc != 4) Usage(7, "Illegal number of arguments.\n");

  img = Iread_image(argv[1]);
  if (thres == -1) depth = 8; else depth = 1;
  
  if (argc == 4 && depth == 1) {
    Usage(7, "Cannot handle option -t along with <colfile> argument.\n");
  }

  if ((argc == 4) && (depth == 8)) {
    if ((stat = color_read(argv[3], tab, &name, &len)) != Iok)
      Ierr_action(stat);
  }

  if (Ipixtyp(img[1]) > Iu_byte_typ) {
    IBAND b;

    Warning(0, "%s%s\n",
	    "Converting BIFF image to smaller pixeltype. ",
	    "May loose range.");

    b      = (IBAND) img[1];
    img[1] = mkConvertBand(img[1], Iu_byte_typ);
    Idel_band(&b);
  }

  stat = write_sunraster(img, argc == 4 ? tab : NULL, len,
			 argv[2], depth, thres);
  if (stat) Error(2, "%s\n", biff2sunraster_error[stat]);

  return(0);
}

#endif
