Hey Marco,
Here's the code I have for a bilinear-based implementation (attached),
though I've omitted the actual NN and bilinear resampling code itself for
brevity. This does have a number of implementation-specific assumptions
which would need to be reworked for the general case. (the general case in
GIS is hard and makes my brain bleed.) So it's not really close to the
point of being ready for a pull request.
It could be adapted to work on RGBA output, though with some modifications
mostly involving using the alpha channel with a NN resample in place of the
NODATA values.
It should be all ANSI C with no external dependencies. (except for one
irrelevant Accelerate framework call)
Hope this is useful -- let me know if anything else is needed.
On Tue, Feb 18, 2014 at 1:14 AM, Marco Hugentobler <
marco.hugentob...@sourcepole.ch> wrote:
> Hi Nick
>
> Resampling on data level does not work in case of colormap rasters,
> therefore the resampling filter currently comes after assigning rgba. One
> possibility would be to provide a user choice if resampling should be done
> on color values or on data.
>
> I think it is best if you post your code (as a pull request on github or
> via mailing list), then others can give it a try and provide feedback. I'm
> not really a raster power user myself (mostly working with rasters as
> background images for maps).
>
> Regards,
> Marco
//
// GetZoomedTile_BilinearPunch:
//
//
// Wrapper around bilinear resize for a raster that preserves NODATA values
// without artifacts.
//
// Evenly resizes (zooming in only) a planar 32-bit float tile of varying resolution,
//normally 256x256 - 384x384.
//
// It will work on other widths and heights, but some of the logic expecting evenly
//divisible srcWH and resampleBufferWH may need to change, or need a ceilf.
//
// Preserves NODATA values vaguely (but not really) derived from PVR textures;
//a "punch through" technique is used based upon NN resampling.
//
// To avoid interpolating NODATAs, a neighborhood raster stats mean function is used.
//
// Currently assumes NODATA = 0.0F and that interpolated values will not be transformed
//into NODATA.
//
void gbImage_GetZoomedTile_BilinearPunch_v2(float* src,
const size_t srcWidth,
const size_t srcHeight,
const size_t srcWidthUnpadded,
const size_t srcHeightUnpadded,
const size_t srcDataCount,
float* dest,
const size_t destWidth,
const size_t destHeight,
float* resampleBuffer,
const size_t resampleBufferWidth,
const size_t resampleBufferHeight,
float* tempBuffer,
const size_t tempBufferBytes,
const intinterpolationTypeId,
const bool doNotTile,
const float NODATA)
{
const bool useBitmask = srcDataCount < srcWidth * srcHeight;
const bool cleanOutput = destWidth == resampleBufferWidth && destHeight == resampleBufferHeight;
// first, get NN resampled mask to filter resampled output with later
if (useBitmask && interpolationTypeId == kGB_TileEngine_Interp_Bilinear)
{
// returns NN resampled raster tile of 0 or 1, which is somewhat more efficient than using conditionals later, but will *not* work in the general case.
// for the general case, do a normal NN resize here, and use a conditional in the final filtering step instead of vmul
gbImage_GetZoomedTile_NN_FromCrop_Bitmask(src, srcWidthUnpadded, srcHeightUnpadded, srcWidth, dest, destWidth, destHeight, NODATA);
_gbImage_FillNODATA(src, srcWidth, srcHeight, srcWidthUnpadded, srcHeightUnpadded, srcDataCount, tempBuffer, tempBufferBytes, interpolationTypeId, NODATA);
}//if
// always do NoNODATA if possible, other version is branchy and slower due to inline NODATA conditionals
if (interpolationTypeId == kGB_TileEngine_Interp_Bilinear || !useBitmask)
{
gbImage_BilinearVectorized_NoNODATA(src,
srcWidth,
srcHeight,
cleanOutput ? dest : resampleBuffer,
resampleBufferWidth,
resampleBufferHeight,
true);