

/*
 * a simple little program to convert raw Lynxx CCD images into
 * a more readable format.  The raw Lynxx images use 3 bytes to 
 * store the values for 2 pixels, since the camera produces only
 * 12 bits of information for each pixel.  The bits for two 
 * consecutive pixels are arranged in 3 consecutive bytes like so:
 *
 *
 *         byte 0                byte 1                         byte 2
 *         buf[0]                buf[1]                         buf[2]
 *     --------------     -------------------------         --------------
 *      low byte 1          high nib 2 | high nib 1           low byte 2
 *
 *
 * So, to reconstruct a 16-bit integer for each of the two pixels, we
 * must combine low bytes with the appropriate high nibble (4 bites)
 * from the middle byte.  Here's the C expression:
 *
 *		pixel 1 value = buf[0];
 *		pixel 1 value += (buf[1] & 0x0F) << 8;
 *
 * 		pixel 2 value = buf[2];
 *		pixel 2 value += (buf[1] & 0xF0) << 4;
 * 
 *
 * This program writes an output binary file with 165x192 2-byte unsigned 
 * integer data values, one for each pixel of the image.  The default
 * output name is "lynxx.out", but the user can override this with
 * a command-line argument.
 *
 * One can use the XVista program "convert" to transform the output 
 * binary file into a FITS file, with minimal header.
 *
 * Example:
 *
 *     % ls -l sat1.lnx
 *       48 -rw-rw-r--   1 richmond richmond    47520 Oct  1 15:51 sat1.lnx
 *     % ./lynxx sat1.lnx
 *     writing data to file lynxx.out
 *     % ~/xvista/convert lynxx.out 165 192 lynxx.fts
 *     % ls -l sat1.*
 *       66 -rw-rw-r--   1 richmond richmond    66240 Oct  1 17:45 sat1.fts
 *       48 -rw-rw-r--   1 richmond richmond    47520 Oct  1 15:51 sat1.lnx
 * 
 *
 * 
 * Usage: lynxx lynxfile [outfile] 
 *
 *
 * Michael Richmond, Oct 14, 1997
 */





#include <stdio.h>
#include <math.h>

main(int argc, char *argv[])
{
	FILE *fp_in, *fp_out;
	char fname[100];
	char foutname[100];
	unsigned char buf[1000];
	char bufout[1000];
	char c1, c2, c3;
	int i, j, k;
	unsigned short int si, sj, sk;
	int nib1, nib2, nib3, nib4, nib5, nib6;
	double x, y;

	if (argc < 2 || argc > 3) {
		fprintf(stderr, "usage: lynxx lynxfile [outfile]\n");
		exit(1);
	}

	/* input file name must be given as first argument */
	sprintf(fname, "%s", argv[1]);

	/* 
	 * if second argument supplied, use it as output file name.
	 * otherwise, use default output name "lynxx.out".
	 */
	if (argc == 3) {
		sprintf(foutname, "%s", argv[2]);
	}
	else {
		sprintf(foutname, "lynxx.out");
	}


	if ((fp_in = fopen(fname, "r")) == NULL) {
		fprintf(stderr, "can't open file %s\n", fname);
		exit(1);
	}

	if ((fp_out = fopen(foutname, "w")) == NULL) {
		fprintf(stderr, "can't open file %s for output\n", foutname);
		exit(1);
	}
	fprintf(stderr, "writing data to file %s\n", foutname);

	for (i = 0; i < 165; i++) {
		for (j = 0; j < 192/2; j++) {

			if (fread(buf, 1, 3, fp_in) != 3) {
				fprintf(stderr, "read failed on row %d col %d\n",
					i, j);
				fflush(fp_out);
				fclose(fp_out);
				exit(1);
			}

			nib1 = (unsigned int) (buf[0] & 0xF0);
			nib2 = (unsigned int) (buf[0] & 0x0F);
			nib3 = (unsigned int) (buf[1] & 0xF0);
			nib4 = (unsigned int) (buf[1] & 0x0F);
			nib5 = (unsigned int) (buf[2] & 0xF0);
			nib6 = (unsigned int) (buf[2] & 0x0F);

			si = buf[0];
			si += (buf[1] & 0x0F) << 8;
			sj = buf[2];
			sj += (buf[1] & 0xF0) << 4;

#ifdef DEBUG
			printf(" %4d %4d: %03o %03o  %03o %03o  %03o %03o   %5d %5d \n", i, j, nib1, nib2, nib3, nib4, nib5, nib6, si, sj);
#endif

			fwrite((void *) (&si), 2, 1, fp_out);
			fwrite((void *) (&sj), 2, 1, fp_out);

		}
	}

	fclose(fp_in);
	fclose(fp_out);
}

