[gdal-dev] gdalwarper destination alpha mask

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[gdal-dev] gdalwarper destination alpha mask

Glenn Burkhardt-2
I'm trying to track down a discrepancy between GDAL 1.7.2 and GDAL
2.4.0.  The NASA Worldwind code makes a call to gdal.ReprojectImage()
using a dataset generated from an input file to a working destination
dataset that's empty, except that the alpha band has been filled with
0xFF.  In the case I'm examining, the projection is 1 to 1; no change. 
The source file has an appropriate alpha mask to clip the image so only
relevant data is shown.

When using the 1.7.2 release, the image is shown with a proper overlay
on the lower priority layers, with the portions with alpha mask of 0
being completely transparent.  But the more recent 2.4.0 release has a
black boundary around the image, indicating that the alpha mask was set
to 0xff for the whole image.

It looks like there's a difference in behavior in the Java call

                         gdal.ReprojectImage(srcDS, destDS, s_srs_wkt,
t_srs_wkt, gdalconst.GRA_Average);

For the 1.7.2 release, the alpha mask in the destination data set is
filled in correctly, matching the alpha band in the source. But in the
2.4.0 release, the destination alpha band is filled with 0xFF, which
sort of explains the black boundary.  Curiously, for the 1.7.2 release,
it doesn't matter if the destination alpha band was filled with zeros or
0xFF.  For the 2.4.0 release, if the destination dataset alpha band is
filled with zeros, the image displays correctly, and the reprojected
destination dataset alpha band matches the source.

I'm trying to understand what the purpose is of the destination alpha
density mask in 'gdalwarpper.cpp'.  In the file 'gdalwarpoperation.cpp',
I see a note that says "Note that detailed semantics of the masks should
be found in

GDALWarpKernel."  And in 'gdalwarpkernel.cpp': "A detailed explanation
of the semantics of the validity and density masks, and their effects on
resampling kernels is needed here."

So if there's a place where the semantics are explained, please send me
link.  And, if this rings a bell about a change that was made some time
between the 1.7.2 (April 23, 2010) and the 2.4.0, please let me know.

Thanks.

_______________________________________________
gdal-dev mailing list
[hidden email]
https://lists.osgeo.org/mailman/listinfo/gdal-dev
Reply | Threaded
Open this post in threaded view
|

Re: gdalwarper destination alpha mask

Even Rouault-2
Glenn,

> I'm trying to track down a discrepancy between GDAL 1.7.2 and GDAL
> 2.4.0.  The NASA Worldwind code makes a call to gdal.ReprojectImage()
> using a dataset generated from an input file to a working destination
> dataset that's empty, except that the alpha band has been filled with
> 0xFF.  In the case I'm examining, the projection is 1 to 1; no change.
> The source file has an appropriate alpha mask to clip the image so only
> relevant data is shown.
>
> When using the 1.7.2 release, the image is shown with a proper overlay
> on the lower priority layers, with the portions with alpha mask of 0
> being completely transparent.  But the more recent 2.4.0 release has a
> black boundary around the image, indicating that the alpha mask was set
> to 0xff for the whole image.
>
> It looks like there's a difference in behavior in the Java call
>
>                          gdal.ReprojectImage(srcDS, destDS, s_srs_wkt,
> t_srs_wkt, gdalconst.GRA_Average);
>
> For the 1.7.2 release, the alpha mask in the destination data set is
> filled in correctly, matching the alpha band in the source. But in the
> 2.4.0 release, the destination alpha band is filled with 0xFF, which
> sort of explains the black boundary.  Curiously, for the 1.7.2 release,
> it doesn't matter if the destination alpha band was filled with zeros or
> 0xFF.  For the 2.4.0 release, if the destination dataset alpha band is
> filled with zeros, the image displays correctly, and the reprojected
> destination dataset alpha band matches the source.
>
> I'm trying to understand what the purpose is of the destination alpha
> density mask in 'gdalwarpper.cpp'.  In the file 'gdalwarpoperation.cpp',
> I see a note that says "Note that detailed semantics of the masks should
> be found in
>
> GDALWarpKernel."  And in 'gdalwarpkernel.cpp': "A detailed explanation
> of the semantics of the validity and density masks, and their effects on
> resampling kernels is needed here."
>
> So if there's a place where the semantics are explained, please send me
> link.  And, if this rings a bell about a change that was made some time
> between the 1.7.2 (April 23, 2010) and the 2.4.0, please let me know.

Looking at the NEWS file, the change of behaviour likely dates back to GDAL
1.8.0:
 * GDALReprojectImage() : correctly assign nSrcAlphaBand and nDstAlphaBand
