Example #1
0
bool DataRequestImp::validate(const RasterDataDescriptor *pDescriptor) const
{
   if (pDescriptor == NULL)
   {
      return false;
   }
   unsigned int numRows = pDescriptor->getRowCount();
   unsigned int numColumns = pDescriptor->getColumnCount();
   unsigned int numBands = pDescriptor->getBandCount();
   unsigned int bytesPerElement = pDescriptor->getBytesPerElement();
   unsigned int postLineBytes = 0;

   DimensionDescriptor startRow = getStartRow();
   DimensionDescriptor stopRow = getStopRow();
   unsigned int concurrentRows = getConcurrentRows();
   DimensionDescriptor startColumn = getStartColumn();
   DimensionDescriptor stopColumn = getStopColumn();
   unsigned int concurrentColumns = getConcurrentColumns();
   DimensionDescriptor startBand = getStartBand();
   DimensionDescriptor stopBand = getStopBand();
   unsigned int concurrentBands = getConcurrentBands();

   if (!startRow.isActiveNumberValid() || !stopRow.isActiveNumberValid() ||
      !startColumn.isActiveNumberValid() || !stopColumn.isActiveNumberValid() ||
      !startBand.isActiveNumberValid() || !stopBand.isActiveNumberValid())
   {
      return false;
   }

   //validate all the parameters before continuing
   if (startRow.getActiveNumber() >= numRows || 
      startRow.getActiveNumber() > stopRow.getActiveNumber() ||
      stopRow.getActiveNumber() >= numRows ||
      startColumn.getActiveNumber() >= numColumns ||
      startColumn.getActiveNumber() > stopColumn.getActiveNumber() ||
      stopColumn.getActiveNumber() >= numColumns ||
      startBand.getActiveNumber() >= numBands ||
      startBand.getActiveNumber() > stopBand.getActiveNumber() ||
      stopBand.getActiveNumber() >= numBands ||
      concurrentRows > stopRow.getActiveNumber()-startRow.getActiveNumber()+1 ||
      concurrentColumns > stopColumn.getActiveNumber()-startColumn.getActiveNumber()+1 ||
      concurrentBands > stopBand.getActiveNumber()-startBand.getActiveNumber()+1)
   {
      return false;
   }

   if (getInterleaveFormat() == BSQ)
   {
      // Can only get single-band BSQ accessors
      if (startBand != stopBand || concurrentBands != 1)
      {
         return false;
      }
   }

   return true;
}
void PropertiesRasterLayer::setDisplayBands(QAction* pAction)
{
   if (mpRasterLayer == NULL)
   {
      return;
   }

   RasterElement* pRasterElement = dynamic_cast<RasterElement*>(mpRasterLayer->getDataElement());
   if (pRasterElement == NULL)
   {
      return;
   }

   const RasterDataDescriptor* pDescriptor =
      dynamic_cast<const RasterDataDescriptor*>(pRasterElement->getDataDescriptor());
   if (pDescriptor == NULL)
   {
      return;
   }

   const std::string name = pAction->text().toStdString();
   DimensionDescriptor redBand;
   DimensionDescriptor greenBand;
   DimensionDescriptor blueBand;
   if (RasterUtilities::findColorCompositeDimensionDescriptors(
      pDescriptor, name, redBand, greenBand, blueBand) == false)
   {
      Service<DesktopServices>()->showSuppressibleMsgDlg("Error",
         "Unable to display " + name + ": required wavelengths do not exist for all bands. "
         "Broaden the wavelength region or specify band numbers in the Raster Layers section of the Options dialog.",
         MESSAGE_ERROR, PropertiesRasterLayer::getDisplayAsWarningDialogId());
   }

   // If at least one of red, green, or blue is valid set display mode to RGB and update the combo boxes appropriately
   if (redBand.isActiveNumberValid() || greenBand.isActiveNumberValid() || blueBand.isActiveNumberValid())
   {
      mpDisplayModeCombo->setCurrentIndex(1);
      mpRedBandCombo->setCurrentIndex(redBand.isActiveNumberValid() ? redBand.getActiveNumber() : -1);
      mpGreenBandCombo->setCurrentIndex(greenBand.isActiveNumberValid() ? greenBand.getActiveNumber() : -1);
      mpBlueBandCombo->setCurrentIndex(blueBand.isActiveNumberValid() ? blueBand.getActiveNumber() : -1);
   }
}
Example #3
0
bool GeoTIFFExporter::CreateGeoTIFF(TIFF *pOut)
{
    if (mpFileDescriptor == NULL)
    {
        return false;
    }

    GTIF* pGtif = GTIFNew(pOut);
    if (pGtif == NULL)
    {
        return false;
    }

    // Get the exported lower left corner location
    const vector<DimensionDescriptor>& rows = mpFileDescriptor->getRows();
    const vector<DimensionDescriptor>& columns = mpFileDescriptor->getColumns();

    unsigned int startRow = 0;
    if (rows.empty() == false)
    {
        DimensionDescriptor rowDim = rows.front();
        if (rowDim.isActiveNumberValid() == true)
        {
            startRow = rowDim.getActiveNumber();
        }
    }

    unsigned int startColumn = 0;
    if (columns.empty() == false)
    {
        DimensionDescriptor columnDim = columns.front();
        if (columnDim.isActiveNumberValid() == true)
        {
            startColumn = columnDim.getActiveNumber();
        }
    }

    LocationType llPixel(startColumn, startRow);
    LocationType urPixel = llPixel + 1.0;
    LocationType llGeoCoord;
    LocationType lrGeoCoord;
    LocationType ulGeoCoord;
    LocationType urGeoCoord;

    bool bGeocoords = false;

    if (mpRaster->isGeoreferenced())
    {
        // Get the lat/long values from the RasterElement
        LocationType pixel = llPixel;
        LocationType latLong = mpRaster->convertPixelToGeocoord(pixel);
        llGeoCoord.mY = latLong.mY;
        llGeoCoord.mX = latLong.mX;

        pixel.mX = urPixel.mX;
        pixel.mY = llPixel.mY;
        latLong = mpRaster->convertPixelToGeocoord(pixel);
        lrGeoCoord.mY = latLong.mY;
        lrGeoCoord.mX = latLong.mX;

        pixel.mX = llPixel.mX;
        pixel.mY = urPixel.mY;
        latLong = mpRaster->convertPixelToGeocoord(pixel);
        ulGeoCoord.mY = latLong.mY;
        ulGeoCoord.mX = latLong.mX;

        pixel = urPixel;
        latLong = mpRaster->convertPixelToGeocoord(pixel);
        urGeoCoord.mY = latLong.mY;
        urGeoCoord.mX = latLong.mX;

        bGeocoords = true;
    }
    bool isOrthoRectified = false;
    DynamicObject* pMetaData = mpRaster->getMetadata();
    bool hasMetaDataTag = false;
    if (pMetaData != NULL)
    {
        try
        {
            isOrthoRectified = dv_cast<bool>(pMetaData->getAttribute("orthorectified"));
            hasMetaDataTag = true;
        }
        catch (bad_cast&)
        {
            // attribute is not present or is not a bool, so calculate isOrthoRectified
        }
    }
    if (!hasMetaDataTag)
    {
        // calculate the value of isOrthoRectified
        if (mpRaster->isGeoreferenced() && !rows.empty() && !columns.empty())
        {
            int endRow(-1);
            int endColumn(-1);
            for (vector<DimensionDescriptor>::const_reverse_iterator rowIt = rows.rbegin(); rowIt != rows.rend(); ++rowIt)
            {
                if (rowIt->isActiveNumberValid())
                {
                    endRow = rowIt->getActiveNumber();
                    break;
                }
            }
            for (vector<DimensionDescriptor>::const_reverse_iterator colIt = columns.rbegin();
                    colIt != columns.rend(); ++colIt)
            {
                if (colIt->isActiveNumberValid())
                {
                    endColumn = colIt->getActiveNumber();
                    break;
                }
            }

            if (endRow != -1 && endColumn != -1 &&
                    static_cast<unsigned int>(endRow) > startRow && static_cast<unsigned int>(endColumn) > startColumn)
            {
                // the chip's (0,0)
                LocationType startPixel = llPixel;
                LocationType startGeo = llGeoCoord;

                // the chip's (0,max)
                LocationType rowMax(startPixel.mX, endRow);
                LocationType rowMaxGeo = mpRaster->convertPixelToGeocoord(rowMax);

                // the chip's (max,0)
                LocationType colMax(endColumn, startPixel.mY);
                LocationType colMaxGeo = mpRaster->convertPixelToGeocoord(colMax);

                //
                LocationType rowMaxCheckGeo(rowMaxGeo.mX, startGeo.mY);
                LocationType rowMaxCheck = mpRaster->convertGeocoordToPixel(rowMaxCheckGeo);
                LocationType colMaxCheckGeo(startGeo.mX, colMaxGeo.mY);
                LocationType colMaxCheck = mpRaster->convertGeocoordToPixel(colMaxCheckGeo);

                LocationType deltaRowMax = rowMaxCheck - rowMax;
                LocationType deltaColMax = colMaxCheck - colMax;

                isOrthoRectified = (deltaRowMax.length() < 0.5) && (deltaColMax.length() < 0.5);
            }
        }
    }

    if (bGeocoords == false)
    {
        GTIFFree(pGtif);
        return false;
    }

    LocationType geoCoordCenter((llGeoCoord.mX + lrGeoCoord.mX + ulGeoCoord.mX + urGeoCoord.mX) / 4.0,
                                (llGeoCoord.mY + lrGeoCoord.mY + ulGeoCoord.mY + urGeoCoord.mY) / 4.0);


    // if the data is orthorectified, write out the appropriate tags
    if (isOrthoRectified)
    {
        double pTiepoints[6] = {0.0, 0.0, 0.0, llGeoCoord.mY, llGeoCoord.mX, 0.0};
        TIFFSetField(pOut, TIFFTAG_GEOTIEPOINTS, 6, pTiepoints);
        /*
          The following calculation can result in a negative scale for the latitude and/or longitude. This is correct
          and is explicitly called out in the GeoTIFF spec (GeoTIFF Format Specification version 1.8.1, section 2.6.1)
          as the proper way to handle flipping of the image. A negative latitude scale corresponds to an image with
          its origin in the lower left or lower right corner, while a positive latitude scale corresponds to an image
          with its origin in the upper left or upper right corner. Similarly for longitude scale.
        */
        double pPixelSize[3] = {urGeoCoord.mY - llGeoCoord.mY, llGeoCoord.mX - urGeoCoord.mX, 0.0};
        TIFFSetField(pOut, TIFFTAG_GEOPIXELSCALE, 3, pPixelSize);
    }
    else
    {
        //compute transformation Matrix values
        double a = lrGeoCoord.mY - llGeoCoord.mY;
        double b = ulGeoCoord.mY - llGeoCoord.mY;
        double d = llGeoCoord.mY;
        double e = lrGeoCoord.mX - llGeoCoord.mX;
        double f = ulGeoCoord.mX - llGeoCoord.mX;
        double h = llGeoCoord.mX;
        double k = 1.0;
        double p = 1.0;

        double tMatrix[16] = {a, b, 0.0, d,
                              e, f, 0.0, h,
                              0.0, 0.0, k, 0.0,
                              0.0, 0.0, 0.0, p
                             };

        TIFFSetField(pOut, GTIFF_TRANSMATRIX, 16, tMatrix);
    }

    GTIFKeySet(pGtif, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelGeographic);
    GTIFKeySet(pGtif, GTRasterTypeGeoKey, TYPE_SHORT, 1, RasterPixelIsArea);
    GTIFKeySet(pGtif, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Degree);
    GTIFKeySet(pGtif, GeogLinearUnitsGeoKey, TYPE_SHORT, 1, Linear_Meter);
    GTIFKeySet(pGtif, GeographicTypeGeoKey, TYPE_SHORT, 1, GCS_WGS_84);
    GTIFKeySet(pGtif, ProjCenterLongGeoKey, TYPE_DOUBLE, 1, geoCoordCenter.mY);
    GTIFKeySet(pGtif, ProjCenterLatGeoKey, TYPE_DOUBLE, 1, geoCoordCenter.mX);

    ///* Here we violate the GTIF abstraction to retarget on another file.
    //   We should just have a function for copying tags from one GTIF object
    //   to another.
    pGtif->gt_tif = pOut;
    pGtif->gt_flags |= FLAG_FILE_MODIFIED;

    //* Install keys and tags
    GTIFWriteKeys(pGtif);
    GTIFFree(pGtif);

    return true;
}
Example #4
0
bool GeoTIFFExporter::writeCube(TIFF* pOut)
{
    if (pOut == NULL)
    {
        return false;
    }

    VERIFY(mpRaster != NULL);
    VERIFY(mpFileDescriptor != NULL);

    const RasterDataDescriptor* pDescriptor = dynamic_cast<const RasterDataDescriptor*>(mpRaster->getDataDescriptor());
    if (pDescriptor == NULL)
    {
        return false;
    }

    int size = 0;
    int row = 0;
    unsigned char* pTempPtr = NULL;
    unsigned char* pBuffer = NULL;
    unsigned char* pDataCubePtr = NULL;
    unsigned short numRows = pDescriptor->getRowCount();
    unsigned short numCols = pDescriptor->getColumnCount();
    unsigned short numBands = pDescriptor->getBandCount();
    unsigned short scols = mpFileDescriptor->getColumnCount();
    unsigned short srows = mpFileDescriptor->getRowCount();
    unsigned short sbands = mpFileDescriptor->getBandCount();

    FactoryResource<DataRequest> pRequest;
    pRequest->setInterleaveFormat(BIP);
    DataAccessor accessor = mpRaster->getDataAccessor(pRequest.release());
    if (!accessor.isValid())
    {
        mMessage = "Could not get a valid BIP accessor for this dataset.";
        if (mpProgress != NULL)
        {
            mpProgress->updateProgress(mMessage, 0, ERRORS);
        }

        return false;
    }

    InterleaveFormatType eInterleave = pDescriptor->getInterleaveFormat();
    if (eInterleave != BIP)
    {
        mMessage = "Data will be saved in BIP format.";
        if (mpProgress != NULL)
        {
            mpProgress->updateProgress(mMessage, 0, WARNING);
        }
    }

    unsigned int bytesPerElement(pDescriptor->getBytesPerElement());
    size = scols * sbands * bytesPerElement;

    TIFFSetField(pOut, TIFFTAG_IMAGEWIDTH, scols);
    TIFFSetField(pOut, TIFFTAG_IMAGELENGTH, srows);
    TIFFSetField(pOut, TIFFTAG_SAMPLESPERPIXEL, sbands);

    //for this tag, must multiply by # of bytes per data type
    TIFFSetField(pOut, TIFFTAG_BITSPERSAMPLE, static_cast<unsigned short>(bytesPerElement * 8));
    TIFFSetField(pOut, TIFFTAG_SAMPLEFORMAT, static_cast<unsigned short>(
                     getTiffSampleFormat(pDescriptor->getDataType())));

    bool packBits = OptionsTiffExporter::getSettingPackBitsCompression();
    if (mpOptionWidget.get() != NULL)
    {
        mpOptionWidget->applyChanges();
        packBits = mpOptionWidget->getPackBitsCompression();
    }
    ttag_t compOpt = (packBits ? COMPRESSION_PACKBITS : COMPRESSION_NONE);

    TIFFSetField(pOut, TIFFTAG_COMPRESSION, compOpt);
    TIFFSetField(pOut, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
    TIFFSetField(pOut, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(pOut, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);      //????
    TIFFSetField(pOut, TIFFTAG_ROWSPERSTRIP, mRowsPerStrip);

    //ready to test write
    mMessage = "Writing out GeoTIFF file...";
    if (mpProgress)
    {
        mpProgress->updateProgress( mMessage, 0, NORMAL);
    }

    if ((numRows == srows) && (numCols == scols) && (numBands == sbands))   // full cube write from memory
    {
        for (row = 0; row < srows; row++)
        {
            if (mAbortFlag)
            {
                mMessage = "GeoTIFF export aborted!";
                if (mpProgress != NULL)
                {
                    mpProgress->updateProgress(mMessage, 0, ERRORS);
                }

                return false;
            }

            VERIFY(accessor.isValid());
            pBuffer = reinterpret_cast<unsigned char*>(accessor->getRow());
            if (pBuffer != NULL)
            {
                if (TIFFWriteScanline(pOut, pBuffer, row, size) < 0)
                {
                    mMessage = "Unable to save GeoTIFF file, check folder permissions.";
                    if (mpProgress)
                    {
                        mpProgress->updateProgress(mMessage, 0, ERRORS);
                    }

                    return false;
                }

                updateProgress(row, srows, mMessage, NORMAL);
            }
            accessor->nextRow();
        }
    }
    else // subcube write
    {
        const vector<DimensionDescriptor>& rows = mpFileDescriptor->getRows();
        const vector<DimensionDescriptor>& columns = mpFileDescriptor->getColumns();
        const vector<DimensionDescriptor>& bands = mpFileDescriptor->getBands();

        unsigned int activeRowNumber = 0;
        unsigned int rowSize(0);
        unsigned int outRow(0);
        for (unsigned int r = 0; r < srows; ++r)
        {
            if (mAbortFlag == true)
            {
                mMessage = "GeoTIFF export aborted!";
                if (mpProgress != NULL)
                {
                    mpProgress->updateProgress(mMessage, 0, ERRORS);
                }

                return false;
            }

            DimensionDescriptor rowDim = rows[r];
            if (rowDim.isActiveNumberValid())
            {
                // Skip to the next row
                for (; activeRowNumber < rowDim.getActiveNumber(); ++activeRowNumber)
                {
                    accessor->nextRow();
                }

                VERIFY(accessor.isValid());

                vector<char> rowData(size);
                if (rowData.empty())
                {
                    mMessage = "Error GeoTIFFExporter008: Unable to allocate row buffer.";
                    if (mpProgress)
                    {
                        mpProgress->updateProgress(mMessage, 0, ERRORS);
                    }

                    return false;
                }

                unsigned int activeColumnNumber = 0;

                char* pExportData = &(rowData.front());
                for (unsigned int c = 0; c < scols; ++c)
                {
                    DimensionDescriptor columnDim = columns[c];
                    if (columnDim.isActiveNumberValid())
                    {
                        // Skip to the next column
                        for (; activeColumnNumber < columnDim.getActiveNumber(); ++activeColumnNumber)
                        {
                            accessor->nextColumn();
                        }

                        char* pCurrentPixel = reinterpret_cast<char*>(accessor->getColumn());

                        unsigned int activeBandNumber = 0;
                        for (unsigned int b = 0; b < sbands; ++b)
                        {
                            DimensionDescriptor bandDim = bands[b];
                            if (bandDim.isActiveNumberValid())
                            {
                                // Skip to the next band
                                for (; activeBandNumber < bandDim.getActiveNumber(); ++activeBandNumber)
                                {
                                    pCurrentPixel += bytesPerElement;
                                }

                                memcpy(pExportData, pCurrentPixel, bytesPerElement);
                                pExportData += bytesPerElement;
                                rowSize += bytesPerElement;
                            }
                        }
                    }
                    else // this column is not included, go to next column
                    {
                        accessor->nextColumn();
                    }
                }

                if (rowSize > 0)
                {
                    // write here
                    if (TIFFWriteScanline(pOut, &rowData[0], outRow, size) < 0)
                    {
                        mMessage = "Error GeoTIFFExporter006: Unable to save GeoTIFF file, check folder permissions.";
                        if (mpProgress)
                        {
                            mpProgress->updateProgress(mMessage, 0, ERRORS);
                        }

                        return false;
                    }

                    updateProgress(outRow++, srows, mMessage, NORMAL);
                }
            }
            else // this row is not included, go to next row
            {
                accessor->nextRow();
            }
        }
    }

    //assumed everything has been done correctly up to now
    //copy over Geo ref info if there are any, else
    //try to look for world file in same directory and apply
    if (!(applyWorldFile(pOut)))
    {
        if (!(CreateGeoTIFF(pOut)))
        {
            //no geo info found, where is it located?
            mMessage = "Geo data is unavailable and will not be written to the output file!";
            updateProgress(srows, srows, mMessage, WARNING);
            if (mpStep != NULL)
            {
                mpStep->addMessage(mMessage, "app", "9C1E7ADE-ADC4-468c-B15E-FEB53D5FEF5B", true);
            }
        }
    }

    return true;
}
void PropertiesRasterLayer::updateDisplayedBandCombo(int index)
{
   // Get the selected raster element
   RasterElement* pElement = NULL;
   if ((index > -1) && (static_cast<int>(mRasterElements.size()) > index))
   {
      pElement = mRasterElements[index];
   }

   // Get the band names from the element
   QStringList strBandNames;
   if (pElement != NULL)
   {
      RasterDataDescriptor* pDescriptor = dynamic_cast<RasterDataDescriptor*>(pElement->getDataDescriptor());
      if (pDescriptor != NULL)
      {
         vector<string> bandNames = RasterUtilities::getBandNames(pDescriptor);
         for (vector<string>::iterator iter = bandNames.begin(); iter != bandNames.end(); ++iter)
         {
            strBandNames.append(QString::fromStdString(*iter));
         }
      }
   }

   // Update the display band combo
   QComboBox* pCombo = dynamic_cast<QComboBox*>(sender());
   if (pCombo == mpGrayElementCombo)
   {
      mpGrayBandCombo->clear();
      mpGrayBandCombo->addItems(strBandNames);

      if (strBandNames.isEmpty() == false)
      {
         mpGrayBandCombo->setCurrentIndex(0);
         if ((mpRasterLayer != NULL) && (mpRasterLayer->getDataElement() == pElement))
         {
            DimensionDescriptor displayedBand = mpRasterLayer->getDisplayedBand(GRAY);
            if (displayedBand.isActiveNumberValid() == true)
            {
               mpGrayBandCombo->setCurrentIndex(displayedBand.getActiveNumber());
            }
         }
      }
   }
   else if (pCombo == mpRedElementCombo)
   {
      mpRedBandCombo->clear();
      mpRedBandCombo->addItems(strBandNames);

      if (strBandNames.isEmpty() == false)
      {
         mpRedBandCombo->setCurrentIndex(0);
         if ((mpRasterLayer != NULL) && (mpRasterLayer->getDataElement() == pElement))
         {
            DimensionDescriptor displayedBand = mpRasterLayer->getDisplayedBand(RED);
            if (displayedBand.isActiveNumberValid() == true)
            {
               mpRedBandCombo->setCurrentIndex(displayedBand.getActiveNumber());
            }
         }
      }
   }
   else if (pCombo == mpGreenElementCombo)
   {
      mpGreenBandCombo->clear();
      mpGreenBandCombo->addItems(strBandNames);

      if (strBandNames.isEmpty() == false)
      {
         mpGreenBandCombo->setCurrentIndex(0);
         if ((mpRasterLayer != NULL) && (mpRasterLayer->getDataElement() == pElement))
         {
            DimensionDescriptor displayedBand = mpRasterLayer->getDisplayedBand(GREEN);
            if (displayedBand.isActiveNumberValid() == true)
            {
               mpGreenBandCombo->setCurrentIndex(displayedBand.getActiveNumber());
            }
         }
      }
   }
   else if (pCombo == mpBlueElementCombo)
   {
      mpBlueBandCombo->clear();
      mpBlueBandCombo->addItems(strBandNames);

      if (strBandNames.isEmpty() == false)
      {
         mpBlueBandCombo->setCurrentIndex(0);
         if ((mpRasterLayer != NULL) && (mpRasterLayer->getDataElement() == pElement))
         {
            DimensionDescriptor displayedBand = mpRasterLayer->getDisplayedBand(BLUE);
            if (displayedBand.isActiveNumberValid() == true)
            {
               mpBlueBandCombo->setCurrentIndex(displayedBand.getActiveNumber());
            }
         }
      }
   }
}