r182: *** empty log message ***
[ctsim.git] / libctsim / imagefile.cpp
index c3d2f67896820bd65fec117fad0b3958cb4b0c11..3f7c0beff717a84bafe3f588816dfc50d29bf0db 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2000 Kevin Rosenberg
 **
-**  $Id: imagefile.cpp,v 1.6 2000/06/28 15:25:34 kevin Exp $
+**  $Id: imagefile.cpp,v 1.10 2000/08/22 16:49:56 kevin Exp $
 **
 **  This program is free software; you can redistribute it and/or modify
 **  it under the terms of the GNU General Public License (version 2) as
@@ -47,29 +47,30 @@ ImageFile::filterResponse (const char* const domainName, double bw, const char*
 }
 
 int
-ImageFile::display (void)
+ImageFile::display (void) const
 {
     double pmin, pmax;
 
-    //    getPixelValueRange (pmin, pmax);
+    getMinMax (pmin, pmax);
 
     return (displayScaling (1, pmin, pmax));
 }
 
 int 
-ImageFile::displayScaling (const int scale, const ImageFileValue pmin, const ImageFileValue pmax)
+ImageFile::displayScaling (const int scale, const ImageFileValue pmin, const ImageFileValue pmax) const
 {
-    int grayscale[256];
     int nx = m_nx;
     int ny = m_ny;
-    ImageFileArray v = getArray();
+    ImageFileArrayConst v = getArray();
+    if (v == NULL || nx == 0 || ny == 0)
+      return 0;
 
 #if HAVE_G2_H
     int pens [nx * ny * scale * scale ];
 
     double view_scale = 255 / (pmax - pmin);
     int id_X11 = g2_open_X11 (nx * scale, ny * scale);
-
+    int grayscale[256];
     for (int i = 0; i < 256; i++) {
        double cval = i / 255.;
        grayscale[i] = g2_ink (id_X11, cval, cval, cval);
@@ -113,11 +114,14 @@ ImageFile::comparativeStatistics (const ImageFile& imComp, double& d, double& r,
        return false;
     }
     ImageFileArrayConst v = getArray();
+    if (v == NULL || m_nx == 0 || m_ny == 0)
+      return false;
+
     ImageFileArrayConst vComp = imComp.getArray();
 
     double myMean = 0.;
-    for (int ix = 0; ix < m_nx; ix++) {
-       for (int iy = 0; iy < m_ny; iy++) {
+    for (unsigned int ix = 0; ix < m_nx; ix++) {
+       for (unsigned int iy = 0; iy < m_ny; iy++) {
            myMean += v[ix][iy];
        }
     }
@@ -127,8 +131,8 @@ ImageFile::comparativeStatistics (const ImageFile& imComp, double& d, double& r,
     double absErrorSum = 0.;
     double sqDiffFromMeanSum = 0.;
     double absValueSum = 0.;
-    for (int ix = 0; ix < m_nx; ix++) {
-       for (int iy = 0; iy < m_ny; iy++) {
+    for (unsigned int ix = 0; ix < m_nx; ix++) {
+       for (unsigned int iy = 0; iy < m_ny; iy++) {
            double diff = v[ix][iy] - vComp[ix][iy];
            sqErrorSum += diff * diff;
            absErrorSum += fabs(diff);
@@ -169,7 +173,9 @@ ImageFile::printComparativeStatistics (const ImageFile& imComp, ostream& os) con
     os << "  Normalized root mean squared distance (d): " << d << endl;
     os << "      Normalized mean absolute distance (r): " << r << endl;
     os << "Worst case distance (2x2 pixel average) (e): " << e << endl;
+    return true;
   }
+  return false;
 }
 
 
@@ -196,6 +202,9 @@ ImageFile::statistics (double& min, double& max, double& mean, double& mode, dou
     int ny = m_ny;
     ImageFileArrayConst v = getArray();
     
+    if (v == NULL || nx == 0 || ny == 0)
+      return;
+
     mean = 0;
     min = v[0][0];
     max = v[0][0];
@@ -210,7 +219,7 @@ ImageFile::statistics (double& min, double& max, double& mean, double& mode, dou
     }
     mean /= (nx * ny);
 
-    static const int nbin = 256;
+    static const int nbin = 1024;
     int hist[ nbin ] = {0};
     double spread = max - min;
     mode = 0;
@@ -235,8 +244,235 @@ ImageFile::statistics (double& min, double& max, double& mean, double& mode, dou
     }
 
     mode = (max_binindex * spread / (nbin - 1)) + min;
-      
-    median = 0.;
+
+    int nPixels = nx * ny;
+    slist<double> vecImage;
+    for (int ix = 0; ix < nx; ix++)
+      for (int iy = 0; iy < ny; iy++)
+       vecImage.push_front (v[ix][iy]);
+    vecImage.sort();
+    slist<double>::const_iterator iter = vecImage.begin();
+    for (int i = 0; i < (nPixels / 2) - 1; i++)
+      iter++; // Advance iterator to (nPixels / 2) - 1;
+
+    if (nPixels % 2) {  // Odd
+      iter++;
+      median = *iter;
+    } else                // Even
+      median = (*iter++ + *iter) / 2;
+}
+
+
+void
+ImageFile::getMinMax (double& min, double& max) const
+{
+    int nx = m_nx;
+    int ny = m_ny;
+    ImageFileArrayConst v = getArray();
+    
+    if (v == NULL || nx == 0 || ny == 0)
+      return;
+
+    min = v[0][0];
+    max = v[0][0];
+    for (int ix = 0; ix < nx; ix++) {
+      for (int iy = 0; iy < ny; iy++) {
+       if (v[ix][iy] > max)
+         max = v[ix][iy];
+       if (v[ix][iy] < min)
+         min = v[ix][iy];
+      }
+    }
+}
+
+void 
+ImageFile::writeImagePGM (const char *outfile, int nxcell, int nycell, double densmin, double densmax)
+{
+  FILE *fp;
+  int nx = m_nx;
+  int ny = m_ny;
+  ImageFileArray v = getArray();
+
+  unsigned char rowp [nx * nxcell];
+
+  if ((fp = fopen (outfile, "wb")) == NULL)
+     return;
+
+  fprintf(fp, "P5\n");
+  fprintf(fp, "%d %d\n", nx, ny);
+  fprintf(fp, "255\n");
+
+  for (int irow = ny - 1; irow >= 0; irow--) {
+    for (int icol = 0; icol < nx; icol++) {
+      int pos = icol * nxcell;
+      double dens = (v[icol][irow] - densmin) / (densmax - densmin);
+      dens = clamp (dens, 0., 1.);
+      for (int p = pos; p < pos + nxcell; p++) {
+       rowp[p] = static_cast<unsigned int> (dens * 255.);
+      }
+    }
+    for (int ir = 0; ir < nycell; ir++) {
+      for (int ic = 0; ic < nx * nxcell; ic++) 
+       fprintf(fp, "%c ", rowp[ic]);
+    }
+  }
+
+  fclose(fp);
+}
+
+void 
+ImageFile::writeImagePGMASCII (const char *outfile, int nxcell, int nycell, double densmin, double densmax)
+{
+  FILE *fp;
+  int nx = m_nx;
+  int ny = m_ny;
+  ImageFileArray v = getArray();
+
+  unsigned char rowp [nx * nxcell];
+  if (rowp == NULL)
+    return;
+
+  if ((fp = fopen (outfile, "wb")) == NULL)
+     return;
+
+  fprintf(fp, "P2\n");
+  fprintf(fp, "%d %d\n", nx, ny);
+  fprintf(fp, "255\n");
+
+  for (int irow = ny - 1; irow >= 0; irow--) {
+    for (int icol = 0; icol < nx; icol++) {
+      int pos = icol * nxcell;
+      double dens = (v[icol][irow] - densmin) / (densmax - densmin);
+      dens = clamp (dens, 0., 1.);
+      for (int p = pos; p < pos + nxcell; p++) {
+       rowp[p] = static_cast<unsigned int> (dens * 255.);
+      }
+    }
+    for (int ir = 0; ir < nycell; ir++) {
+      for (int ic = 0; ic < nx * nxcell; ic++) 
+       fprintf(fp, "%d ", rowp[ic]);
+      fprintf(fp, "\n");
+    }
+  }
+
+  fclose(fp);
 }
 
 
+#ifdef HAVE_PNG
+void 
+ImageFile::writeImagePNG (const char *outfile, int bitdepth, int nxcell, int nycell, double densmin, double densmax)
+{
+  FILE *fp;
+  png_structp png_ptr;
+  png_infop info_ptr;
+  double max_out_level = (1 << bitdepth) - 1;
+  int nx = m_nx;
+  int ny = m_ny;
+  ImageFileArray v = getArray();
+
+  unsigned char rowp [nx * nxcell * (bitdepth / 8)];
+
+  if ((fp = fopen (outfile, "wb")) == NULL)
+     return;
+
+  png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+  if (! png_ptr)
+    return;
+
+  info_ptr = png_create_info_struct(png_ptr);
+  if (! info_ptr) {
+    png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
+    fclose(fp);
+    return;
+  }
+
+  if (setjmp(png_ptr->jmpbuf)) {
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    fclose(fp);
+    return;
+  }
+
+  png_init_io(png_ptr, fp);
+
+  png_set_IHDR(png_ptr, info_ptr, nx * nxcell, ny * nycell, bitdepth, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT);
+
+  png_write_info(png_ptr, info_ptr);
+  for (int irow = ny - 1; irow >= 0; irow--) {
+    png_bytep row_pointer = rowp;
+    
+    for (int icol = 0; icol < nx; icol++) {
+      int pos = icol * nxcell;
+      double dens = (v[icol][irow] - densmin) / (densmax - densmin);
+      dens = clamp (dens, 0., 1.);
+      unsigned int outval = static_cast<unsigned int> (dens * max_out_level);
+
+      for (int p = pos; p < pos + nxcell; p++) {
+       if (bitdepth == 8)
+         rowp[p] = outval;
+       else {
+         int rowpos = p * 2;
+         rowp[rowpos] = (outval >> 8) & 0xFF;
+         rowp[rowpos+1] = (outval & 0xFF);
+       }
+      }
+    }
+    for (int ir = 0; ir < nycell; ir++)
+      png_write_rows (png_ptr, &row_pointer, 1);
+  }
+
+  png_write_end(png_ptr, info_ptr);
+  png_destroy_write_struct(&png_ptr, &info_ptr);
+
+  fclose(fp);
+}
+#endif
+
+#ifdef HAVE_GD
+#include "gd.h"
+static const int N_GRAYSCALE=256;
+
+void
+ImageFile::writeImageGIF (const char *outfile, int nxcell, int nycell, double densmin, double densmax)
+{
+  gdImagePtr gif;
+  FILE *out;
+  int gs_indices[N_GRAYSCALE];
+  int nx = m_nx;
+  int ny = m_ny;
+  ImageFileArray v = getArray();
+
+  unsigned char rowp [nx * nxcell];
+  if (rowp == NULL)
+    return;
+
+  gif = gdImageCreate(nx * nxcell, ny * nycell);
+  for (int i = 0; i < N_GRAYSCALE; i++)
+    gs_indices[i] = gdImageColorAllocate(gif, i, i, i);
+
+  int lastrow = ny * nycell - 1;
+  for (int irow = 0; irow < ny; irow++) {
+    int rpos = irow * nycell;
+    for (int ir = rpos; ir < rpos + nycell; ir++) {
+      for (int icol = 0; icol < nx; icol++) {
+       int cpos = icol * nxcell;
+       double dens = (v[icol][irow] - densmin) / (densmax - densmin);
+       dens = clamp(dens, 0., 1.);
+       for (int ic = cpos; ic < cpos + nxcell; ic++) {
+         rowp[ic] = (unsigned int) (dens * (double) (N_GRAYSCALE - 1));
+         gdImageSetPixel(gif, ic, lastrow - ir, gs_indices[rowp[ic]]);
+       }
+      }
+    }
+  }
+
+  if ((out = fopen(outfile,"w")) == NULL) {
+    sys_error(ERR_FATAL, "Error opening output file %s for writing", outfile);
+    return (1);
+  }
+  gdImageGif(gif,out);
+  fclose(out);
+  gdImageDestroy(gif);
+}
+#endif
+