Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

pgmio.cpp

Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00007  * Copyright (c) 2000-2006 Baylor College of Medicine
00008  *
00009  * This software is issued under a joint BSD/GNU license. You may use the
00010  * source code in this file under either license. However, note that the
00011  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00012  * so you are responsible for compliance with the licenses of these packages
00013  * if you opt to use BSD licensing. The warranty disclaimer below holds
00014  * in either instance.
00015  *
00016  * This complete copyright notice must be included in any revised version of the
00017  * source code. Additional authorship citations may be added, but existing
00018  * author citations must be preserved.
00019  *
00020  * This program is free software; you can redistribute it and/or modify
00021  * it under the terms of the GNU General Public License as published by
00022  * the Free Software Foundation; either version 2 of the License, or
00023  * (at your option) any later version.
00024  *
00025  * This program is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00028  * GNU General Public License for more details.
00029  *
00030  * You should have received a copy of the GNU General Public License
00031  * along with this program; if not, write to the Free Software
00032  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00033  *
00034  * */
00035 
00036 #include "pgmio.h"
00037 #include "geometry.h"
00038 #include "util.h"
00039 #include "portable_fileio.h"
00040 
00041 #ifdef _WIN32
00042         //MS Visual Studio.NET does not supply isnan()
00043         //they have _isnan() in <cfloat>
00044         #include <cfloat>
00045 #endif
00046 
00047 using namespace EMAN;
00048 
00049 const char *PgmIO::MAGIC_BINARY = "P5";
00050 const char *PgmIO::MAGIC_ASCII = "P2";
00051 
00052 PgmIO::PgmIO(const string & file, IOMode rw)
00053 :       filename(file), rw_mode(rw), pgm_file(0), is_big_endian(true),
00054         initialized(false), nx(0), ny(0), maxval(0), minval(0),
00055         file_offset(0), rendermin(0), rendermax(0)
00056 {}
00057 
00058 PgmIO::~PgmIO()
00059 {
00060         if (pgm_file) {
00061                 fclose(pgm_file);
00062                 pgm_file = 0;
00063         }
00064 }
00065 
00066 //anonymous namespace make this function local for this file
00067 namespace
00068 {
00069         int read_int_and_space(FILE * in)
00070         {
00071                 char buf[32];
00072                 int c = 0;
00073 
00074                 int i = 0;
00075                 while (!isspace(c = getc(in))) {
00076                         buf[i] = static_cast < char >(c);
00077                         i++;
00078                 }
00079 
00080                 return atoi(buf);
00081         }
00082 }
00083 
00084 void PgmIO::init()
00085 {
00086         ENTERFUNC;
00087 
00088         if (initialized) {
00089                 return;
00090         }
00091 
00092         initialized = true;
00093 
00094         bool is_new_file = false;
00095         pgm_file = sfopen(filename, rw_mode, &is_new_file, true);
00096 
00097         if (!is_new_file) {
00098                 const int bufsz = 1024;
00099                 char buf[bufsz];
00100 
00101                 buf[0] = static_cast < char >(getc(pgm_file));
00102                 buf[1] = static_cast < char >(getc(pgm_file));
00103                 buf[2] = '\0';
00104                 getc(pgm_file);
00105 
00106                 if (!is_valid(&buf)) {
00107                         throw ImageReadException(filename, "invalid PGM file");
00108                 }
00109 
00110                 char c = '\0';
00111 
00112                 while ((c = static_cast < char >(getc(pgm_file))) == '#') {
00113                         fgets(buf, bufsz, pgm_file);
00114                 }
00115                 ungetc(c, pgm_file);
00116 
00117                 nx = read_int_and_space(pgm_file);
00118                 ny = read_int_and_space(pgm_file);
00119                 maxval = read_int_and_space(pgm_file);
00120 
00121                 if (nx <= 0 || ny <= 0) {
00122                         throw ImageReadException(filename, "file size < 0");
00123                 }
00124 
00125                 file_offset = portable_ftell(pgm_file);
00126         }
00127         EXITFUNC;
00128 }
00129 
00130 bool PgmIO::is_valid(const void *first_block)
00131 {
00132         ENTERFUNC;
00133         bool result = false;
00134         if (first_block) {
00135                 result = Util::check_file_by_magic(first_block, MAGIC_BINARY);
00136         }
00137         EXITFUNC;
00138         return result;
00139 }
00140 
00141 int PgmIO::read_header(Dict & dict, int image_index, const Region * area, bool)
00142 {
00143         ENTERFUNC;
00144 
00145         //single image format, index can only be zero
00146         if(image_index == -1) {
00147                 image_index = 0;
00148         }
00149 
00150         if(image_index != 0) {
00151                 throw ImageReadException(filename, "no stack allowed for MRC image. For take 2D slice out of 3D image, read the 3D image first, then use get_clip().");
00152         }
00153 
00154         init();
00155 
00156         check_read_access(image_index);
00157         check_region(area, IntSize(nx, ny));
00158         int xlen = 0, ylen = 0;
00159         EMUtil::get_region_dims(area, nx, &xlen, ny, &ylen);
00160 
00161         dict["nx"] = xlen;
00162         dict["ny"] = ylen;
00163         dict["nz"] = 1;
00164 
00165         dict["PGM.max_gray"] = maxval;
00166         dict["PGM.min_gray"] = minval;
00167 
00168         EXITFUNC;
00169         return 0;
00170 }
00171 
00172 int PgmIO::write_header(const Dict & dict, int image_index, const Region*,
00173                                                 EMUtil::EMDataType, bool)
00174 {
00175         ENTERFUNC;
00176         int err = 0;
00177 
00178         //single image format, index can only be zero
00179         if(image_index == -1) {
00180                 image_index = 0;
00181         }
00182         if(image_index != 0) {
00183                 throw ImageWriteException(filename, "PGM file does not support stack.");
00184         }
00185         check_write_access(rw_mode, image_index);
00186 
00187         int nz = dict["nz"];
00188         if ((int)nz != 1) {
00189                 LOGERR("Cannot write 3D image as PGM. Your image nz = %d", nz);
00190                 err = 1;
00191                 throw ImageWriteException("N/A", "Cannot write 3D image as PGM.");
00192         }
00193         else {
00194                 nx = dict["nx"];
00195                 ny = dict["ny"];
00196 
00197                 if(dict.has_key("min_grey")) minval = dict["min_gray"];
00198                 if(dict.has_key("max_grey")) maxval = dict["max_gray"];
00199 
00200                 //if we didn't get any good values from attributes, assign to 255 by default
00201 #ifdef _WIN32
00202                 if (maxval<=minval || _isnan(minval) || _isnan(maxval)) {
00203 #else
00204                         if (maxval<=minval || std::isnan(minval) || std::isnan(maxval)) {
00205 #endif  //_WIN32
00206                         maxval = 255;
00207                 }
00208 
00209                 if(dict.has_key("render_min")) rendermin=(float)dict["render_min"];     // float value representing black in the output
00210                 if(dict.has_key("render_max")) rendermax=(float)dict["render_max"];     // float value representign white in the output
00211 
00212                 fprintf(pgm_file, "%s\n%d %d\n%d\n", MAGIC_BINARY, nx, ny, maxval);
00213         }
00214 
00215         EXITFUNC;
00216         return err;
00217 }
00218 
00219 int PgmIO::read_data(float *data, int image_index, const Region * area, bool)
00220 {
00221         ENTERFUNC;
00222 
00223         //single image format, index can only be zero
00224         image_index = 0;
00225         check_read_access(image_index, data);
00226         check_region(area, IntSize(nx, ny));
00227 
00228         portable_fseek(pgm_file, file_offset, SEEK_SET);
00229 
00230         unsigned char *cdata = (unsigned char *) (data);
00231         size_t mode_size = sizeof(unsigned char);
00232 
00233         EMUtil::process_region_io(cdata, pgm_file, READ_ONLY, image_index,
00234                                                           mode_size, nx, ny, 1, area, true);
00235 
00236         int xlen = 0, ylen = 0;
00237         EMUtil::get_region_dims(area, nx, &xlen, ny, &ylen);
00238 
00239         for (int k = xlen * ylen - 1; k >= 0; k--) {
00240                 data[k] = static_cast < float >(cdata[k]);
00241         }
00242 
00243         EXITFUNC;
00244         return 0;
00245 }
00246 
00247 int PgmIO::write_data(float *data, int image_index, const Region* area,
00248                                           EMUtil::EMDataType, bool)
00249 {
00250         ENTERFUNC;
00251 
00252         //single image format, index can only be zero
00253         image_index = 0;
00254 /*      if(area && (area->size[0]!=nx || area->size[1]!=ny)) {
00255                 throw ImageWriteException("N/A", "No region writing for PGM images");
00256         }
00257 */
00258 
00259         check_write_access(rw_mode, image_index, 1, data);
00260         check_region(area, IntSize(nx, ny));
00261 
00262         // If we didn't get any parameters in 'render_min' or 'render_max', we need to find some good ones
00263         EMUtil::getRenderMinMax(data, nx, ny, rendermin, rendermax);
00264 
00265         unsigned char *cdata=(unsigned char *)malloc(nx*ny);    //cdata is the normalized data
00266 
00267         int old_add = 0;
00268         int new_add = 0;
00269         for( int j=0; j<ny; ++j ) {
00270                 for( int i=0; i<nx; ++i) {
00271                         old_add = j*nx+i;
00272                         new_add = (ny-1-j)*nx + i;
00273                         if( data[old_add]<rendermin ) {
00274                                 cdata[new_add] = 0;
00275                         }
00276                         else if( data[old_add]>rendermax )
00277                         {
00278                                 cdata[new_add] = 255;
00279                         }
00280                         else {
00281                                 cdata[new_add] = (unsigned char)((data[old_add]-rendermin)/(rendermax-rendermin)*256.0);
00282                         }
00283                 }
00284         }
00285 
00286         size_t mode_size = sizeof(unsigned char);
00287         //fwrite(cdata, nx, ny, pgm_file);
00288         EMUtil::process_region_io(cdata, pgm_file, WRITE_ONLY, image_index,
00289                                                           mode_size, nx, ny, 1, area);
00290 
00291         free(cdata);
00292         EXITFUNC;
00293         return 0;
00294 }
00295 
00296 void PgmIO::flush()
00297 {
00298         fflush(pgm_file);
00299 }
00300 
00301 
00302 bool PgmIO::is_complex_mode()
00303 {
00304         return false;
00305 }
00306 
00307 bool PgmIO::is_image_big_endian()
00308 {
00309         init();
00310         return is_big_endian;
00311 }
00312 

Generated on Tue Jun 11 13:46:16 2013 for EMAN2 by  doxygen 1.3.9.1