Repository: rasterio/rasterio

Issue:
WarpedVRT issue when alpha 
In https://github.com/rasterio/rasterio/blob/d008e8aab38afd5d14d98499847754bd0eeaa501/rasterio/_warp.pyx#L978-L979
`dst_alpha` will always be set to `0` when `add_alpha` is False. 

This cause an issue when we already have an alpha band in the data. For some reason the output data will then be totally different.

#### Show image difference 

```python
#### Comparison between rasterio / WarpedVRT and GDALWarpedVRT

```python
import os
import rasterio
from rasterio.vrt import WarpedVRT

# Pure Rasterio Read
with rasterio.open("fake.tif") as src:
    alpha = src.read(out_shape=(1, int(src.height/10), int(src.width/10)), indexes=(6,))
    arr = src.read(out_shape=(1, int(src.height/10), int(src.width/10)), indexes=(1,))
    print("Rasterio - mean: ", arr[alpha > 0].mean())

# Use WarpedVRT but without reprojection
with rasterio.open("fake.tif") as src:
    with WarpedVRT(src, add_alpha=False) as vrt:
        alpha = src.read(out_shape=(1, int(src.height/10), int(src.width/10)), indexes=(6,))
        arr = vrt.read(out_shape=(1, int(src.height/10), int(src.width/10)), indexes=(1,))
        print("WarpedVRT - mean: ", arr[alpha > 0].mean())


# Create a WarpedVRT using GDAL
os.system("gdalwarp -of VRT fake.tif fake.vrt -overwrite")

with rasterio.open("fake.vrt") as src:
    alpha = src.read(out_shape=(1, int(src.height/10), int(src.width/10)), indexes=(6,))
    arr = src.read(out_shape=(1, int(src.height/10), int(src.width/10)), indexes=(1,))
    print("GDAL - mean: ", arr[alpha > 0].mean())
