/** Imagic Writer * @ingroup Imagic */ int ImageBase::writeIMAGIC(size_t select_img, int mode, const String &bitDepth, CastWriteMode castMode) { #undef DEBUG //#define DEBUG #ifdef DEBUG printf("DEBUG writeIMAGIC: Reading Imagic file\n"); #endif IMAGIChead header; // Cast T to datatype without convert data DataType wDType, myTypeID = myT(); if (bitDepth == "") { switch(myTypeID) { case DT_Double: case DT_Float: case DT_Int: case DT_UInt: wDType = DT_Float; strncpy(header.type,"REAL", sizeof(header.type)); break; case DT_UShort: castMode = CW_CONVERT; /* no break */ case DT_Short: wDType = DT_Short; strncpy(header.type,"INTG", sizeof(header.type)); break; case DT_SChar: castMode = CW_CONVERT; /* no break */ case DT_UChar: wDType = DT_UChar; strncpy(header.type,"PACK", sizeof(header.type)); break; case DT_CFloat: case DT_CDouble: wDType = DT_CFloat; strncpy(header.type,"COMP", sizeof(header.type)); break; default: wDType = DT_Unknown; REPORT_ERROR(ERR_TYPE_INCORRECT, "ERROR: Unsupported data type by IMAGIC format."); } } else //Convert to other data type { // Default Value wDType = (bitDepth == "default") ? DT_Float : datatypeRAW(bitDepth); switch (wDType) { case DT_UChar: strncpy(header.type,"PACK", sizeof(header.type)); break; case DT_Short: strncpy(header.type,"INTG", sizeof(header.type)); break; case DT_Float: (strncpy)(header.type,"REAL", sizeof(header.type)); break; case DT_CFloat: strncpy(header.type,"COMP", sizeof(header.type)); break; default: REPORT_ERROR(ERR_TYPE_INCORRECT,"ERROR: incorrect IMAGIC bits depth value."); } } if (mmapOnWrite) { MDMainHeader.setValue(MDL_DATATYPE,(int) wDType); if (!checkMmapT(wDType)) { if (dataMode < DATA && castMode == CW_CAST) // This means ImageGeneric wants to know which DataType must use in mapFile2Write return 0; else //Mapping is an extra. When not available, go on and do not report an error. { /* In this case we cannot map the file because required and feasible datatypes are * not compatible. Then we denote to MapFile2Write the same incoming datatype to * keep using this Image object as usual, without mapping on write. */ mmapOnWrite = false; dataMode = DATA; MDMainHeader.setValue(MDL_DATATYPE,(int) myTypeID); // In case Image size great then, at least, map the multidimarray if (mdaBase->nzyxdim*gettypesize(myTypeID) > tiff_map_min_size) mdaBase->setMmap(true); // Allocate memory for image data (Assume xdim, ydim, zdim and ndim are already set //if memory already allocated use it (no resize allowed) mdaBase->coreAllocateReuse(); return 0; } } else dataMode = DATA; } size_t Xdim, Ydim, Zdim, Ndim; getDimensions(Xdim, Ydim, Zdim, Ndim); if (Zdim > 1) REPORT_ERROR(ERR_MULTIDIM_DIM, "writeIMAGIC: Imagic format does not support volumes."); size_t datasize, datasize_n; datasize_n = (size_t)Xdim*Ydim*Zdim; datasize = datasize_n * gettypesize(wDType); // fill in the file header header.nhfr = 1; header.npix2 = Xdim*Ydim; header.npixel = header.npix2; header.iylp = Xdim; header.ixlp = Ydim; time_t timer; time ( &timer ); tm* t = localtime(&timer); header.ndate = t->tm_mday; header.nmonth = t->tm_mon + 1; header.nyear = t->tm_year; header.nhour = t->tm_hour; header.nminut = t->tm_min; header.nsec = t->tm_sec; double aux; if (!MDMainHeader.empty()) { #define SET_MAIN_HEADER_VALUE(field, label) MDMainHeader.getValueOrDefault(label, aux, 0.); header.field = (float)aux SET_MAIN_HEADER_VALUE(densmin, MDL_MIN); SET_MAIN_HEADER_VALUE(densmax, MDL_MAX); SET_MAIN_HEADER_VALUE(avdens, MDL_AVG); SET_MAIN_HEADER_VALUE(sigma, MDL_STDDEV); header.varian = header.sigma*header.sigma; } memcpy(header.lastpr, "Xmipp", 5); memcpy(header.name, filename.c_str(), 80); size_t imgStart = IMG_INDEX(select_img); header.ifn = replaceNsize - 1 ; header.imn = 1; if ( mode == WRITE_APPEND ) { imgStart = replaceNsize; header.ifn = replaceNsize + Ndim - 1 ; } else if( mode == WRITE_REPLACE && imgStart + Ndim > replaceNsize) header.ifn = imgStart + Ndim - 1; else if (Ndim > replaceNsize) header.ifn = Ndim - 1; /* * BLOCK HEADER IF NEEDED */ FileLock flockHead, flockImg; flockHead.lock(fhed); flockImg.lock(fimg); if (replaceNsize == 0) // Header written first time { if ( swapWrite ) { IMAGIChead headTemp = header; swapPage((char *) &headTemp, IMAGICSIZE - 916, DT_Float); fwrite( &headTemp, IMAGICSIZE, 1, fhed ); } fwrite( &header, IMAGICSIZE, 1, fhed ); } else if( header.ifn + 1 > (int)replaceNsize && imgStart > 0 ) // Update number of images when needed { fseek( fhed, sizeof(int), SEEK_SET); if ( swapWrite ) { int ifnswp = header.ifn; swapPage((char *) &ifnswp, SIZEOF_INT, DT_Int); fwrite(&(ifnswp),SIZEOF_INT,1,fhed); } else fwrite(&(header.ifn),SIZEOF_INT,1,fhed); } // Jump to the selected imgStart position fseek(fimg, datasize * imgStart, SEEK_SET); fseek(fhed, IMAGICSIZE * imgStart, SEEK_SET); std::vector<MDRow>::iterator it = MD.begin(); for (size_t i = 0; i < Ndim; ++i, ++it) { header.iyold=header.ixold=0; header.euler_alpha=header.euler_beta=header.euler_gamma=0.; // Write the individual image header if (it != MD.end() && (dataMode == _HEADER_ALL || dataMode == _DATA_ALL)) { #define SET_HEADER_VALUEInt(field, label) it->getValueOrDefault((label), (aux), 0); header.field = -(int)(aux) #define SET_HEADER_VALUEDouble(field, label) it->getValueOrDefault((label), (aux), 0.); header.field = -(float)(aux) SET_HEADER_VALUEInt(ixold, MDL_SHIFT_X); SET_HEADER_VALUEInt(iyold, MDL_SHIFT_Y); SET_HEADER_VALUEDouble(euler_alpha, MDL_ANGLE_ROT); SET_HEADER_VALUEDouble(euler_beta, MDL_ANGLE_TILT); SET_HEADER_VALUEDouble(euler_gamma, MDL_ANGLE_PSI); } // Update index number of image header.imn = imgStart + i + 1; if ( swapWrite ) swapPage((char *) &header, IMAGICSIZE - 916, DT_Float); fwrite( &header, IMAGICSIZE, 1, fhed ); if (dataMode >= DATA) { if (mmapOnWrite && Ndim == 1) // Can map one image at a time only { mappedOffset = ftell(fimg); mappedSize = mappedOffset + datasize; fseek(fimg, datasize-1, SEEK_CUR); fputc(0, fimg); } else writeData(fimg, i*datasize_n, wDType, datasize_n, castMode); } else fseek(fimg, datasize, SEEK_CUR); } //Unlock flockHead.unlock(); flockImg.unlock(); if (mmapOnWrite) mmapFile(); return(0); }
int ImageBase::readEM(size_t select_img, bool isStack) { // EM File formats does not support stacks if (select_img > FIRST_IMAGE & !isStack) REPORT_ERROR(ERR_ARG_INCORRECT, "readEM: EM file format does not support stacks."); EMHead header; if ( fread( &header, EMHEADERSIZE, 1, fimg ) != 1 ) REPORT_ERROR(ERR_IO_NOREAD, formatString("rwEM: cannot read EM main header from file %s" ". Error message: %s", filename.c_str() ,strerror(errno))); // endian: If machine is SGI, OS-9 or MAC: Big Endian, otherwise Litle Endian // Check Machine endianess bool isLE = IsLittleEndian(); if (header.machine == 0 || header.machine == 3 || header.machine == 5) swap = isLE; else if (header.machine == 1 || header.machine == 2 || header.machine == 4 || header.machine == 6) swap = !isLE; else REPORT_ERROR(ERR_IMG_UNKNOWN, "rwEM: Unknown source machine to determine Endianness"); if (swap) swapPage((char *) &header, EMHEADERSIZE - 256, DT_UInt); // EMHEADERSIZE - 256 is to exclude userdata from swapping // Setting image dimensions ArrayDim aDim; if (isStack) { if ( select_img > header.zdim ) REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS, formatString("readEM: %s Image number %lu exceeds stack size %lu", this->filename.c_str(), select_img, header.zdim)); aDim.ndim = (select_img > ALL_IMAGES)? 1 : header.zdim; aDim.zdim = 1; } else { aDim.ndim = 1; aDim.zdim = header.zdim; } aDim.xdim = header.xdim; aDim.ydim= header.ydim; replaceNsize = aDim.ndim; setDimensions(aDim); DataType datatype; switch (header.datatype) { case 1: datatype = DT_SChar; break; case 2: datatype = DT_Short; break; case 4: datatype = DT_Int; break; case 3: case 5: datatype = DT_Float; break; case 8: datatype = DT_CFloat; break; case 9: datatype = DT_CDouble; break; default: REPORT_ERROR(ERR_ARG_INCORRECT, formatString("readEM: Unknown datatype value: %c", header.datatype)); break; } MDMainHeader.setValue(MDL_DATATYPE,(int)datatype); offset = EMHEADERSIZE; // If only header is read: return if (dataMode==HEADER || (dataMode == _HEADER_ALL && aDim.ndim > 1)) // Stop reading if not necessary return 0; size_t imgStart = IMG_INDEX(select_img); size_t imgEnd = (select_img != ALL_IMAGES) ? imgStart + 1 : aDim.ndim; MD.clear(); MD.resize(imgEnd - imgStart,MDL::emptyHeader); /* As MRC does not support stacks, we use the geometry stored in the header for any image when we simulate the file is a stack.*/ if (dataMode == _HEADER_ALL || dataMode == _DATA_ALL) { for ( size_t i = 0; i < imgEnd - imgStart; ++i ) { MD[i].setValue(MDL_SHIFT_X, 0.); MD[i].setValue(MDL_SHIFT_Y, 0.); MD[i].setValue(MDL_SHIFT_Z, 0.); MD[i].setValue(MDL_ORIGIN_X, 0.); MD[i].setValue(MDL_ORIGIN_Y, 0.); MD[i].setValue(MDL_ORIGIN_Z, 0.); } } if ( dataMode < DATA ) // Don't read the individual header and the data if not necessary return 0; readData(fimg, select_img, datatype, 0); return(0); }
/** Imagic reader * @ingroup Imagic */ int ImageBase::readIMAGIC(size_t select_img) { #undef DEBUG //#define DEBUG #ifdef DEBUG printf("DEBUG readIMAGIC: Reading Imagic file\n"); #endif IMAGIChead* header = new IMAGIChead; if ( fread( header, IMAGICSIZE, 1, fhed ) < 1 ) REPORT_ERROR(ERR_IO_NOREAD,(String)"readIMAGIC: header file of " + filename + " cannot be read"); // Determine byte order and swap bytes if from little-endian machine if ( (swap = (( abs(header->nyear) > SWAPTRIG ) || ( header->ixlp > SWAPTRIG ))) ) swapPage((char *) header, IMAGICSIZE - 916, DT_Float); // IMAGICSIZE - 916 is to exclude labels from swapping DataType datatype=DT_Float; if ( strstr(header->type,"PACK") ) datatype = DT_UChar; else if ( strstr(header->type,"INTG") ) datatype = DT_Short; else if ( strstr(header->type,"REAL") ) datatype = DT_Float; else if ( strstr(header->type,"RECO") ) { datatype = DT_CFloat; // Complex data transform = NoTransform; } else if ( strstr(header->type,"COMP") ) { datatype = DT_CFloat; // Complex transform data transform = Centered; } // Set min-max values and other statistical values if ( header->sigma == 0 && header->varian != 0 ) header->sigma = sqrt(header->varian); if ( header->densmax == 0 && header->densmin == 0 && header->sigma != 0 ) { header->densmin = header->avdens - header->sigma; header->densmax = header->avdens + header->sigma; } offset = 0; // separate header file MDMainHeader.setValue(MDL_MIN,(double)header->densmin); MDMainHeader.setValue(MDL_MAX,(double)header->densmax); MDMainHeader.setValue(MDL_AVG,(double)header->avdens); MDMainHeader.setValue(MDL_STDDEV,(double)header->sigma); MDMainHeader.setValue(MDL_SAMPLINGRATE_X,(double)1.); MDMainHeader.setValue(MDL_SAMPLINGRATE_Y,(double)1.); MDMainHeader.setValue(MDL_SAMPLINGRATE_Z,(double)1.); MDMainHeader.setValue(MDL_DATATYPE,(int)datatype); int _xDim,_yDim,_zDim; size_t _nDim; _xDim = (int) header->iylp; _yDim = (int) header->ixlp; _zDim = (int) 1; _nDim = (size_t) header->ifn + 1 ; if ( select_img > _nDim ) REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS, formatString("readImagic: Image number %lu exceeds stack size %lu", select_img, _nDim)); if( select_img != ALL_IMAGES ) _nDim = 1; replaceNsize = _nDim; setDimensions(_xDim, _yDim, _zDim, _nDim ); if (dataMode == HEADER || (dataMode == _HEADER_ALL && _nDim > 1)) // Stop reading if not necessary { delete header; return 0; } // Get the header information fseek( fhed, IMG_INDEX(select_img) * IMAGICSIZE, SEEK_SET ); MD.clear(); MD.resize(_nDim,MDL::emptyHeader); double daux=1.; for ( size_t i = 0; i < _nDim; ++i ) { if ( fread( header, IMAGICSIZE, 1, fhed ) < 1 ) return(-2); { if ( swap ) swapPage((char *) header, IMAGICSIZE - 916, DT_Float); if (dataMode == _HEADER_ALL || dataMode == _DATA_ALL) { MD[i].setValue(MDL_SHIFT_X, (double)-1. * header->ixold); MD[i].setValue(MDL_SHIFT_Y, (double)-1. * header->iyold); MD[i].setValue(MDL_SHIFT_Z, 0.); MD[i].setValue(MDL_ANGLE_ROT, (double)-1. * header->euler_alpha); MD[i].setValue(MDL_ANGLE_TILT,(double)-1. * header->euler_beta); MD[i].setValue(MDL_ANGLE_PSI, (double)-1. * header->euler_gamma); MD[i].setValue(MDL_WEIGHT, 1.); MD[i].setValue(MDL_SCALE, daux); } } } delete header; if (dataMode < DATA) // Don't read the individual header and the data if not necessary return 0; size_t pad = 0; readData(fimg, select_img, datatype, pad ); return(0); }