FFHeaderI & FFHeaderI::operator = (FFHeaderI const & ffh) { if (&ffh != this) { if (data) free(data); if (filename) delete[] filename; filename = 0; data = 0; length = ffh.length; if (ffh.filename) { filename = new char [1+strlen(ffh.filename)]; strcpy(filename,ffh.filename); } if (ffh.data) { data = malloc(length); memcpy(data,ffh.data,length); } ptrdiff_t offset = (size_t)data - (size_t)ffh.data; for (int i=0; i<FFHI_HASHTABLESIZE; ++i) { for (CLIF<FFDataI> i_file(&ffh.files[i]); !i_file.done(); i_file.next()) { files[i].add_entry(FFDataI(i_file(),offset)); } } } return *this; }
FFHeaderI::FFHeaderI(FFHeaderI const & ffh) : filename(0) , data(0) , length(ffh.length) ,should_be_kept(ffh.should_be_kept) { if (ffh.filename) { filename = new char [1+strlen(ffh.filename)]; strcpy(filename,ffh.filename); } if (ffh.data) { data = malloc(length); memcpy(data,ffh.data,length); } ptrdiff_t offset = (size_t)data - (size_t)ffh.data; for (int i=0; i<FFHI_HASHTABLESIZE; ++i) { for (CLIF<FFDataI> i_file(&ffh.files[i]); !i_file.done(); i_file.next()) { files[i].add_entry(FFDataI(i_file(),offset)); } } }
void const * FFHeaderI::FindFile(char const * name, size_t * lengthP) const { for (CLIF<FFDataI> i_file(&files[HashFunction(name)]); !i_file.done(); i_file.next()) { if (i_file()==name) { if (lengthP) *lengthP = i_file().GetLength(); return i_file().GetDataPointer(); } } return 0; }
CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage ) { MSGDataset *poGDS = (MSGDataset *) poDS; int iBytesPerPixel = 1; if (eDataType == GDT_UInt16) iBytesPerPixel = 2; else if (eDataType == GDT_Float32) iBytesPerPixel = 4; /* -------------------------------------------------------------------- */ /* Calculate the correct input file name based on nBlockYOff */ /* -------------------------------------------------------------------- */ int strip_number; int iChannel = poGDS->command.iChannel(1 + ((nBand - 1) % poGDS->command.iNrChannels())); if (fScanNorth) strip_number = nBlockYOff + 1; else strip_number = poGDS->command.iNrStrips(iChannel) - nBlockYOff; std::string strip_input_file = poGDS->command.sFileName(iSatellite, nBand, strip_number); /* -------------------------------------------------------------------- */ /* Open the input file */ /* -------------------------------------------------------------------- */ if (access(strip_input_file.c_str(), 0) == 0) // does it exist? { std::ifstream i_file (strip_input_file.c_str(), std::ios::in|std::ios::binary); if (i_file.good()) { XRITHeaderParser xhp (i_file); if (xhp.isValid()) { std::vector <short> QualityInfo; unsigned short chunck_height = xhp.nrRows(); unsigned short chunck_bpp = xhp.nrBitsPerPixel(); unsigned short chunck_width = xhp.nrColumns(); unsigned __int8 NR = (unsigned __int8)chunck_bpp; unsigned int nb_ibytes = xhp.dataSize(); int iShift = 0; bool fSplitStrip = false; // in the split strip the "shift" only happens before the split "row" int iSplitRow = 0; if (iChannel == 12) { iSplitRow = iSplitLine % xhp.nrRows(); int iSplitBlock = iSplitLine / xhp.nrRows(); fSplitStrip = (nBlockYOff == iSplitBlock); // in the split strip the "shift" only happens before the split "row" // When iLowerShift > 0, the lower HRV image is shifted to the right // When iLowerShift < 0, the lower HRV image is shifted to the left // The available raster may be wider than needed, so that time series don't fall outside the raster. if (nBlockYOff <= iSplitBlock) iShift = -iLowerShift; // iShift < 0 means upper image moves to the left // iShift > 0 means upper image moves to the right } std::auto_ptr< unsigned char > ibuf( new unsigned char[nb_ibytes]); if (ibuf.get() == 0) { CPLError( CE_Failure, CPLE_AppDefined, "Not enough memory to perform wavelet decompression\n"); return CE_Failure; } i_file.read( (char *)(ibuf.get()), nb_ibytes); Util::CDataFieldCompressedImage img_compressed(ibuf.release(), nb_ibytes*8, (unsigned char)chunck_bpp, chunck_width, chunck_height ); Util::CDataFieldUncompressedImage img_uncompressed; //**************************************************** //*** Here comes the wavelets decompression routine COMP::DecompressWT(img_compressed, NR, img_uncompressed, QualityInfo); //**************************************************** // convert: // Depth: // 8 bits -> 8 bits // 10 bits -> 16 bits (img_uncompressed contains the 10 bits data in packed form) // Geometry: // chunck_width x chunck_height to nBlockXSize x nBlockYSize // cases: // combination of the following: // - scan direction can be north or south // - eDataType can be GDT_Byte, GDT_UInt16 or GDT_Float32 // - nBlockXSize == chunck_width or nBlockXSize > chunck_width // - when nBlockXSize > chunck_width, fSplitStrip can be true or false // we won't distinguish the following cases: // - NR can be == 8 or != 8 // - when nBlockXSize > chunck_width, iShift iMinCOff-iMaxCOff <= iShift <= 0 int nBlockSize = nBlockXSize * nBlockYSize; int y = chunck_width * chunck_height; int iStep = -1; if (fScanNorth) // image is the other way around { y = -1; // See how y is used below: += happens first, the result is used in the [] iStep = 1; } COMP::CImage cimg (img_uncompressed); // unpack if (eDataType == GDT_Byte) { if (nBlockXSize == chunck_width) // optimized version { if (poGDS->command.cDataConversion == 'B') { for( int i = 0; i < nBlockSize; ++i ) ((GByte *)pImage)[i] = cimg.Get()[y+=iStep] / 4; } else { for( int i = 0; i < nBlockSize; ++i ) ((GByte *)pImage)[i] = cimg.Get()[y+=iStep]; } } else { // initialize to 0's (so that it does not have to be done in an 'else' statement <performance>) memset(pImage, 0, nBlockXSize * nBlockYSize * iBytesPerPixel); if (poGDS->command.cDataConversion == 'B') { for( int j = 0; j < chunck_height; ++j ) // assumption: nBlockYSize == chunck_height { int iXOffset = j * nBlockXSize + iShift; iXOffset += nBlockXSize - iLowerWestColumnPlanned - 1; // Position the HRV part in the frame; -1 to compensate the pre-increment in the for-loop if (fSplitStrip && (j >= iSplitRow)) // In splitstrip, below splitline, thus do not shift!! iXOffset -= iShift; for (int i = 0; i < chunck_width; ++i) ((GByte *)pImage)[++iXOffset] = cimg.Get()[y+=iStep] / 4; } } else { for( int j = 0; j < chunck_height; ++j ) // assumption: nBlockYSize == chunck_height { int iXOffset = j * nBlockXSize + iShift; iXOffset += nBlockXSize - iLowerWestColumnPlanned - 1; // Position the HRV part in the frame; -1 to compensate the pre-increment in the for-loop if (fSplitStrip && (j >= iSplitRow)) // In splitstrip, below splitline, thus do not shift!! iXOffset -= iShift; for (int i = 0; i < chunck_width; ++i) ((GByte *)pImage)[++iXOffset] = cimg.Get()[y+=iStep]; } } } } else if (eDataType == GDT_UInt16) // this is our "normal case" if scan direction is South: 10 bit MSG data became 2 bytes per pixel { if (nBlockXSize == chunck_width) // optimized version { for( int i = 0; i < nBlockSize; ++i ) ((GUInt16 *)pImage)[i] = cimg.Get()[y+=iStep]; } else { // initialize to 0's (so that it does not have to be done in an 'else' statement <performance>) memset(pImage, 0, nBlockXSize * nBlockYSize * iBytesPerPixel); for( int j = 0; j < chunck_height; ++j ) // assumption: nBlockYSize == chunck_height { int iXOffset = j * nBlockXSize + iShift; iXOffset += nBlockXSize - iLowerWestColumnPlanned - 1; // Position the HRV part in the frame; -1 to compensate the pre-increment in the for-loop if (fSplitStrip && (j >= iSplitRow)) // In splitstrip, below splitline, thus do not shift!! iXOffset -= iShift; for (int i = 0; i < chunck_width; ++i) ((GUInt16 *)pImage)[++iXOffset] = cimg.Get()[y+=iStep]; } } } else if (eDataType == GDT_Float32) // radiometric calibration is requested { if (nBlockXSize == chunck_width) // optimized version { for( int i = 0; i < nBlockSize; ++i ) ((float *)pImage)[i] = (float)rRadiometricCorrection(cimg.Get()[y+=iStep], iChannel, nBlockYOff * nBlockYSize + i / nBlockXSize, i % nBlockXSize, poGDS); } else { // initialize to 0's (so that it does not have to be done in an 'else' statement <performance>) memset(pImage, 0, nBlockXSize * nBlockYSize * iBytesPerPixel); for( int j = 0; j < chunck_height; ++j ) // assumption: nBlockYSize == chunck_height { int iXOffset = j * nBlockXSize + iShift; iXOffset += nBlockXSize - iLowerWestColumnPlanned - 1; // Position the HRV part in the frame; -1 to compensate the pre-increment in the for-loop if (fSplitStrip && (j >= iSplitRow)) // In splitstrip, below splitline, thus do not shift!! iXOffset -= iShift; int iXFrom = nBlockXSize - iLowerWestColumnPlanned + iShift; // i is used as the iCol parameter in rRadiometricCorrection int iXTo = nBlockXSize - iLowerWestColumnPlanned + chunck_width + iShift; for (int i = iXFrom; i < iXTo; ++i) // range always equal to chunck_width .. this is to utilize i to get iCol ((float *)pImage)[++iXOffset] = (float)rRadiometricCorrection(cimg.Get()[y+=iStep], iChannel, nBlockYOff * nBlockYSize + j, (fSplitStrip && (j >= iSplitRow))?(i - iShift):i, poGDS); } } } } else // header could not be opened .. make sure block contains 0's memset(pImage, 0, nBlockXSize * nBlockYSize * iBytesPerPixel); } else // file could not be opened .. make sure block contains 0's memset(pImage, 0, nBlockXSize * nBlockYSize * iBytesPerPixel); i_file.close(); } else // file does not exist .. make sure block contains 0's memset(pImage, 0, nBlockXSize * nBlockYSize * iBytesPerPixel); return CE_None; }
MSGRasterBand::MSGRasterBand( MSGDataset *poDS, int nBand ) : fScanNorth(false) , iLowerShift(0) , iSplitLine(0) , iLowerWestColumnPlanned(0) { this->poDS = poDS; this->nBand = nBand; // Find if we're dealing with MSG1, MSG2, MSG3 or MSG4 // Doing this per band is the only way to guarantee time-series when the satellite is changed std::string sPrologueFileName = poDS->command.sPrologueFileName(poDS->iCurrentSatellite, nBand); bool fPrologueExists = (access(sPrologueFileName.c_str(), 0) == 0); // Make sure we're testing for MSG1,2,3 or 4 exactly once, start with the most recently used, and remember it in the static member for the next round. if (!fPrologueExists) { poDS->iCurrentSatellite = 1 + poDS->iCurrentSatellite % MAX_SATELLITES; sPrologueFileName = poDS->command.sPrologueFileName(poDS->iCurrentSatellite, nBand); fPrologueExists = (access(sPrologueFileName.c_str(), 0) == 0); int iTries = 2; while (!fPrologueExists && (iTries < MAX_SATELLITES)) { poDS->iCurrentSatellite = 1 + poDS->iCurrentSatellite % MAX_SATELLITES; sPrologueFileName = poDS->command.sPrologueFileName(poDS->iCurrentSatellite, nBand); fPrologueExists = (access(sPrologueFileName.c_str(), 0) == 0); ++iTries; } if (!fPrologueExists) // assume missing prologue file, keep original satellite number { poDS->iCurrentSatellite = 1 + poDS->iCurrentSatellite % MAX_SATELLITES; sPrologueFileName = poDS->command.sPrologueFileName(poDS->iCurrentSatellite, nBand); } } iSatellite = poDS->iCurrentSatellite; // From here on, the satellite that corresponds to this band is settled to the current satellite nBlockXSize = poDS->GetRasterXSize(); nBlockYSize = poDS->GetRasterYSize(); /* -------------------------------------------------------------------- */ /* Open an input file and capture the header for the nr. of bits. */ /* -------------------------------------------------------------------- */ int iStrip = 1; int iChannel = poDS->command.iChannel(1 + ((nBand - 1) % poDS->command.iNrChannels())); std::string input_file = poDS->command.sFileName(iSatellite, nBand, iStrip); while ((access(input_file.c_str(), 0) != 0) && (iStrip <= poDS->command.iNrStrips(iChannel))) // compensate for missing strips input_file = poDS->command.sFileName(iSatellite, nBand, ++iStrip); if (iStrip <= poDS->command.iNrStrips(iChannel)) { std::ifstream i_file (input_file.c_str(), std::ios::in|std::ios::binary); if (i_file.good()) { XRITHeaderParser xhp (i_file); if (xhp.isValid()) { // Data type is either 8 or 16 bits .. we tell this to GDAL here eDataType = GDT_Byte; // default .. always works if (xhp.nrBitsPerPixel() > 8) { if (poDS->command.cDataConversion == 'N') eDataType = GDT_UInt16; // normal case: MSG 10 bits data else if (poDS->command.cDataConversion == 'B') eDataType = GDT_Byte; // output data type Byte else eDataType = GDT_Float32; // Radiometric calibration } // make IReadBlock be called once per file nBlockYSize = xhp.nrRows(); // remember the scan direction fScanNorth = xhp.isScannedNorth(); } } i_file.close(); } else if (nBand > 1) { // missing entire band .. take data from first band MSGRasterBand* pFirstRasterBand = (MSGRasterBand*)poDS->GetRasterBand(1); eDataType = pFirstRasterBand->eDataType; nBlockYSize = pFirstRasterBand->nBlockYSize; fScanNorth = pFirstRasterBand->fScanNorth; } else // also first band is missing .. do something for fail-safety { eDataType = GDT_Byte; // default .. always works if (poDS->command.cDataConversion == 'N') eDataType = GDT_UInt16; // normal case: MSG 10 bits data else if (poDS->command.cDataConversion == 'B') eDataType = GDT_Byte; // output data type Byte else eDataType = GDT_Float32; // Radiometric calibration // nBlockYSize : default // fScanNorth : default } /* -------------------------------------------------------------------- */ /* For the HRV band, read the prologue for shift and splitline. */ /* -------------------------------------------------------------------- */ if (iChannel == 12) { if (fPrologueExists) { std::ifstream p_file(sPrologueFileName.c_str(), std::ios::in|std::ios::binary); XRITHeaderParser xhp(p_file); Prologue pp; if (xhp.isValid() && xhp.isPrologue()) pp.read(p_file); p_file.close(); iLowerShift = pp.idr()->PlannedCoverageHRV->UpperWestColumnPlanned - pp.idr()->PlannedCoverageHRV->LowerWestColumnPlanned; iSplitLine = abs(pp.idr()->PlannedCoverageHRV->UpperNorthLinePlanned - pp.idr()->PlannedCoverageHRV->LowerNorthLinePlanned) + 1; // without the "+ 1" the image of 1-Jan-2005 splits incorrectly iLowerWestColumnPlanned = pp.idr()->PlannedCoverageHRV->LowerWestColumnPlanned; } } /* -------------------------------------------------------------------- */ /* Initialize the ReflectanceCalculator with the band-dependent info. */ /* -------------------------------------------------------------------- */ int iCycle = 1 + (nBand - 1) / poDS->command.iNrChannels(); std::string sTimeStamp = poDS->command.sCycle(iCycle); m_rc = new ReflectanceCalculator(sTimeStamp, rRTOA[iChannel-1]); }