Index: trunk/psLib/src/jpeg/psImageJpeg.c
===================================================================
--- trunk/psLib/src/jpeg/psImageJpeg.c	(revision 27145)
+++ trunk/psLib/src/jpeg/psImageJpeg.c	(revision 28998)
@@ -7,4 +7,5 @@
 #include <string.h>
 
+#include <kapa.h>
 #include "psMemory.h"
 #include "psImage.h"
@@ -134,4 +135,144 @@
     return psImageJpegColormapSet (map, "greyscale");
 }
+
+// XXX need to fix library references for this (psLib does not depend on libkapa)
+# if (0)
+// XXX Add colormap bar with scale (min -> max)
+// XXX Add option to plot the source overlay (pass in bDrawBuffer populated with points?)
+// XXX need to update bDraw APIs to pass in/out structure and avoid the local static 
+bool psImageJpegNew(const psImageJpegColormap *map, const psImage *image, const char *filename,
+                 float min, float max)
+{
+    PS_ASSERT_PTR_NON_NULL(map, false);
+    PS_ASSERT_IMAGE_NON_NULL(image, false);
+    PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, false);
+    PS_ASSERT_VECTOR_NON_NULL(map->red, false);
+    PS_ASSERT_VECTOR_NON_NULL(map->green, false);
+    PS_ASSERT_VECTOR_NON_NULL(map->blue, false);
+    PS_ASSERT_PTR_NON_NULL(filename, false);
+    PS_ASSERT_INT_POSITIVE(strlen(filename), false);
+    PS_ASSERT_FLOAT_REAL(min, false);
+    PS_ASSERT_FLOAT_REAL(max, false);
+
+    float zero, scale;
+    struct jpeg_compress_struct cinfo;
+    struct jpeg_error_mgr jerr;
+
+    long pixel;
+    JSAMPLE *jpegLine;   // Points to data for current line
+    JSAMPROW jpegLineList[1];  // pointer to JSAMPLE row[s]
+    JSAMPLE *jpegImage;
+    JSAMPLE *outPix;
+
+    /* JPEG init calls */
+    cinfo.err = jpeg_std_error (&jerr);
+    jpeg_create_compress (&cinfo);
+
+    /* open file, prep for jpeg */
+    FILE *f = fopen(filename, "w");
+    if (!f) {
+	psError(PS_ERR_IO, true, "failed to open %s for output\n", filename);
+	return false;
+    }
+    jpeg_stdio_dest(&cinfo, f);
+
+    /* set up color jpeg buffers */
+    int quality = 75;
+    cinfo.image_width = image->numCols; // image width and height, in pixels
+    cinfo.image_height = image->numRows;
+    cinfo.input_components = 3;
+    cinfo.in_color_space = JCS_RGB;
+    jpeg_set_defaults (&cinfo);
+    jpeg_set_quality (&cinfo, quality, true); // limit to baseline-JPEG values
+    jpeg_start_compress (&cinfo, true);
+
+    psU8 *Rpix = map->red->data.U8;
+    psU8 *Gpix = map->green->data.U8;
+    psU8 *Bpix = map->blue->data.U8;
+
+    if (max == min) {
+	zero = min - 0.1;
+	scale = 256.0/0.2;
+    } else {
+	zero = min;
+	scale = 256.0/(max - min);
+    }
+
+    int dx = image->numCols;
+    int dy = image->numRows;
+
+    // output image buffer and line buffer
+    jpegLine = psAlloc (3*dx*sizeof(JSAMPLE));
+    jpegImage = psAlloc (3*dx*dy*sizeof(JSAMPLE));
+
+    // first copy the image data into the output buffer 
+    for (int j = 0; j < dy; j++) {
+	psF32 *row = image->data.F32[j];
+
+	outPix = jpegLine;
+	for (int i = 0; i < dx; i++, outPix += 3) {
+	    if (isfinite(row[i])) {
+		pixel = PS_JPEG_SCALEVALUE(row[i],zero,scale);
+		outPix[0] = Rpix[pixel];
+		outPix[1] = Gpix[pixel];
+		outPix[2] = Bpix[pixel];
+	    } else {
+		// XXX NAN value should be set per-color map
+		outPix[0] = 0x00;
+		outPix[1] = 0xff;
+		outPix[2] = 0x00;
+	    }
+	}
+	memcpy (&jpegImage[j*3*dx], jpegLine, 3*dx);
+    }
+
+    bDrawBuffer *bdbuf = bDrawBufferCreate(dx, dy);
+    bDrawSetBuffer(bdbuf);
+    bDrawColor red = KapaColorByName("red");
+    bDrawSetStyle (red, 1, 0);
+    bDrawCircle(40.0, 20.0, 3.0);
+
+    {
+	int Npalette;
+	png_color *palette = KapaPNGPalette (&Npalette);
+	bDrawColor white = KapaColorByName ("white");
+	for (int j = 0; j < dy; j++) {
+	    for (int i = 0; i < dx; i++) {
+		bDrawColor color = bdbuf[0].pixels[j][i];
+		if (color == white) continue;
+		jpegImage[j*3*dx + 3*i + 0] = palette[color].red;
+		jpegImage[j*3*dx + 3*i + 1] = palette[color].green;
+		jpegImage[j*3*dx + 3*i + 2] = palette[color].blue;
+	    }
+	}
+    }
+    bDrawBufferFree (bdbuf);
+
+    // write out the image buffer
+    for (int j = 0; j < image->numRows; j++) {
+	jpegLineList[0] = &jpegImage[j*3*dx];
+	if (jpeg_write_scanlines(&cinfo, jpegLineList, 1) == 0) {
+	    psError(PS_ERR_IO, true, "Unable to write line %d to JPEG", j);
+	    psFree(jpegLine);
+	    psFree(jpegImage);
+	    fclose(f);
+	    return false;
+	}
+    }
+
+    jpeg_finish_compress(&cinfo);
+    if (fclose(f) == EOF) {
+	psError(PS_ERR_IO, true, "Failed to close %s", filename);
+	psFree(jpegLine);
+	psFree(jpegImage);
+	return false;
+    }
+    jpeg_destroy_compress(&cinfo);
+
+    psFree(jpegLine);
+    psFree(jpegImage);
+    return true;
+}
+# endif
 
 bool psImageJpeg(const psImageJpegColormap *map, const psImage *image, const char *filename,
