This is an automated email from the git hooks/post-receive script.

johanvdw-guest pushed a commit to branch master
in repository rasterio.

commit c7657eac83517c7231c1c0671151a721860c8060
Author: Johan Van de Wauw <jo...@vandewauw.be>
Date:   Tue Sep 15 21:51:05 2015 +0200

    Revert "Revert "Merge tag 'upstream/0.26.0'""
    
    This reverts commit 50c4ae398d5f92a8fc6c80e0e109df4103b0cb6c.
---
 .gitignore               |  76 +++++++++++++++++++++++++++
 .travis.yml              |  20 +++++--
 AUTHORS.txt              |   3 +-
 CHANGES.txt              |  18 +++++++
 README.rst               |  45 +++++++++++++++-
 docs/cli.rst             | 133 ++++++++++++++++++++++++++++++++---------------
 docs/reproject.rst       |  64 +++++++++++++++++++++--
 examples/polygonize.py   |  10 ++--
 rasterio/__init__.py     |   2 +-
 rasterio/_base.pyx       |  35 ++++++++++++-
 rasterio/_features.pyx   |  10 ++--
 rasterio/_fill.pyx       |   4 +-
 rasterio/_gdal.pxd       |   2 +-
 rasterio/_io.pyx         |   8 +--
 rasterio/_warp.pyx       |   8 +--
 rasterio/dtypes.py       |   6 +++
 rasterio/enums.py        |   2 +-
 rasterio/rio/bands.py    |  15 +-----
 rasterio/rio/convert.py  |   6 ++-
 rasterio/rio/info.py     |   6 +++
 rasterio/rio/main.py     |   8 +--
 rasterio/rio/options.py  |   8 ++-
 rasterio/rio/overview.py |   6 +--
 requirements-dev.txt     |   3 +-
 setup.py                 |   3 +-
 tests/test_checksum.py   |  45 ++++++++++++++++
 tests/test_colormap.py   |  14 +++--
 tests/test_dtypes.py     |  21 +++++---
 tests/test_overviews.py  |  10 ++++
 tests/test_rio_bands.py  |   6 +--
 tests/test_rio_info.py   |  16 ++++++
 31 files changed, 496 insertions(+), 117 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0b87ebd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,76 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# IDE's etc.
+.idea/
+venv/
+venv2/
+
+# rasterio
+test.tif
+gdal-config.txt
+VERSION.txt
+rasterio/_fill.cpp
+rasterio/_warp.cpp
+rasterio/_base.c
+rasterio/_copy.c
+rasterio/_drivers.c
+rasterio/_err.c
+rasterio/_example.c
+rasterio/_features.c
+rasterio/_io.c
diff --git a/.travis.yml b/.travis.yml
index 440f792..bbf5cc5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,12 +8,22 @@ before_install:
   - sudo apt-get update -qq
   - sudo apt-get install -y libgdal1h gdal-bin libgdal-dev
 install:
-  - pip install --install-option="--no-cython-compile" cython
-  - "pip install -r requirements-dev.txt"
-  - "pip install pytest pytest-cov"
-  - "pip install coveralls"
-  - "pip install -e ."
+  - pip install --install-option="--no-cython-compile" cython==0.22
+  - pip install -r requirements-dev.txt
+  - pip install -e .
 script: 
   - py.test --cov rasterio --cov-report term-missing
 after_success:
   - coveralls
+before_deploy:
+  - pip wheel --wheel-dir=/tmp/wheelhouse -r requirements-dev.txt
+  - pip wheel --wheel-dir=/tmp/wheelhouse -r requirements.txt
+  - pip wheel --wheel-dir=/tmp/wheelhouse .
+  - tar -C /tmp -czvf rasterio-travis-wheels-$TRAVIS_PYTHON_VERSION.tar.gz 
wheelhouse
+deploy:
+  provider: releases
+  api_key:
+    secure: 
uP/hy8LRdDnN6XHSLChmKYdW9CdIy8pqvUyXFPgTDY/mlItMUdDNdP95bitzn/rNNXnOkCGsARqzRCLeGI3jB0nEGuAzY6fGWYt2igjfMOhpdDG6o3LcaoP4mITuFfe5/kCQeUb8WB3QK6c2cL7nEEPzoSniqZQ6MsxHIvUW7ts=
+  file: rasterio-travis-wheels-$TRAVIS_PYTHON_VERSION.tar.gz
+  on:
+    tags: true
diff --git a/AUTHORS.txt b/AUTHORS.txt
index 481e0ea..5050878 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -16,9 +16,10 @@ Johan Van de Wauw <johan.vandew...@gmail.com>
 James Seppi <james.se...@gmail.com>
 Jacques Tardie <h...@jacquestardie.org>
 Etienne B. Racine <etienn...@gmail.com>
-cgohlke <cgoh...@uci.edu>
+Christoph Gohlke <cgoh...@uci.edu>
 Martijn Visser <mgvis...@gmail.com>
 Aldo Culquicondor <alculquicon...@gmail.com>
 Robin Wilson <ro...@rtwilson.com>
+Patrick Young <patrick.yo...@digitalglobe.com>
 
 See also https://github.com/mapbox/rasterio/graphs/contributors.
diff --git a/CHANGES.txt b/CHANGES.txt
index b5c549d..96ee33a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,24 @@
 Changes
 =======
 
