/** * \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; }
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) }