/* zeisstopnm.c - convert a Zeiss confocal image into a portable anymap
**
** Copyright (C) 1993 by Oliver Trepte, oliver@fysik4.kth.se
**
** Derived from the pbmplus package,
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
**
**
** This conversion utility is based on a mail from Keith Bartels to
** the confocal mail group (confocal@ubvm.cc.buffalo.edu) in June 1993.
**
** I'm including here a description of the Zeiss confocal image format. I
** obtained this over the phone on 4-10-1991 form a Zeiss Engineer, and from
** what I hear, it is probably not correct for the new scopes.
** Zeiss puts its header information and the end of the file, so I call it
** a tailer.  This is nice because most conversions programs that work with raw
** image files will read the image simply ignore the tailer.  The file contains:
**
** The image data: NxN  1 byte pixels (where N is the number of pixels in a
** scan line) in a standard raw rastering order.
**
** The tailer contains:
** 256 bytes: the blue Look-Up-Table (LUT)
** 256 bytes: the red LUT
** 256 bytes: the green LUT
** 8 bytes: empty
** 2 bytes: no. of columns in the image. hi-byte, low-byte
** 2 bytes: no. of rows in the image.
** 2 bytes: x-position of upper left pixel  (0 for 512x512 images)
** 2 bytes: y-position of upper left pixel  (0 for 512x512 images)
** 16 bytes: empty
** 32 bytes: test from upper right corner of image, ASCII.
** 128 bytes: text from the bottom two rows of the screen, ASCII.
** 64 bytes: reserved
** -----------
** 1024 bytes TOTAL
**
** So, image files contain NxN + 1024 bytes.
**
** Keith Bartels
** keith@VISION.EE.UTEXAS.EDU
**
*/

#include "pnm.h"

int
main( argc, argv )
    int argc;
    char* argv[];
    {
    FILE* ifp;
    gray* grayrow;
    register gray* gP;
    int argn, row, i;
    register int col, val;
    int rows=0, cols=0;
    int format = 0;
    xel* xelrow;
    register xel* xP;
    char* buf = NULL;
    unsigned char *lutr, *lutg, *lutb;
    long nread = 0;
    unsigned char* data;
    unsigned char* byteP;
    char* usage = "[-pgm|-ppm] [Zeissfile]";


    pnm_init( &argc, argv );

    argn = 1;

    while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
	{
	if ( pm_keymatch( argv[argn], "-pgm", 3 ) )
	    {
	    if ( argn >= argc )
		pm_usage( usage );
	    format = PGM_TYPE;
	    }
	else if ( pm_keymatch( argv[argn], "-ppm", 3 ) )
	    {
	    if ( argn >= argc )
		pm_usage( usage );
	    format = PPM_TYPE;
	    }
	else
	    pm_usage( usage );
	++argn;
	}

    if ( argn < argc )
	{
	ifp = pm_openr( argv[argn] );
	++argn;
	}
    else
	ifp = stdin;

    if ( argn != argc )
	pm_usage( usage );

    /* Read the image to a buffer */

    buf = pm_read_unknown_size( ifp, &nread );

    /* Check the format of the file */

    if (nread <=1024)
	pm_error( "Input file not in Zeiss format (too small)" );

    lutg = (unsigned char *)buf+(nread-1024+512);
    lutr = (unsigned char *)buf+(nread-1024+256);
    lutb = (unsigned char *)buf+(nread-1024);

    cols = ((unsigned char) buf[nread-1024+768+8]) +
	(((unsigned char) buf[nread-1024+768+9]) << 8);
    rows = ((unsigned char) buf[nread-1024+768+10]) +
	(((unsigned char) buf[nread-1024+768+11]) << 8);

    if ( cols <= 0 )
	pm_error( "invalid cols: %d", cols );
    if ( rows <= 0 )
	pm_error( "invalid rows: %d", rows );

    if (cols*rows != nread-1024)
	pm_error( "Hmm, %d rows, %d cols, %d total image size",
		 rows, cols, nread-1024);

    /* Choose pgm or ppm */
    /* If the LUTs all contain 0,1,2,3,4..255, it is a pgm file */

    for (i=0; i<256 && format==0; i++)
	if (lutr[i] != i || lutg[i] != i || lutb[i] != i)
	    format = PPM_TYPE;

    if (format == 0)
	format = PGM_TYPE;

    pnm_writepnminit( stdout, cols, rows, 255, format, 0 );
    xelrow = pnm_allocrow( cols );
    byteP = (unsigned char *) buf;

    switch ( PNM_FORMAT_TYPE(format) )
        {
        case PGM_TYPE:
        pm_message( "writing PGM file, %d rows %d columns", rows, cols );
        break;

        case PPM_TYPE:
        pm_message( "writing PPM file, %d rows %d columns", rows, cols );
        break;

        default:
        pm_error( "shouldn't happen" );
        }

    for ( row = 0; row < rows; ++row )
    {
	switch ( PNM_FORMAT_TYPE(format) )
	{
	case PGM_TYPE:
	    for ( col = 0, xP = xelrow; col < cols; ++col, ++xP, ++byteP )
		PNM_ASSIGN1( *xP, *byteP );
	    break;

	case PPM_TYPE:
	    for ( col = 0, xP = xelrow; col < cols; ++col, ++xP, ++byteP )
		PPM_ASSIGN( *xP, lutr[*byteP], lutg[*byteP], lutb[*byteP] );
	    break;

        default:
	    pm_error( "shouldn't happen" );
        }

	pnm_writepnmrow( stdout, xelrow, cols, 255, format, 0 );
    }

    free( buf );
    pm_close( stdout );

    exit( 0 );
}