+0.26.0 (2015-08-11)
+-------------------
+- Add dependency on click-plugins, a new project that takes over the plugin
+  duties formerly assigned to cligj (#426).
+- Change rio-stack's --photometric=RGB option to --rgb (#429). Other 
+  photometric interpretations should be assigned using the --co option 
+  added in 0.25.0.
+- Allow for ndarray-like objects (like xray arrays), not just numpy arrays,
+  in warp() and elsewhere (#436).
+- Add --rgb flag to rio-convert (#439).
+- Fixed resampling algorithm enumeration bug (#441).
+- Colormap handling was made too strict in 0.24.1 and has been made more
+  forgiving. Callers are now warned when alpha values will be ignored instead
+  of receiving exceptions (#444).
+- Add a .gitignore (#445). Better late than never!
+- Add a checksum() method to base dataset class and checksums to output of
+  rio-info (#449).
+
 0.25.0 (2015-07-17)
 -------------------
 - New rio-warp command (#264, #404).
diff --git a/README.rst b/README.rst
index a113f1e..51ddcc0 100644
--- a/README.rst
+++ b/README.rst
@@ -149,6 +149,18 @@ using Python.
     >>> b.min(), b.max(), b.mean()
     (1, 255, 44.434478650699106)
 
+Rio Plugins
+-----------
+
+Rio provides the ability to create additional subcommands using plugins.  See
+`cli.rst 
<https://github.com/mapbox/rasterio/blob/master/docs/cli.rst#rio-plugins>`__
+for more information on building plugins.
+
+See the
+`plugin registry 
<https://github.com/mapbox/rasterio/wiki/Rio-plugin-registry>`__
+for a list of available plugins.
+
+
 Installation
 ============
 
@@ -271,12 +283,43 @@ From the repo directory, run py.test
 
     $ py.test
 
-
 Note: some tests do not succeed on Windows (see
 `#66
 <https://github.com/mapbox/rasterio/issues/66>`__.).
 
 
+Downstream testing
+------------------
+
+If your project depends on Rasterio and uses Travis-CI, you can speed up your
+builds by fetching Rasterio and its dependencies as a set of wheels from 
+GitHub as done in `rio-plugin-example 
+<https://github.com/sgillies/rio-plugin-example/blob/master/.travis.yml>`__.
+
+.. code-block:: yaml
+
+    language: python
+    env:
+      - RASTERIO_VERSION=0.26
+    python:
+      - "2.7"
+      - "3.4"
+    cache:
+      directories:
+        - $HOME/.pip-cache/
+        - $HOME/wheelhouse
+    before_install:
+      - sudo add-apt-repository -y ppa:ubuntugis/ppa
+      - sudo apt-get update -qq
+      - sudo apt-get install -y libgdal1h gdal-bin
+      - curl -L 
https://github.com/mapbox/rasterio/releases/download/$RASTERIO_VERSION/rasterio-travis-wheels-$TRAVIS_PYTHON_VERSION.tar.gz
 > /tmp/wheelhouse.tar.gz
+      - tar -xzvf /tmp/wheelhouse.tar.gz -C $HOME
+    install:
+      - pip install --use-wheel --find-links=$HOME/wheelhouse -e .[test] 
--cache-dir $HOME/.pip-cache
+    script: 
+      - py.test
+
+
 Documentation
 -------------
 
diff --git a/docs/cli.rst b/docs/cli.rst
index 8db75d5..56f560c 100644
--- a/docs/cli.rst
+++ b/docs/cli.rst
@@ -39,12 +39,30 @@ It is developed using `Click <http://click.pocoo.org/>`__.
 Commands are shown below. See ``--help`` of individual commands for more
 details.
 
+creation options
+----------------
+
+For commands that create new datasets, format specific creation options may
+also be passed using ``--co``. For example, to tile a new GeoTIFF output file,
+add the following.
+
+.. code-block:: console
+
+    --co tiled=true --co blockxsize=256 --co blockysize=256
+
+To compress it using the LZW method, add
+
+.. code-block:: console
+
+    --co compress=LZW
+
+
 bounds
 ------
 
-New in 0.10.
+Added in 0.10.
 
-The bounds command writes the bounding boxes of raster datasets to GeoJSON for
+The ``bounds`` command writes the bounding boxes of raster datasets to GeoJSON 
for
 use with, e.g., `geojsonio-cli <https://github.com/mapbox/geojsonio-cli>`__.
 
 .. code-block:: console
@@ -93,10 +111,13 @@ use with, e.g., `geojsonio-cli 
<https://github.com/mapbox/geojsonio-cli>`__.
 Shoot the GeoJSON into a Leaflet map using geojsonio-cli by typing 
 ``rio bounds tests/data/RGB.byte.tif | geojsonio``.
 
+
 calc
 ----
 
-The calc command reads files as arrays, evaluates lisp-like expressions in
+Added in 0.19
+
+The ``calc`` command reads files as arrays, evaluates lisp-like expressions in
 their context, and writes the result as a new file. Members of the numpy
 module and arithmetic and logical operators are available builtin functions
 and operators. It is intended for simple calculations; any calculations
@@ -139,10 +160,10 @@ Please see `calc.rst <calc.rst>`__ for more details.
 convert
 -------
 
-New in 0.25
+Added in 0.25
 
-Like ``gdal_translate``, rio-convert copies and converts raster datasets to
-other data types and formats. 
+The ``convert`` command copies and converts raster datasets to other data types
+and formats (similar to ``gdal_translate``).
 
 Data values may be linearly scaled when copying by using the ``--scale-ratio``
 and ``--scale-offset`` options. Destination raster values are calculated as
@@ -158,25 +179,15 @@ as uint8:
 
     $ rio convert in16.tif out8.tif --dtype uint8 --scale-ratio 0.0625
 
-Format specific creation options may also be passed using --co. To tile a
-new GeoTIFF output file, add the following.
-
-.. code-block:: console
-
-    --co tiled=true --co blockxsize=256 --co blockysize=256
+You can use `--rgb` as shorthand for `--co photometric=rgb`.
 
-To compress it using the LZW method, add
-
-.. code-block:: console
-
-    --co compress=LZW
 
 edit-info
 ---------
 
-New in 0.24
+Added in 0.24
 
-The edit-info command allows you edit a raster dataset's metadata, namely
+The ``edit-info`` command allows you edit a raster dataset's metadata, namely
 
 - coordinate reference system
 - affine transformation matrix
@@ -186,8 +197,8 @@ The edit-info command allows you edit a raster dataset's 
metadata, namely
 A TIFF created by spatially-unaware image processing software like Photoshop
 or Imagemagick can be turned into a GeoTIFF by editing these metadata items.
 
-You can set or change a dataset's coordinate reference system to, e.g., 
-EPSG:3857 (Web Mercator),
+For example, you can set or change a dataset's coordinate reference system to
+Web Mercator (EPSG:3857),
 
 .. code-block:: console
 
@@ -209,9 +220,9 @@ or set its nodata value to, e.g., `0`:
 mask
 ----
 
-New in 0.21
+Added in 0.21
 
-The mask command masks in pixels from all bands of a raster using features
+The ``mask`` command masks in pixels from all bands of a raster using features
 (masking out all areas not covered by features) and optionally crops the output
 raster to the extent of the features.  Features are assumed to be in the same
 coordinate reference system as the input raster.
@@ -240,7 +251,9 @@ keep pixels not covered by features.
 info
 ----
 
-Rio's info command prints structured information about a dataset.
+Added in 0.13
+
+The ``info`` command prints structured information about a dataset.
 
 .. code-block:: console
 
@@ -273,7 +286,7 @@ Rio's info command prints structured information about a 
dataset.
       "nodata": 0.0
     }
 
-More information, such as band statistics, can be had using the `--verbose`
+More information, such as band statistics, can be had using the ``--verbose``
 option.
 
 .. code-block:: console
@@ -324,10 +337,11 @@ option.
       "nodata": 0.0
     }
 
+
 insp
 ----
 
-The insp command opens a dataset and an interpreter.
+The ``insp`` command opens a dataset and an interpreter.
 
 .. code-block:: console
 
@@ -339,36 +353,40 @@ The insp command opens a dataset and an interpreter.
     >>> print src.bounds
     BoundingBox(left=101985.0, bottom=2611485.0, right=339315.0, top=2826915.0)
 
+
 merge
 -----
 
-The merge command can be used to flatten a stack of identically structured
+Added in 0.12.1
+
+The ``merge`` command can be used to flatten a stack of identically structured
 datasets.
 
 .. code-block:: console
 
     $ rio merge rasterio/tests/data/R*.tif merged.tif
 
+
 overview
 --------
 
 New in 0.25
 
-A pyramid of overviews computed once and stored in the dataset using
-rio-overview can improve performance in some applications.
+The ``overview`` command creates overviews stored in the dataset, which can
+improve performance in some applications.
 
 The decimation levels at which to build overviews can be specified as a
 comma separated list
 
 .. code-block:: console
 
-    $ rio pyramid --build 2,4,8,16
+    $ rio overview --build 2,4,8,16
 
 or a base and range of exponents.
 
 .. code-block:: console
 
-    $ rio pyramid --build 2^1..4
+    $ rio overview --build 2^1..4
 
 Note that overviews can not currently be removed and are not automatically
 updated when the dataset's primary bands are modified.
@@ -377,14 +395,15 @@ Information about existing overviews can be printed using 
the --ls option.
 
 .. code-block:: console
 
-    $ rio pyramid --ls
+    $ rio overview --ls
+
 
 rasterize
 ---------
 
 New in 0.18.
 
-The rasterize command rasterizes GeoJSON features into a new or existing
+The ``rasterize`` command rasterizes GeoJSON features into a new or existing
 raster.
 
 .. code-block:: console
@@ -425,6 +444,7 @@ Other options are available, see:
 
     $ rio rasterize --help
 
+
 sample
 ------
 
@@ -442,13 +462,14 @@ values at that position to stdout.
 
 The output of the transform command (see below) makes good input for sample.
 
+
 shapes
 ------
 
 New in 0.11.
 
-The shapes command extracts and writes features of a specified dataset band out
-as GeoJSON.
+The ``shapes`` command extracts and writes features of a specified dataset band
+out as GeoJSON.
 
 .. code-block:: console
 
@@ -465,15 +486,16 @@ data region.
 
 See http://bl.ocks.org/anonymous/raw/ef244954b719dba97926/.
 
+
 stack
 -----
 
 New in 0.15.
 
-The rio-stack command stack a number of bands from one or more input files into
-a multiband dataset. Input datasets must be of a kind: same data type,
+The ``stack`` command stacks a number of bands from one or more input files
+into a multiband dataset. Input datasets must be of a kind: same data type,
 dimensions, etc. The output is cloned from the first input. By default,
-rio-stack will take all bands from each input and write them in same order to
+``stack`` will take all bands from each input and write them in same order to
 the output. Optionally, bands for each input may be specified using a simple
 syntax:
 
@@ -492,12 +514,15 @@ Examples using the Rasterio testing dataset that produce 
a copy of it.
     $ rio stack RGB.byte.tif --bidx 1..3 stacked.tif
     $ rio stack RGB.byte.tif --bidx ..2 RGB.byte.tif --bidx 3.. stacked.tif
 
+You can use `--rgb` as shorthand for `--co photometric=rgb`.
+
+
 transform
 ---------
 
 New in 0.10.
 
-The transform command reads a JSON array of coordinates, interleaved, and
+The ``transform`` command reads a JSON array of coordinates, interleaved, and
 writes another array of transformed coordinates to stdout.
 
 To transform a longitude, latitude point (EPSG:4326 is the default) to 
@@ -523,11 +548,10 @@ warp
 
 New in 0.25
 
-The warp command warps (reprojects) a raster based on parameters that can be
+The ``warp`` command warps (reprojects) a raster based on parameters that can 
be
 obtained from a template raster, or input directly.  The output is always
 overwritten.
 
-
 To copy coordinate reference system, transform, and dimensions from a template
 raster, do the following:
 
@@ -565,4 +589,31 @@ Other options are available, see:
     $ rio warp --help
 
 
+Rio Plugins
+-----------
+
+Rio uses ``click-plugins`` to provide the ability to create additional
+subcommands using plugins developed outside rasterio.  This is ideal for
+commands that require additional dependencies beyond those used by rasterio, or
+that provide functionality beyond the intended scope of rasterio.
+
+For example, `rio-mbtiles <https://github.com/mapbox/rio-mbtiles>`__ provides
+a command ``rio mbtiles`` to export a raster to an MBTiles file.
+
+See `click-plugins <https://github.com/click-contrib/click-plugins>`__ for more
+information on how to build these plugins in general.
+
+In order to use these plugins with rio, add the commands to the
+``rasterio.rio_plugins'`` entry point in your ``setup.py`` file, as described
+`here <https://github.com/click-contrib/click-plugins#developing-plugins>`__
+
+See the
+`plugin registry 
<https://github.com/mapbox/rasterio/wiki/Rio-plugin-registry>`__
+for a list of available plugins.
+
+
+
+Other commands?
+---------------
+
 Suggestions for other commands are welcome!
diff --git a/docs/reproject.rst b/docs/reproject.rst
index 0b467f4..906a60c 100644
--- a/docs/reproject.rst
+++ b/docs/reproject.rst
@@ -54,16 +54,70 @@ transform.
         assert not destination.all()
 
 
-See `examples/reproject.py 
<https://github.com/mapbox/rasterio/blob/master/examples/reproject.py>`__ for 
code that writes the destination array to a GeoTIFF file. I've 
-uploaded the resulting file to a Mapbox map to demonstrate that the 
reprojection is
+See `examples/reproject.py 
<https://github.com/mapbox/rasterio/blob/master/examples/reproject.py>`__
+for code that writes the destination array to a GeoTIFF file. I've uploaded the
+resulting file to a Mapbox map to demonstrate that the reprojection is
 correct: 
https://a.tiles.mapbox.com/v3/sgillies.hfek2oko/page.html?secure=1#6/0.000/0.033.
 
 Reprojecting a GeoTIFF dataset
 ------------------------------
 
-Here's a more real-world example of using ``reproject()`` to make an output 
dataset zoomed out by a factor of 2.
-Methods of the ``rasterio.Affine`` class help us generate the output dataset's 
transform matrix and, thereby, its
-spatial extent. 
+Reprojecting a GeoTIFF dataset from one coordinate reference system is a common
+use case.  Rasterio provides a few utilities to make this even easier:
+
+``transform_bounds()``
+transforms the bounding coordinates of the source raster to the target
+coordinate reference system, densifiying points along the edges to account
+for non-linear transformations of the edges.
+
+
+``calculate_default_transform()``
+transforms bounds to target coordinate system, calculates resolution if not
+provided, and returns destination transform and dimensions.
+
+
+.. code-block:: python
+
+    import numpy
+    import rasterio
+    from rasterio.warp import calculate_default_transform, reproject, 
RESAMPLING
+
+    dst_crs = 'EPSG:4326'
+
+    with rasterio.open('rasterio/tests/data/RGB.byte.tif') as src:
+        affine, width, height = calculate_default_transform(
+            src.crs, dst_crs, src.width, src.height, *src.bounds)
+        kwargs = src.meta.copy()
+        kwargs.update({
+            'crs': dst_crs,
+            'transform': affine,
+            'affine': affine,
+            'width': width,
+            'height': height
+        })
+
+        with rasterio.open('/tmp/RGB.byte.wgs84.tif', 'w', **kwargs) as dst:
+            for i in range(1, src.count + 1):
+                reproject(
+                    source=rasterio.band(src, i),
+                    destination=rasterio.band(dst, i),
+                    src_transform=src.affine,
+                    src_crs=src.crs,
+                    dst_transform=affine,
+                    dst_crs=dst_crs,
+                    resampling=RESAMPLING.nearest)
+
+
+See ``rasterio/rio/warp.py`` for more complex examples of reprojection based on
+new bounds, dimensions, and resolution (as well as a command-line interface
+described
+`here <https://github.com/mapbox/rasterio/blob/master/docs/cli.rst#warp>`__).
+
+
+
+It is also possible to use ``reproject()`` to create an output dataset zoomed
+out by a factor of 2.  Methods of the ``rasterio.Affine`` class help us 
generate
+the output dataset's transform matrix and, thereby, its spatial extent.
 
 .. code-block:: python
 
diff --git a/examples/polygonize.py b/examples/polygonize.py
index ae6e000..e21a97d 100644
--- a/examples/polygonize.py
+++ b/examples/polygonize.py
@@ -1,10 +1,12 @@
 import pprint
 
 import rasterio
-import rasterio._features as ftrz
+from rasterio.features import shapes
 
-with rasterio.open('box.png') as src:
-    image = src.read_band(1)
+with rasterio.open('tests/data/shade.tif') as src:
+    image = src.read(1)
 
+# Print the first two shapes...
 pprint.pprint(
-    list(ftrz.polygonize(image)))
+    list(shapes(image))[:2]
+)
diff --git a/rasterio/__init__.py b/rasterio/__init__.py
index e03e1bf..7cf55cf 100644
--- a/rasterio/__init__.py
+++ b/rasterio/__init__.py
@@ -23,7 +23,7 @@ from rasterio import _err, coords, enums
 
 __all__ = [
     'band', 'open', 'drivers', 'copy', 'pad']
-__version__ = "0.25.0"
+__version__ = "0.26.0"
 
 log = logging.getLogger('rasterio')
 class NullHandler(logging.Handler):
diff --git a/rasterio/_base.pyx b/rasterio/_base.pyx
index b514845..caf5e85 100644
--- a/rasterio/_base.pyx
+++ b/rasterio/_base.pyx
@@ -598,7 +598,6 @@ cdef class DatasetReader(object):
     def kwds(self):
         return self.tags(ns='rio_creation_kwds')
 
-
     # Overviews.
     def overviews(self, bidx):
         cdef void *hovband = NULL
@@ -612,6 +611,40 @@ cdef class DatasetReader(object):
             factors.append(int(round(float(self.width)/float(xsize))))
         return factors
 
+    def checksum(self, bidx, window=None):
+        """Compute an integer checksum for the stored band
+
+        Parameters
+        ----------
+        bidx : int
+            The band's index (1-indexed).
+        window: tuple, optional
+            A window of the band. Default is the entire extent of the band.
+
+        Returns
+        -------
+        An int.
+        """
+        cdef void *hband = NULL
+        cdef int xoff, yoff, width, height
+        if self._hds == NULL:
+            raise ValueError("can't read closed raster file")
+        hband = _gdal.GDALGetRasterBand(self._hds, bidx)
+        if hband == NULL:
+            raise ValueError("NULL band")
+        if not window:
+            xoff = yoff = 0
+            width, height = self.width, self.height
+        else:
+            window = eval_window(window, self.height, self.width)
+            window = crop_window(window, self.height, self.width)
+            xoff = window[1][0]
+            width = window[1][1] - xoff
+            yoff = window[0][0]
+            height = window[0][1] - yoff
+        return _gdal.GDALChecksumImage(hband, xoff, yoff, width, height)
+
+
 # Window utils
 # A window is a 2D ndarray indexer in the form of a tuple:
 # ((row_start, row_stop), (col_start, col_stop))
diff --git a/rasterio/_features.pyx b/rasterio/_features.pyx
index bc83a65..0289303 100644
--- a/rasterio/_features.pyx
+++ b/rasterio/_features.pyx
@@ -67,7 +67,7 @@ def _shapes(image, mask, connectivity, transform):
     if is_float:
         fieldtp = 2
 
-    if isinstance(image, np.ndarray):
+    if dtypes.is_ndarray(image):
         mem_ds = InMemoryRaster(image, transform)
         hband = mem_ds.band
     elif isinstance(image, tuple):
@@ -76,7 +76,7 @@ def _shapes(image, mask, connectivity, transform):
     else:
         raise ValueError("Invalid source image")
 
-    if isinstance(mask, np.ndarray):
+    if dtypes.is_ndarray(mask):
         # A boolean mask must be converted to uint8 for GDAL
         mask_ds = InMemoryRaster(mask.astype('uint8'), transform)
         hmaskband = mask_ds.band
@@ -168,7 +168,7 @@ def _sieve(image, size, output, mask, connectivity):
     cdef _io.RasterUpdater udr
     cdef _io.RasterReader mask_reader
 
-    if isinstance(image, np.ndarray):
+    if dtypes.is_ndarray(image):
         in_mem_ds = InMemoryRaster(image)
         in_band = in_mem_ds.band
     elif isinstance(image, tuple):
@@ -177,7 +177,7 @@ def _sieve(image, size, output, mask, connectivity):
     else:
         raise ValueError("Invalid source image")
 
-    if isinstance(output, np.ndarray):
+    if dtypes.is_ndarray(output):
         log.debug("Output array: %r", output)
         out_mem_ds = InMemoryRaster(output)
         out_band = out_mem_ds.band
@@ -187,7 +187,7 @@ def _sieve(image, size, output, mask, connectivity):
     else:
         raise ValueError("Invalid output image")
 
-    if isinstance(mask, np.ndarray):
+    if dtypes.is_ndarray(mask):
         # A boolean mask must be converted to uint8 for GDAL
         mask_mem_ds = InMemoryRaster(mask.astype('uint8'))
         mask_band = mask_mem_ds.band
diff --git a/rasterio/_fill.pyx b/rasterio/_fill.pyx
index 2515564..723af0a 100644
--- a/rasterio/_fill.pyx
+++ b/rasterio/_fill.pyx
@@ -23,7 +23,7 @@ def _fillnodata(image, mask, double max_search_distance=100.0,
     cdef _io.RasterReader mrdr
     cdef char **alg_options = NULL
 
-    if isinstance(image, np.ndarray):
+    if dtypes.is_ndarray(image):
         # copy numpy ndarray into an in-memory dataset.
         image_dataset = _gdal.GDALCreate(
             memdriver,
@@ -38,7 +38,7 @@ def _fillnodata(image, mask, double max_search_distance=100.0,
     else:
         raise ValueError("Invalid source image")
 
-    if isinstance(mask, np.ndarray):
+    if dtypes.is_ndarray(mask):
         mask_cast = mask.astype('uint8')
         mask_dataset = _gdal.GDALCreate(
             memdriver,
diff --git a/rasterio/_gdal.pxd b/rasterio/_gdal.pxd
index a4b4154..75b937c 100644
--- a/rasterio/_gdal.pxd
+++ b/rasterio/_gdal.pxd
@@ -232,4 +232,4 @@ cdef extern from "gdal_alg.h":
     void GDALDestroyApproxTransformer( void * )
 
     int GDALFillNodata(void *dst_band, void *mask_band, double 
max_search_distance, int deprecated, int smoothing_iterations, char **options, 
void *progress_func, void *progress_data)
-
+    int GDALChecksumImage(void *band, int xoff, int yoff, int width, int 
height)
diff --git a/rasterio/_io.pyx b/rasterio/_io.pyx
index b1bb71b..c317678 100644
--- a/rasterio/_io.pyx
+++ b/rasterio/_io.pyx
@@ -1136,7 +1136,7 @@ cdef class RasterReader(_base.DatasetReader):
             stacklevel=2)
 
         if self._hds == NULL:
-            raise ValueError("can't write closed raster file")
+            raise ValueError("can't read closed raster file")
         hband = _gdal.GDALGetRasterBand(self._hds, 1)
         if hband == NULL:
             raise ValueError("NULL band mask")
@@ -1684,9 +1684,9 @@ cdef class RasterUpdater(RasterReader):
         for i, rgba in colormap.items():
 
             if len(rgba) == 4 and self.driver in ('GTiff'):
-                raise ValueError(
-                    "Format '%s' doesn't support 4 component colormap entries"
-                    % self.driver)
+                warnings.warn(
+                    "This format doesn't support alpha in colormap entries. "
+                    "The value will be ignored.")
 
             elif len(rgba) == 3:
                 rgba = tuple(rgba) + (255,)
diff --git a/rasterio/_warp.pyx b/rasterio/_warp.pyx
index 1e267af..7d4e4f4 100644
--- a/rasterio/_warp.pyx
+++ b/rasterio/_warp.pyx
@@ -246,7 +246,7 @@ def _reproject(
     # If the source is an ndarray, we copy to a MEM dataset.
     # We need a src_transform and src_dst in this case. These will
     # be copied to the MEM dataset.
-    if isinstance(source, np.ndarray):
+    if dtypes.is_ndarray(source):
         # Convert 2D single-band arrays to 3D multi-band.
         if len(source.shape) == 2:
             source = source.reshape(1, *source.shape)
@@ -300,7 +300,7 @@ def _reproject(
         raise ValueError("Invalid source")
     
     # Next, do the same for the destination raster.
-    if isinstance(destination, np.ndarray):
+    if dtypes.is_ndarray(destination):
         if len(destination.shape) == 2:
             destination = destination.reshape(1, *destination.shape)
         if destination.shape[0] != src_count:
@@ -489,11 +489,11 @@ def _reproject(
         #    _gdal.GDALDestroyApproxTransformer(psWOptions.pTransformerArg)
         if psWOptions != NULL:
             _gdal.GDALDestroyWarpOptions(psWOptions)
-        if isinstance(source, np.ndarray):
+        if dtypes.is_ndarray(source):
             if hdsin != NULL:
                 _gdal.GDALClose(hdsin)
 
-    if reprojected and isinstance(destination, np.ndarray):
+    if reprojected and dtypes.is_ndarray(destination):
         retval = _io.io_auto(destination, hdsout, 0)
         # TODO: handle errors (by retval).
 
diff --git a/rasterio/dtypes.py b/rasterio/dtypes.py
index e08f14e..449ec5f 100644
--- a/rasterio/dtypes.py
+++ b/rasterio/dtypes.py
@@ -96,3 +96,9 @@ def get_minimum_int_dtype(values):
         return int16
     elif min_value >= -2147483648 and max_value <= 2147483647:
         return int32
+
+
+def is_ndarray(array):
+    import numpy
+
+    return isinstance(array, numpy.ndarray) or hasattr(array, '__array__')
diff --git a/rasterio/enums.py b/rasterio/enums.py
index 669538e..d33f71d 100644
--- a/rasterio/enums.py
+++ b/rasterio/enums.py
@@ -24,7 +24,7 @@ class Resampling(Enum):
     nearest='NEAREST'
     gauss='GAUSS'
     cubic='CUBIC'
-    average='AVERAGE',
+    average='AVERAGE'
     mode='MODE'
     average_magphase='AVERAGE_MAGPHASE'
     none='NONE'
diff --git a/rasterio/rio/bands.py b/rasterio/rio/bands.py
index 09b9c16..f692644 100644
--- a/rasterio/rio/bands.py
+++ b/rasterio/rio/bands.py
@@ -9,26 +9,13 @@ import rasterio
 from rasterio.five import zip_longest
 
 
-PHOTOMETRIC_CHOICES = [val.lower() for val in [
-    'MINISBLACK',
-    'MINISWHITE',
-    'RGB',
-    'CMYK',
-    'YCBCR',
-    'CIELAB',
-    'ICCLAB',
-    'ITULAB']]
-
-
 # Stack command.
 @click.command(short_help="Stack a number of bands into a multiband dataset.")
 @files_inout_arg
 @options.output_opt
 @format_opt
 @options.bidx_mult_opt
-@click.option('--photometric', default=None,
-              type=click.Choice(PHOTOMETRIC_CHOICES),
-              help="Photometric interpretation")
+@options.rgb_opt
 @options.creation_options
 @click.pass_context
 def stack(ctx, files, output, driver, bidx, photometric, creation_options):
diff --git a/rasterio/rio/convert.py b/rasterio/rio/convert.py
index 37fea24..3443b51 100644
--- a/rasterio/rio/convert.py
+++ b/rasterio/rio/convert.py
@@ -29,11 +29,12 @@ warnings.simplefilter('default')
               help="Source to destination scaling ratio.")
 @click.option('--scale-offset', type=float, default=None,
               help="Source to destination scaling offset.")
+@options.rgb_opt
 @options.creation_options
 @click.pass_context
 def convert(
         ctx, files, output, driver, dtype, scale_ratio, scale_offset,
-        creation_options):
+        photometric, creation_options):
     """Copy and convert raster datasets to other data types and formats.
 
     Data values may be linearly scaled when copying by using the
@@ -81,6 +82,9 @@ def convert(
                 profile['dtype'] = dtype
             dst_dtype = profile['dtype']
 
+            if photometric:
+                creation_options['photometric'] = photometric
+
             profile.update(**creation_options)
 
             with rasterio.open(outputfile, 'w', **profile) as dst:
diff --git a/rasterio/rio/info.py b/rasterio/rio/info.py
index f6e1890..d86d014 100644
--- a/rasterio/rio/info.py
+++ b/rasterio/rio/info.py
@@ -257,6 +257,9 @@ def env(ctx, key):
 @click.option('--stats', 'meta_member', flag_value='stats',
               help="Print statistics (min, max, mean) of a single band "
                    "(use --bidx).")
+@click.option('--checksum', 'meta_member', flag_value='checksum',
+              help="Print integer checksum of a single band "
+                   "(use --bidx).")
 @click.option('-v', '--tell-me-more', '--verbose', is_flag=True,
               help="Output extra information.")
 @options.bidx_opt
@@ -292,6 +295,7 @@ def info(ctx, input, aspect, indent, namespace, 
meta_member, verbose, bidx,
                               'mean': float(b.mean())
                               } for b in src.read(masked=masked)]
                     info['stats'] = stats
+                    info['checksum'] = [src.checksum(i) for i in src.indexes]
                 if aspect == 'meta':
                     if meta_member == 'stats':
                         band = src.read(bidx, masked=masked)
@@ -299,6 +303,8 @@ def info(ctx, input, aspect, indent, namespace, 
meta_member, verbose, bidx,
                             float(band.min()),
                             float(band.max()),
                             float(band.mean())))
+                    elif meta_member == 'checksum':
+                        click.echo(str(src.checksum(bidx)))
                     elif meta_member:
                         if isinstance(info[meta_member], (list, tuple)):
                             click.echo(" ".join(map(str, info[meta_member])))
diff --git a/rasterio/rio/main.py b/rasterio/rio/main.py
index 2732654..2282ae5 100644
--- a/rasterio/rio/main.py
+++ b/rasterio/rio/main.py
@@ -8,8 +8,8 @@ from pkg_resources import iter_entry_points
 import sys
 
 import click
+from click_plugins import with_plugins
 import cligj
-import cligj.plugins
 
 import rasterio
 
@@ -19,9 +19,9 @@ def configure_logging(verbosity):
     logging.basicConfig(stream=sys.stderr, level=log_level)
 
 
-@cligj.plugins.group(plugins=(
-        ep for ep in list(iter_entry_points('rasterio.rio_commands')) +
-                     list(iter_entry_points('rasterio.rio_plugins'))))
+@with_plugins(ep for ep in list(iter_entry_points('rasterio.rio_commands')) +
+              list(iter_entry_points('rasterio.rio_plugins')))
+@click.group()
 @cligj.verbose_opt
 @cligj.quiet_opt
 @click.version_option(version=rasterio.__version__, message='%(version)s')
diff --git a/rasterio/rio/options.py b/rasterio/rio/options.py
index 1bd6521..0e5aeb8 100644
--- a/rasterio/rio/options.py
+++ b/rasterio/rio/options.py
@@ -153,4 +153,10 @@ creation_options = click.option(
     callback=_cb_key_val,
     help="Driver specific creation options."
          "See the documentation for the selected output driver for "
-         "more information.")
\ No newline at end of file
+         "more information.")
+
+rgb_opt = click.option(
+    '--rgb', 'photometric', 
+    flag_value='rgb',
+    default=False,
+    help="Set RGB photometric interpretation")
diff --git a/rasterio/rio/overview.py b/rasterio/rio/overview.py
index 1c7892c..231e2d0 100644
--- a/rasterio/rio/overview.py
+++ b/rasterio/rio/overview.py
@@ -50,11 +50,11 @@ def overview(ctx, input, build, ls, rebuild, resampling):
     The decimation levels at which to build overviews can be specified as
     a comma separated list
 
-      rio pyramid --build 2,4,8,16
+      rio overview --build 2,4,8,16
 
     or a base and range of exponents.
 
-      rio pyramid --build 2^1..4
+      rio overview --build 2^1..4
 
     Note that overviews can not currently be removed and are not 
     automatically updated when the dataset's primary bands are
@@ -63,7 +63,7 @@ def overview(ctx, input, build, ls, rebuild, resampling):
     Information about existing overviews can be printed using the --ls
     option.
 
-      rio pyramid --ls
+      rio overview --ls
 
     """
     verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 5b7ff43..a3e8d64 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,11 +1,12 @@
 affine
 cligj
 coveralls>=0.4
-cython>=0.21.2
+cython==0.22
 delocate
 enum34
 numpy>=1.8.0
 snuggs>=1.2
 pytest
+pytest-cov
 setuptools>=0.9.8
 wheel
diff --git a/setup.py b/setup.py
index a45f8b4..c5b2c23 100755
--- a/setup.py
+++ b/setup.py
@@ -197,7 +197,8 @@ inst_reqs = [
     'affine>=1.0',
     'cligj>=0.2.0',
     'Numpy>=1.7',
-    'snuggs>=1.3.1']
+    'snuggs>=1.3.1',
+    'click-plugins']
 
 if sys.version_info < (3, 4):
     inst_reqs.append('enum34')
diff --git a/tests/test_checksum.py b/tests/test_checksum.py
new file mode 100644
index 0000000..1a6fd4e
--- /dev/null
+++ b/tests/test_checksum.py
@@ -0,0 +1,45 @@
+import rasterio
+
+
+def test_checksum_band():
+    with rasterio.open('tests/data/RGB.byte.tif') as src:
+        checksums = [src.checksum(i) for i in src.indexes]
+        assert checksums == [25420, 29131, 37860]
+
+
+def test_checksum_band_window():
+    with rasterio.open('tests/data/RGB.byte.tif') as src:
+        window = ((0, src.height), (0, src.width))
+        checksums = [src.checksum(i, window=window) for i in src.indexes]
+        assert checksums == [25420, 29131, 37860]
+
+
+def test_checksum_band_window_min():
+    with rasterio.open('tests/data/RGB.byte.tif') as src:
+        window = ((0, 1), (0, 1))
+        checksums = [src.checksum(i, window=window) for i in src.indexes]
+        assert checksums == [0, 0, 0]
+
+
+def test_checksum_band_window_quarter():
+    """A quarter window's checksum is different from the full image's"""
+    with rasterio.open('tests/data/RGB.byte.tif') as src:
+        window = ((0, src.height//2), (0, src.width//2))
+        checksums = [src.checksum(i, window=window) for i in src.indexes]
+        assert checksums != [25420, 29131, 37860]
+
+
+def test_checksum_band_window_too_tall():
+    """Windows get truncated to maximum extent"""
+    with rasterio.open('tests/data/RGB.byte.tif') as src:
+        window = ((0, 10000), (0, src.width))
+        checksums = [src.checksum(i, window=window) for i in src.indexes]
+        assert checksums == [25420, 29131, 37860]
+
+
+def test_checksum_band_window_too_short():
+    """Negative values in windows get evaluated properly"""
+    with rasterio.open('tests/data/RGB.byte.tif') as src:
+        window = ((0, -1), (0, src.width))
+        checksums = [src.checksum(i, window=window) for i in src.indexes]
+        assert checksums == [25420, 29131, 37860]
diff --git a/tests/test_colormap.py b/tests/test_colormap.py
index 112ebfa..5fc7778 100644
--- a/tests/test_colormap.py
+++ b/tests/test_colormap.py
@@ -2,24 +2,28 @@ import logging
 import pytest
 import subprocess
 import sys
+import warnings
 
 import rasterio
 
+
 logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
 
 
-def test_write_colormap_err(tmpdir):
+def test_write_colormap_warn(tmpdir, recwarn):
 
     with rasterio.drivers():
 
         with rasterio.open('tests/data/shade.tif') as src:
-            meta = src.meta
+            profile = src.meta
 
         tiffname = str(tmpdir.join('foo.tif'))
 
-        with rasterio.open(tiffname, 'w', **meta) as dst:
-            with pytest.raises(ValueError):
-                dst.write_colormap(1, {0: (255, 0, 0, 255), 255: (0, 0, 0, 0)})
+        with rasterio.open(tiffname, 'w', **profile) as dst:
+            dst.write_colormap(1, {0: (255, 0, 0, 255), 255: (0, 0, 0, 0)})
+
+        w = recwarn.pop(UserWarning)
+        assert "The value will be ignored" in str(w.message)
 
 
 def test_write_colormap(tmpdir):
diff --git a/tests/test_dtypes.py b/tests/test_dtypes.py
index 7a41fc7..1826ec5 100644
--- a/tests/test_dtypes.py
+++ b/tests/test_dtypes.py
@@ -1,14 +1,23 @@
 import numpy as np
 
-import rasterio.dtypes
+from rasterio import dtypes, ubyte
+
+
+def test_is_ndarray():
+    assert dtypes.is_ndarray(np.zeros((1,)))
+    assert dtypes.is_ndarray([0]) == False
+    assert dtypes.is_ndarray((0,)) == False
+
 
 def test_np_dt_uint8():
-    assert rasterio.dtypes.check_dtype(np.uint8)
+    assert dtypes.check_dtype(np.uint8)
+
 
 def test_dt_ubyte():
-    assert rasterio.dtypes.check_dtype(rasterio.ubyte)
+    assert dtypes.check_dtype(ubyte)
+
 
 def test_gdal_name():
-    assert rasterio.dtypes._gdal_typename(rasterio.ubyte) == 'Byte'
-    assert rasterio.dtypes._gdal_typename(np.uint8) == 'Byte'
-    assert rasterio.dtypes._gdal_typename(np.uint16) == 'UInt16'
+    assert dtypes._gdal_typename(ubyte) == 'Byte'
+    assert dtypes._gdal_typename(np.uint8) == 'Byte'
+    assert dtypes._gdal_typename(np.uint16) == 'UInt16'
diff --git a/tests/test_overviews.py b/tests/test_overviews.py
index 381a06e..a219f75 100644
--- a/tests/test_overviews.py
+++ b/tests/test_overviews.py
@@ -38,3 +38,13 @@ def test_build_overviews_two(data):
         assert src.overviews(1) == [2, 4]
         assert src.overviews(2) == [2, 4]
         assert src.overviews(3) == [2, 4]
+
+
+def test_build_overviews_three(data):
+    inputfile = str(data.join('RGB.byte.tif'))
+    with rasterio.open(inputfile, 'r+') as src:
+        overview_factors = [2, 4]
+        src.build_overviews(overview_factors, resampling=Resampling.average)
+        assert src.overviews(1) == [2, 4]
+        assert src.overviews(2) == [2, 4]
+        assert src.overviews(3) == [2, 4]
diff --git a/tests/test_rio_bands.py b/tests/test_rio_bands.py
index dfc6b18..d6d9dd0 100644
--- a/tests/test_rio_bands.py
+++ b/tests/test_rio_bands.py
@@ -5,10 +5,6 @@ import rasterio
 from rasterio.rio import bands
 
 
-def test_photometic_choices():
-    assert len(bands.PHOTOMETRIC_CHOICES) == 8
-
-
 def test_stack(tmpdir):
     outputname = str(tmpdir.join('stacked.tif'))
     runner = CliRunner()
@@ -54,7 +50,7 @@ def test_stack_single_slice(tmpdir):
         [
             'tests/data/RGB.byte.tif', '--bidx', '1',
             'tests/data/RGB.byte.tif', '--bidx', '2..',
-            '--photometric', 'rgb',
+            '--rgb',
             outputname])
     assert result.exit_code == 0
     with rasterio.open(outputname) as out:
diff --git a/tests/test_rio_info.py b/tests/test_rio_info.py
index 79c5184..eb4e1f3 100644
--- a/tests/test_rio_info.py
+++ b/tests/test_rio_info.py
@@ -641,3 +641,19 @@ def test_insp_err():
         'tests'
     ])
     assert result.exit_code == 1
+
+
+def test_info_checksums():
+    runner = CliRunner()
+    result = runner.invoke(
+        info.info, ['tests/data/RGB.byte.tif', '--tell-me-more'])
+    assert result.exit_code == 0
+    assert '"checksum": [25420, 29131, 37860]' in result.output
+
+
+def test_info_checksums_only():
+    runner = CliRunner()
+    result = runner.invoke(
+        info.info, ['tests/data/RGB.byte.tif', '--checksum', '--bidx', '2'])
+    assert result.exit_code == 0
+    assert result.output.strip() == '29131'

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-grass/rasterio.git

_______________________________________________
Pkg-grass-devel mailing list
Pkg-grass-devel@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-grass-devel

Reply via email to