EMAN2
df3io.cpp
Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Grant Tang, 08/06/2010 (gtang@bcm.edu)
00007  * Copyright (c) 2000-2010 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 <algorithm>
00037 #include <climits>
00038 
00039 #include "df3io.h"
00040 #include "portable_fileio.h"
00041 
00042 using namespace EMAN;
00043 
00044 Df3IO::Df3IO(const string & df3_filename, IOMode rw)
00045 :       filename(df3_filename), rw_mode(rw), df3file(0),
00046         initialized(false), is_new_file(false)
00047 {
00048 }
00049 
00050 Df3IO::~Df3IO()
00051 {
00052         if (df3file) {
00053                 fclose(df3file);
00054                 df3file = 0;
00055         }
00056 }
00057 
00058 void Df3IO::init()
00059 {
00060         ENTERFUNC;
00061         if (initialized) {
00062                 return;
00063         }
00064 
00065         initialized = true;
00066         df3file = sfopen(filename, rw_mode, &is_new_file);
00067 
00068         EXITFUNC;
00069 }
00070 
00071 // header is 3 MSB unsigned shorts (nx,ny,nz) in big-endian
00072 int Df3IO::read_header(Dict & dict, int, const Region *, bool )
00073 {
00074         ENTERFUNC;
00075         init();
00076 
00077         if (!is_new_file) {
00078                 if (fread(&nx, sizeof(unsigned short), 1, df3file) != 1) {
00079                         throw ImageReadException(filename, "DF3 header");
00080                 }
00081 
00082                 fread(&ny, sizeof(unsigned short), 1, df3file);
00083                 fread(&nz, sizeof(unsigned short), 1, df3file);
00084 
00085                 if(!ByteOrder::is_host_big_endian()) {
00086                         ByteOrder::swap_bytes(&nx);
00087                         ByteOrder::swap_bytes(&ny);
00088                         ByteOrder::swap_bytes(&nz);
00089                 }
00090 
00091                 dict["nx"] = (int)nx;
00092                 dict["ny"] = (int)ny;
00093                 dict["nz"] = (int)nz;
00094         }
00095 
00096         EXITFUNC;
00097         return 0;
00098 }
00099 
00100 int Df3IO::write_header(const Dict & dict, int, const Region*, EMUtil::EMDataType, bool)
00101 {
00102         ENTERFUNC;
00103         init();
00104 
00105         nx = (unsigned short)((int)dict["nx"]);
00106         ny = (unsigned short)((int)dict["ny"]);
00107         nz = (unsigned short)((int)dict["nz"]);
00108 
00109         portable_fseek(df3file, 0, SEEK_SET);
00110 
00111         unsigned short df3header[3];
00112         df3header[0] = nx;
00113         df3header[1] = ny;
00114         df3header[2] = nz;
00115         ByteOrder::become_big_endian(df3header, 3);
00116 
00117         if(fwrite(df3header, sizeof(unsigned short), 3, df3file) != 3) {
00118                 throw ImageWriteException(filename, "DF3 header");
00119         }
00120 
00121         EXITFUNC;
00122         return 0;
00123 }
00124 
00125 int Df3IO::read_data(float *rdata, int, const Region *, bool)
00126 {
00127         ENTERFUNC;
00128 
00129         size_t image_size = (size_t)nx*ny*nz;
00130 
00131         // obtain file size:
00132         portable_fseek (df3file , 0 , SEEK_END);
00133         size_t fsize = ftell (df3file);
00134         rewind (df3file);
00135 
00136         unsigned int * uidata = 0;
00137         unsigned short * usdata = 0;
00138         unsigned char * ucdata = 0;
00139 
00140         portable_fseek(df3file, sizeof(unsigned short)*3, SEEK_SET);    //skip header
00141         switch(fsize/image_size) {
00142         case sizeof(unsigned int):
00143                 uidata = new unsigned int[image_size];
00144                 fread(uidata, sizeof(unsigned int), image_size, df3file);
00145                 become_host_endian < unsigned int >(uidata, image_size);
00146                 std::copy(uidata, uidata+image_size, rdata);
00147                 if(uidata) {delete [] uidata; uidata=0;}
00148                 break;
00149         case sizeof(unsigned short):
00150                 usdata = new unsigned short[image_size];
00151                 fread(usdata, sizeof(unsigned short), image_size, df3file);
00152                 become_host_endian < unsigned short >(usdata, image_size);
00153                 std::copy(usdata, usdata+image_size, rdata);
00154                 if(usdata) {delete [] usdata; usdata=0;}
00155                 break;
00156         case sizeof(unsigned char):
00157                 ucdata = new unsigned char[image_size];
00158                 fread(ucdata, sizeof(unsigned char), image_size, df3file);
00159                 std::copy(ucdata, ucdata+image_size, rdata);
00160                 if(ucdata) {delete [] ucdata; ucdata=0;}
00161                 break;
00162         default:
00163                 throw ImageReadException(filename, "DF3 does not support this kind of data type.");
00164         }
00165 
00166         EXITFUNC;
00167         return 0;
00168 }
00169 
00170 int Df3IO::write_data(float *data, int, const Region*,
00171                                           EMUtil::EMDataType dt, bool)
00172 {
00173         ENTERFUNC;
00174 
00175         size_t img_size = (size_t)nx*ny*nz;
00176         unsigned int * uidata = 0;
00177         unsigned short * usdata = 0;
00178         unsigned char * ucdata = 0;
00179         float rendermin = 0.0f;
00180         float rendermax = 0.0f;
00181         EMUtil::getRenderMinMax(data, nx, ny, rendermin, rendermax, nz);
00182 
00183         switch(dt) {
00184         case EMUtil::EM_UINT:
00185                 uidata = new unsigned int[img_size];
00186                 for (size_t i = 0; i < img_size; ++i) {
00187                         if(data[i] <= rendermin) {
00188                                 uidata[i] = 0;
00189                         }
00190                         else if(data[i] >= rendermax) {
00191                                 uidata[i] = UINT_MAX;
00192                         }
00193                         else {
00194                                 uidata[i]=(unsigned int)((data[i]-rendermin)/(rendermax-rendermin)*UINT_MAX);
00195                         }
00196                 }
00197                 ByteOrder::become_big_endian(uidata, img_size);
00198                 if(fwrite(uidata, sizeof(unsigned int), img_size, df3file) != img_size) {
00199                         throw ImageWriteException(filename, "DF3 unsigned int data");
00200                 }
00201                 if(uidata) {delete [] uidata; uidata=0;}
00202                 break;
00203         case EMUtil::EM_USHORT:
00204                 usdata = new unsigned short[img_size];
00205                 for (size_t i = 0; i < img_size; ++i) {
00206                         if(data[i] <= rendermin) {
00207                                 usdata[i] = 0;
00208                         }
00209                         else if(data[i] >= rendermax) {
00210                                 usdata[i] = USHRT_MAX;
00211                         }
00212                         else {
00213                                 usdata[i]=(unsigned short)((data[i]-rendermin)/(rendermax-rendermin)*USHRT_MAX);
00214                         }
00215                 }
00216                 ByteOrder::become_big_endian(usdata, img_size);
00217                 if(fwrite(usdata, sizeof(unsigned short), img_size, df3file) != img_size) {
00218                         throw ImageWriteException(filename, "DF3 unsigned short data");
00219                 }
00220                 if(usdata) {delete [] usdata; usdata=0;}
00221                 break;
00222         case EMUtil::EM_UCHAR:
00223                 ucdata = new unsigned char[img_size];
00224                 for (size_t i = 0; i < img_size; ++i) {
00225                         if(data[i] <= rendermin) {
00226                                 ucdata[i] = 0;
00227                         }
00228                         else if(data[i] >= rendermax){
00229                                 ucdata[i] = UCHAR_MAX;
00230                         }
00231                         else {
00232                                 ucdata[i]=(unsigned char)((data[i]-rendermin)/(rendermax-rendermin)*UCHAR_MAX);
00233                         }
00234                 }
00235                 if(fwrite(ucdata, sizeof(unsigned char), img_size, df3file) != img_size) {
00236                         throw ImageWriteException(filename, "DF3 unsigned char data");
00237                 }
00238                 if(ucdata) {delete [] ucdata; ucdata=0;}
00239                 break;
00240         default:
00241                 throw ImageWriteException(filename,"DF3 does not support this data format");
00242         }
00243 
00244         EXITFUNC;
00245         return 0;
00246 }
00247 
00248 void Df3IO::flush()
00249 {
00250         fflush(df3file);
00251 }
00252 
00253 bool Df3IO::is_image_big_endian()
00254 {
00255         return true;    //DF3 file is always big endian
00256 }
00257 
00258 bool Df3IO::is_complex_mode()
00259 {
00260         return false;   //DF3 only support real image
00261 }
00262 
00263 bool Df3IO::is_valid(const void *first_block, off_t)
00264 {
00265         ENTERFUNC;
00266 
00267         if (!first_block) {
00268                 return false;
00269         }
00270 
00271         const unsigned short *data = static_cast < const unsigned short *>(first_block);
00272         unsigned short nx = data[0];
00273         unsigned short ny = data[1];
00274         unsigned short nz = data[2];
00275 
00276         if(ByteOrder::is_data_big_endian(&nx) && ByteOrder::is_data_big_endian(&ny) && ByteOrder::is_data_big_endian(&nz)) {
00277                 return true;
00278         }
00279 
00280         EXITFUNC;
00281         return false;
00282 }