(#3821) --> https://trac.osgeo.org/gdal/ticket/3821

Previously the source and target alpha bands were treated as regular bands.
If the target alpha band is initialized to 0xFF, then it means that all target
pixels are valid, and thus they will remain the same if there is no
corresponding source pixel, or if they have source_alpha = 0.

The maths involved with destination density are in:
https://github.com/OSGeo/gdal/blob/master/gdal/alg/gdalwarpkernel.cpp#L1330
https://github.com/OSGeo/gdal/blob/master/gdal/alg/gdalwarpkernel.cpp#L1414
Basically this is for alpha blending of source onto target.

That said, looking at the above mentionned change in GDALReprojectImage(), I
noticed there was something slightly wrong, which I just fixed, in which the
alpha bands were treated both as regular bands and alpha bands. So I'm not
sure what the effect was exactly. That said, the difference in results seemed
minimal when warping over a target image initialized with alpha = 0.

So all in all, you should initialize your target image with alpha = 0 as you
noticed.

Even


--
Spatialys - Geospatial professional services
http://www.spatialys.com
_______________________________________________
gdal-dev mailing list
[hidden email]
https://lists.osgeo.org/mailman/listinfo/gdal-dev
Reply | Threaded
Open this post in threaded view
|

Re: gdalwarper destination alpha mask

Glenn Burkhardt-2
On 5/5/2019 1:16 PM, Even Rouault wrote:
Glenn,

I'm trying to track down a discrepancy between GDAL 1.7.2 and GDAL
2.4.0.  The NASA Worldwind code makes a call to gdal.ReprojectImage()
using a dataset generated from an input file to a working destination
dataset that's empty, except that the alpha band has been filled with
0xFF.  In the case I'm examining, the projection is 1 to 1; no change. 
The source file has an appropriate alpha mask to clip the image so only
relevant data is shown.

When using the 1.7.2 release, the image is shown with a proper overlay
on the lower priority layers, with the portions with alpha mask of 0
being completely transparent.  But the more recent 2.4.0 release has a
black boundary around the image, indicating that the alpha mask was set
to 0xff for the whole image.

It looks like there's a difference in behavior in the Java call

                         gdal.ReprojectImage(srcDS, destDS, s_srs_wkt,
t_srs_wkt, gdalconst.GRA_Average);

For the 1.7.2 release, the alpha mask in the destination data set is
filled in correctly, matching the alpha band in the source. But in the
2.4.0 release, the destination alpha band is filled with 0xFF, which
sort of explains the black boundary.  Curiously, for the 1.7.2 release,
it doesn't matter if the destination alpha band was filled with zeros or
0xFF.  For the 2.4.0 release, if the destination dataset alpha band is
filled with zeros, the image displays correctly, and the reprojected
destination dataset alpha band matches the source.

I'm trying to understand what the purpose is of the destination alpha
density mask in 'gdalwarpper.cpp'.  In the file 'gdalwarpoperation.cpp',
I see a note that says "Note that detailed semantics of the masks should
be found in

GDALWarpKernel."  And in 'gdalwarpkernel.cpp': "A detailed explanation
of the semantics of the validity and density masks, and their effects on
resampling kernels is needed here."

So if there's a place where the semantics are explained, please send me
link.  And, if this rings a bell about a change that was made some time
between the 1.7.2 (April 23, 2010) and the 2.4.0, please let me know.
Looking at the NEWS file, the change of behaviour likely dates back to GDAL 
1.8.0:
 * GDALReprojectImage() : correctly assign nSrcAlphaBand and nDstAlphaBand 
(#3821) --> https://trac.osgeo.org/gdal/ticket/3821

Previously the source and target alpha bands were treated as regular bands.
If the target alpha band is initialized to 0xFF, then it means that all target 
pixels are valid, and thus they will remain the same if there is no 
corresponding source pixel, or if they have source_alpha = 0.

The maths involved with destination density are in:
https://github.com/OSGeo/gdal/blob/master/gdal/alg/gdalwarpkernel.cpp#L1330
https://github.com/OSGeo/gdal/blob/master/gdal/alg/gdalwarpkernel.cpp#L1414
Basically this is for alpha blending of source onto target.

That said, looking at the above mentionned change in GDALReprojectImage(), I 
noticed there was something slightly wrong, which I just fixed, in which the 
alpha bands were treated both as regular bands and alpha bands. So I'm not 
sure what the effect was exactly. That said, the difference in results seemed 
minimal when warping over a target image initialized with alpha = 0.

So all in all, you should initialize your target image with alpha = 0 as you 
noticed.

Even


It turns out that the change you made for treating the alpha band separately (https://github.com/OSGeo/gdal/commit/b427cb23ff1bc2a5ba2f6634fc3bd90816bb7789) fixed one other problem that you might have intended to fix, but has caused another. 

I have a general question - the new code assumes that the alpha band will always be the last one in the dataset.  Is that guaranteed by some standard?  In the previous code, the alpha band could have been band 1, and the band number was recorded for later use.

After I changed the WorldWind code to initialize the target alpha band to 0, which fixed my immediate problem, I discovered that if the source dataset has no alpha band, that the alpha band of the result has all zeros.  That doesn't happen with your change - it doesn't matter what's in the target alpha band initially if there is no alpha band in the source - after reprojectImage, the alpha band of the result has all 255 regardless of the values initially in the target dataset.  That makes sense.

Perhaps that's the problem you intended to fix.

The new problem in the WorldWind code is that 'reprojectImage' was used to clip the source dataset to a 'region-of-interest' (ROI).  That's probably an improper use of reprojectImage.  If you refer to this code:

    https://github.com/WorldWindEarth/WorldWindJava/blob/develop/src/gov/nasa/worldwind/data/GDALDataRaster.java

in createMaskDataset at line 466, it's creating a dataset with a single alpha band for the ROI.  When the mask dataset is used at line 1135 in a reprojectImage call, GDAL correctly reports a warning:

    GDAL error 5 : GDALWarpOptions.Validate(): nBandCount=0, no bands configured!

The intent was to generate a dataset with alpha=0 outside of the ROI.  In the call to GDALUtils.composeDataRaster at line 1154, the alpha band is retrieved from the mask data set, and eventually used in 'GDALUtils.applyImageMask()' to clip the image.

    https://github.com/WorldWindEarth/WorldWindJava/blob/develop/src/gov/nasa/worldwind/util/gdal/GDALUtils.java

So in order to work with any GDAL release after 3.0.0, that code will need to be reworked. 

If you tell me that WorldWind's use of 'reprojectImage' is inappropriate for this purpose, that's fine.  It will need to be re-written.  But other users might be using 'reprojectImage' for similar purposes, other code might break.  Some entry in the release notes might help.


_______________________________________________
gdal-dev mailing list
[hidden email]
https://lists.osgeo.org/mailman/listinfo/gdal-dev
Reply | Threaded
Open this post in threaded view
|

Re: gdalwarper destination alpha mask

Even Rouault-2
> It turns out that the change you made for treating the alpha band
> separately
> (https://github.com/OSGeo/gdal/commit/b427cb23ff1bc2a5ba2f6634fc3bd90816bb77
> 89) fixed one other problem that you might have intended to fix, but has
> caused another.
>
> I have a general question - the new code assumes that the alpha band
> will always be the last one in the dataset.  Is that guaranteed by some
> standard?  In the previous code, the alpha band could have been band 1,
> and the band number was recorded for later use.

That's an informal convention used in GDAL, and in particularly by the
gdalwarp utility and the warping kernel itself. If the alpha band is not the
last one, it would be reprojected as any other band. In fact, the warping
kernel does not reproject the source alpha band (when it is the last one): it
uses it as a mask for the other bands. And it updates the destination alpha
band with the pixel "density" of the reprojected pixels.
The intent of the changes done in GDALReprojectImage() is that it behaves like
GDALWarp() as much as possible. It seems GDALReprojectImage() didn't initially
take into accout the specificities of alpha at all, and that a later attempt
at doing so was broken.

>
> After I changed the WorldWind code to initialize the target alpha band
> to 0, which fixed my immediate problem, I discovered that if the source
> dataset has no alpha band, that the alpha band of the result has all
> zeros.  That doesn't happen with your change - it doesn't matter what's
> in the target alpha band initially if there is no alpha band in the
> source - after reprojectImage, the alpha band of the result has all 255
> regardless of the values initially in the target dataset.

Depends. If the reprojection doesn't cause geometry changes, then yes, this
will be 255. Otherwise you'll get 0 in the areas that don't have a
corresponding source pixel.

>
> Perhaps that's the problem you intended to fix.
>
> The new problem in the WorldWind code is that 'reprojectImage' was used
> to clip the source dataset to a 'region-of-interest' (ROI).  That's
> probably an improper use of reprojectImage.  If you refer to this code:
>
> https://github.com/WorldWindEarth/WorldWindJava/blob/develop/src/gov/nasa/wo
> rldwind/data/GDALDataRaster.java
>
> in createMaskDataset at line 466, it's creating a dataset with a single
> alpha band for the ROI.  When the mask dataset is used at line 1135 in a
> reprojectImage call, GDAL correctly reports a warning:
>
>      GDAL error 5 : GDALWarpOptions.Validate(): nBandCount=0, no bands
> configured!
>
> The intent was to generate a dataset with alpha=0 outside of the ROI.
> In the call to GDALUtils.composeDataRaster at line 1154, the alpha band
> is retrieved from the mask data set, and eventually used in
> 'GDALUtils.applyImageMask()' to clip the image.

I believe you should proceed differently. Create a composite image *before*
reproject with the source alpha band at 0 in the areas outside of the ROI.
Or unmark your mask band as being an alpha band so it is treated as a regular
band.

Even

--
Spatialys - Geospatial professional services
http://www.spatialys.com
_______________________________________________
gdal-dev mailing list
[hidden email]
https://lists.osgeo.org/mailman/listinfo/gdal-dev