/**
 * \todo TODO: do stretching histogram
 */
bool LinearStretchOperation::stretch(IRasterCoverage toStretch)
{
    NumericStatistics& statistics = _inputRaster->statistics();

    // TODO: separate histogram into own class (and move
    // certain operations to it

    SPNumericRange rng = _inputRaster->datadef().range<NumericRange>();
    double valueRange = rng->distance();
    PixelIterator iterInput(_inputRaster);

    std::for_each(begin(_outputRaster), end(_outputRaster), [&](double& v) {
        double vin = *iterInput;
        if(vin >= _limits.first && vin <= _limits.second) {
            v = statistics.stretchLinear(vin, valueRange);
        }
        ++iterInput;
    });

    return true;
}
Example #2
0
void RasterValueImage::setTextureData(ValueTexture *tex, const unsigned int offsetX, const unsigned int offsetY, unsigned int texSizeX, unsigned int texSizeY, unsigned int zoomFactor)
{
    long imageWidth = _raster->size().xsize();
    long imageHeight = _raster->size().ysize();
    long sizeX = texSizeX; // the size of the input (pixeliterator)
    long sizeY = texSizeY;
    if (offsetX + sizeX > imageWidth)
        sizeX = imageWidth - offsetX;
    if (offsetY + sizeY > imageHeight)
        sizeY = imageHeight - offsetY;
    if (sizeX == 0 || sizeY == 0)
        return;
    const long xSizeOut = (long)ceil((double)sizeX / ((double)zoomFactor)); // the size until which the pixels vector will be filled (this is commonly the same as texSizeX, except the rightmost / bottommost textures, as raster-images seldom have as size of ^2)
    texSizeX /= zoomFactor; // the actual size of the texture (commonly 256 or maxtexturesize, but smaller texture sizes may be allocated for the rightmost or bottommost textures)
    texSizeY /= zoomFactor;

    BoundingBox bb(Pixel(offsetX, offsetY), Pixel(offsetX + sizeX - 1, offsetY + sizeY - 1));
    // the "pixels" array must be made 32-bit aligned (32-bit-alignment is required by QImage)
    int xl = (quint32)texSizeX % 4 == 0 ? texSizeX : ((texSizeX / 4) + 1) * 4;
    int rest = xl - texSizeX;
    quint32 size = xl * texSizeY;
    std::vector<quint8> * pixels = new std::vector<quint8> ();
    pixels->resize(size);
    PixelIterator pixIter(_raster, bb); // This iterator runs through bb. The corners of bb are "inclusive".

    SPNumericRange numrange = _raster->datadef().range<NumericRange>();
    if (!numrange->isValid())
        _raster->statistics(NumericStatistics::pBASIC);
    auto end = pixIter.end();
    quint32 position = 0;
    while(pixIter != end){
        double value = *pixIter;
        int index = isNumericalUndef2(value,_raster) ? 0 : 1 + (_colorTable.size() - 2) * (value - numrange->min()) / numrange->distance();
        (*pixels)[position] = index; // int32 to quint8 conversion (do we want this?)
        pixIter += zoomFactor;
        if ( pixIter.ychanged()) {
            position += (rest + texSizeX - xSizeOut);
            if (zoomFactor > 1)
                pixIter += sizeX * (zoomFactor - 1) - ((zoomFactor - (sizeX % zoomFactor)) % zoomFactor);
        }
        ++position;
    }
    const uchar *datablock = (const uchar *)pixels->data();
    QImage * image = new QImage(datablock, xl, texSizeY, QImage::Format_Indexed8);
    image->setColorTable(_colorTable);
    tex->setQImage(image, pixels); // carry over the image and the data-buffer to the texture object (see QImage documentation: the data-buffer must exist throughout the existence of the QImage)
}