Repository: rasterio/rasterio

Issue:
`rio merge --co TILED=YES` not producing tiled output
Specifically in the case where its inputs are stripped, not tiled, TIFFs. The signature of this bug is a GDAL error like

```
ERROR:GDAL:CPLE_AppDefined in _TIFFVSetField:/private/tmp/combined2.tif: Bad value 600 for "TileWidth" tag
```



Discussion:
@sgillies looks like its probably because `merge` uses [`src.profile`](https://github.com/mapbox/rasterio/blob/master/rasterio/rio/merge.py#L76) (which contains `blockxsize` and `blockysize`) as the template for the output file instead of `src.meta` so you're not getting the default values for `TILED=YES`.

I can knock this one out but won't be able to get to it until Friday or maybe this weekend.  Would be nice to include this in `0.29`, which I'm sure you want to release out soon for the Numpy 1.10 fix.

@geowurster I'm on this one right now as it's a blocker at work and yeah, that's my take too. It'll be a simple fix.

While I'm at it, what would you think about me making a change to the creation_options callback? IMO it would be handy if it lowercased the keys (to standardize) and converted values to standard Python forms. In other words: `"YES"` to `True` and `"256"` to `256`.

@sgillies I jumped on it too before I saw your comment at https://github.com/mapbox/rasterio/tree/merge-use-meta if you didn't get that far yet.

@sgillies Didn't notice the rest of your comment.

Normalizing to lowercase is probably a good idea, although there's nothing stopping someone from doing:

``` python
{
    "TILED": "YES",
    "tiled": "no"
}
```

which GDAL won't complain about, so it might be nice to have a duplicate value check [when they are encoded](https://github.com/mapbox/rasterio/blob/master/rasterio/_io.pyx#L1294-L1308) as well.

As far as normalizing to Python types, that would be nice but I see `SPARSE_OK=TRUE/FALSE` and `TILED=YES/NO`, but are `YES | TRUE / NO | FALSE` interchangeable _everywhere_?  Just tried a translate with `TILED=TRUE` and `TILED=FALSE` and that worked but I don't know about other drivers.


Resolving patch:
diff --git a/rasterio/rio/merge.py b/rasterio/rio/merge.py
--- a/rasterio/rio/merge.py
+++ b/rasterio/rio/merge.py
@@ -73,6 +73,7 @@ def merge(ctx, files, output, driver, bounds, res, nodata, force_overwrite,
     profile['height'] = dest.shape[1]
     profile['width'] = dest.shape[2]
     profile['driver'] = driver
+
     profile.update(**creation_options)
 
     with rasterio.open(output, 'w', **profile) as dst:
diff --git a/rasterio/rio/options.py b/rasterio/rio/options.py
--- a/rasterio/rio/options.py
+++ b/rasterio/rio/options.py
@@ -73,6 +73,8 @@ def _cb_key_val(ctx, param, value):
                 raise click.BadParameter("Invalid syntax for KEY=VAL arg: {}".format(pair))
             else:
                 k, v = pair.split('=', 1)
+                k = k.lower()
+                v = v.lower()
                 out[k] = v
 
         return out


Test patch:
diff --git a/tests/data/shade.tif b/tests/data/shade.tif
Binary files a/tests/data/shade.tif and b/tests/data/shade.tif differ
diff --git a/tests/test_options.py b/tests/test_options.py
--- a/tests/test_options.py
+++ b/tests/test_options.py
@@ -7,7 +7,7 @@ def test_cb_key_val():
 
     pairs = ['KEY=val', '1==']
     expected = {
-        'KEY': 'val',
+        'key': 'val',
         '1': '=',
     }
     assert options._cb_key_val(None, None, pairs) == expected
diff --git a/tests/test_profile.py b/tests/test_profile.py
--- a/tests/test_profile.py
+++ b/tests/test_profile.py
@@ -79,11 +79,26 @@ def test_profile_overlay():
     assert kwds['count'] == 3
 
 
-def test_dataset_profile_property(data):
+def test_dataset_profile_property_tiled(data):
+    """An tiled dataset's profile has block sizes"""
+    with rasterio.open('tests/data/shade.tif') as src:
+        assert src.profile['blockxsize'] == 256
+        assert src.profile['blockysize'] == 256
+        assert src.profile['tiled'] == True
+
+
+def test_dataset_profile_property_untiled(data):
+    """An untiled dataset's profile has no block sizes"""
+    with rasterio.open('tests/data/RGB.byte.tif') as src:
+        assert 'blockxsize' not in src.profile
+        assert 'blockysize' not in src.profile
+        assert src.profile['tiled'] == False
+
+
+def test_dataset_profile_creation_kwds(data):
+    """Updated creation keyword tags appear in profile"""
     tiffile = str(data.join('RGB.byte.tif'))
     with rasterio.open(tiffile, 'r+') as src:
         src.update_tags(ns='rio_creation_kwds', foo='bar')
-        assert src.profile['blockxsize'] == 791
-        assert src.profile['blockysize'] == 3
         assert src.profile['tiled'] == False
         assert src.profile['foo'] == 'bar'