>>> Rasterio - mean:  10000
>>> WarpedVRT - mean:  39
>>> GDAL - mean: 10000
```

First reported in https://github.com/developmentseed/titiler/discussions/629


Discussion:

Resolving patch:
diff --git a/rasterio/vrt.py b/rasterio/vrt.py
--- a/rasterio/vrt.py
+++ b/rasterio/vrt.py
@@ -55,6 +55,8 @@ class WarpedVRT(WarpedVRTReaderBase, WindowMethodsMixin,
         or one-eigth of a pixel.
     src_alpha : int, optional
         Index of a source band to use as an alpha band for warping.
+    dst_alpha : int, optional
+        Index of a destination band to use as an alpha band for warping.
     add_alpha : bool, optional
         Whether to add an alpha masking band to the virtual dataset.
         Default: False. This option will cause deletion of the VRT


Test patch:
diff --git a/tests/data/RGBA.uint16.tif b/tests/data/RGBA.uint16.tif
new file mode 100644
Binary files /dev/null and b/tests/data/RGBA.uint16.tif differ
diff --git a/tests/test_warpedvrt.py b/tests/test_warpedvrt.py
--- a/tests/test_warpedvrt.py
+++ b/tests/test_warpedvrt.py
@@ -93,24 +93,25 @@ def test_warped_vrt_add_alpha(dsrec, path_rgb_byte_tif):
 
 def test_warped_vrt_msk_add_alpha(path_rgb_msk_byte_tif, caplog):
     """Add an alpha band to the VRT to access per-dataset mask of a source"""
-    with rasterio.open(path_rgb_msk_byte_tif) as src:
-        vrt = WarpedVRT(src, crs=DST_CRS, add_alpha=True)
-        assert vrt.src_nodata is None
-        assert vrt.dst_nodata is None
-        assert vrt.count == 4
-        assert vrt.mask_flag_enums == (
-            [MaskFlags.per_dataset, MaskFlags.alpha],
-        ) * 3 + (
-            [MaskFlags.all_valid],
-        )
+    with rasterio.Env(GDAL_DISABLE_READDIR_ON_OPEN="TRUE"):
+        with rasterio.open(path_rgb_msk_byte_tif) as src:
+            vrt = WarpedVRT(src, crs=DST_CRS, add_alpha=True)
+            assert vrt.src_nodata is None
+            assert vrt.dst_nodata is None
+            assert vrt.count == 4
+            assert vrt.mask_flag_enums == (
+                [MaskFlags.per_dataset, MaskFlags.alpha],
+            ) * 3 + (
+                [MaskFlags.all_valid],
+            )
 
-        caplog.set_level(logging.DEBUG)
-        with rasterio.Env(CPL_DEBUG=True):
-            masks = vrt.read_masks()
-            assert masks[0, 0, 0] == 0
-            assert masks[0].mean() > 0
+            caplog.set_level(logging.DEBUG)
+            with rasterio.Env(CPL_DEBUG=True):
+                masks = vrt.read_masks()
+                assert masks[0, 0, 0] == 0
+                assert masks[0].mean() > 0
 
-        assert "RGB2.byte.tif.msk" in caplog.text
+            assert "RGB2.byte.tif.msk" in caplog.text
 
 
 def test_warped_vrt_msk_nodata(path_rgb_msk_byte_tif, caplog):
@@ -376,18 +377,19 @@ def test_hit_ovr(red_green):
     # GDAL doesn't log overview hits for local files , so we copy the
     # overviews of green.tif over the red overviews and expect to find
     # green pixels below.
-    green_ovr = red_green.join("green.tif.ovr")
-    shutil.move(green_ovr, red_green.join("red.tif.ovr"))
-    assert not green_ovr.exists()
-    with rasterio.open(str(red_green.join("red.tif.ovr"))) as ovr:
-        data = ovr.read()
-        assert (data[1] == 204).all()
-
-    with rasterio.open(str(red_green.join("red.tif"))) as src, WarpedVRT(src) as vrt:
-        data = vrt.read(out_shape=(vrt.count, vrt.height // 2, vrt.width // 2))
-        image = numpy.moveaxis(data, 0, -1)
-        assert image[0, 0, 0] == 17
-        assert image[0, 0, 1] == 204
+    with rasterio.Env(GDAL_DISABLE_READDIR_ON_OPEN="TRUE"):
+        green_ovr = red_green.join("green.tif.ovr")
+        shutil.move(green_ovr, red_green.join("red.tif.ovr"))
+        assert not green_ovr.exists()
+        with rasterio.open(str(red_green.join("red.tif.ovr"))) as ovr:
+            data = ovr.read()
+            assert (data[1] == 204).all()
+
+        with rasterio.open(str(red_green.join("red.tif"))) as src, WarpedVRT(src) as vrt:
+            data = vrt.read(out_shape=(vrt.count, vrt.height // 2, vrt.width // 2))
+            image = numpy.moveaxis(data, 0, -1)
+            assert image[0, 0, 0] == 17
+            assert image[0, 0, 1] == 204
 
 
 def test_warped_vrt_1band_add_alpha():
@@ -666,3 +668,18 @@ def test_warpedvrt_rpcs__width_height():
             assert vrt.dst_transform.almost_equals(
                 affine.Affine(0.008598908695300157, 0.0, -123.48824818566573, 0.0, -0.0041566403046337285, 49.52797830474037)
             )
+
+
+def test_warpedvrt_dst_alpha():
+    """When using using Uint16 data with Alpha band we should keep the original values"""
+    with rasterio.open('tests/data/RGBA.uint16.tif') as src:
+        arr = src.read(1)
+        assert numpy.unique(arr).tolist() == [10000]
+
+        with WarpedVRT(src, add_alpha=False, init_dest=1) as vrt:
+            vrt_arr = vrt.read(1)
+
+            # When using WarpedVRT, the `masked` data will be initialized to the
+            # `init_dest` value (1) so the unique values in the array should be
+            # 1 and 10000 (the original unique value).
+            assert numpy.unique(vrt_arr).tolist() == [1, 10000]