[mapnik] 01/01: Imported Upstream version 3.0.14~rc1+ds

Bas Couwenberg sebastic at debian.org
Sat Jun 3 09:05:37 UTC 2017


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

sebastic pushed a commit to annotated tag upstream/3.0.14_rc1+ds
in repository mapnik.

commit 0fc1ea0f81834919a2e254ee673c206ecbd7d368
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sat Jun 3 10:21:51 2017 +0200

    Imported Upstream version 3.0.14~rc1+ds
---
 .gitmodules                                        |   2 +-
 .travis.yml                                        |  27 +-
 CHANGELOG.md                                       |  11 +-
 benchmark/data/roads.xml                           |   2 +-
 bootstrap.sh                                       |  60 +-
 codecov.yml                                        |  10 +
 demo/viewer/main.cpp                               |   2 +-
 demo/viewer/viewer.pro                             |   1 -
 include/mapnik/config_error.hpp                    |   6 +-
 include/mapnik/datasource.hpp                      |   9 +-
 include/mapnik/enumeration.hpp                     |   4 +-
 include/mapnik/font_engine_freetype.hpp            |  79 +--
 include/mapnik/gradient.hpp                        |   2 +-
 include/mapnik/image_reader.hpp                    |   4 +-
 include/mapnik/image_util.hpp                      |   4 +-
 .../json/geometry_generator_grammar_impl.hpp       |  18 +-
 include/mapnik/json/geometry_util.hpp              |  43 +-
 include/mapnik/raster.hpp                          |  13 +-
 .../renderer_common/process_raster_symbolizer.hpp  |  49 +-
 include/mapnik/svg/svg_parser_exception.hpp        |   4 +-
 include/mapnik/util/file_io.hpp                    |   3 +-
 include/mapnik/value_error.hpp                     |   4 +-
 include/mapnik/version.hpp                         |   2 +-
 include/mapnik/xml_node.hpp                        |  12 +-
 plugins/input/gdal/build.py                        |   2 +-
 plugins/input/gdal/gdal_featureset.cpp             | 678 ++++++++++-----------
 plugins/input/ogr/build.py                         |   2 +-
 plugins/input/raster/raster_featureset.cpp         |  55 +-
 plugins/input/raster/raster_info.cpp               |   2 +-
 plugins/input/shape/dbfile.cpp                     |   2 +-
 plugins/input/shape/dbfile.hpp                     |   2 +-
 scripts/check-padding                              |   2 +-
 scripts/travis-common.sh                           |  17 +-
 src/config_error.cpp                               |   2 +-
 src/font_engine_freetype.cpp                       |  74 ++-
 src/gradient.cpp                                   |   2 +-
 src/image_scaling.cpp                              |  10 +-
 src/image_view.cpp                                 |   1 -
 src/json/mapnik_json_geometry_parser.cpp           |  10 +-
 src/load_map.cpp                                   |  14 +-
 src/map.cpp                                        |   2 +-
 src/tiff_reader.cpp                                | 213 +++++--
 src/xml_tree.cpp                                   |  12 +-
 test/unit/datasource/geojson.cpp                   |  52 +-
 test/unit/datasource/shapeindex.cpp                |   8 +-
 test/unit/imaging/tiff_io.cpp                      | 612 +++++++++++--------
 utils/pgsql2sqlite/build.py                        |  26 +-
 utils/shapeindex/shapeindex.cpp                    |   5 +-
 48 files changed, 1245 insertions(+), 931 deletions(-)

diff --git a/.gitmodules b/.gitmodules
index dfcbea5..a103059 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -5,7 +5,7 @@
 [submodule "test/data-visual"]
 	path = test/data-visual
 	url = https://github.com/mapnik/test-data-visual.git
-	branch = master
+	branch = 3.0.x
 [submodule "deps/mapbox/variant"]
 	path = deps/mapbox/variant
 	url = https://github.com/mapbox/variant.git
diff --git a/.travis.yml b/.travis.yml
index 814325d..3d19711 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,8 +10,6 @@ env:
    - CCACHE_COMPRESS=1
    - HEAVY_JOBS="2"
    - PREFIX=/tmp/mapnik
-   - secure: "D5CLP5lbyFru788iZO8RqDenY/YsHPREvr34zCEi93xMqOTxPmME/zyuEZSyjP5ZLyf8g/fxOuPYSDbOQ1QLwNDBWxB0JomWOahyimHKrMCrMcGHCjl//2W2mE+p9VwF5VLGgfy7CskGkS49Mye37FDK0ejwuq6MDI45DsH4Fkk="
-   - secure: "ZPHyAVL3ID5g3KEmwcnzG9z2tAQwSx526Qd3Y6tsZ3Yj+aSagVBiZQjZGKWgNX74lymtmYKnb2Md46apWLeImt6tjB3MWTu7WwWoZRnqUligz/8Nmg4Lgo7EOCkQcjN/gpA1i+cM5b+ZKDTZYOaHO6/+DAaunQzA7/p99hw/XYg="
    - secure: "F6ivqDNMBQQnrDGA9+7IX+GDswuIqQQd7YPJdQqa2Ked9jddAQDeJClb05ig3JlwfOlYLGZOd43ZX0pKuMtI2Gbkwz211agGP9S3YunwlRg8iWtJlO5kYFUdKCmJNhjg4icfkGELCgwXn+zuEWFSLpkPcjqAFKFlQrIJeAJJgKM="
 addons:
   postgresql: "9.4"
@@ -33,7 +31,7 @@ matrix:
     - os: linux
       sudo: false
       compiler: ": clang"
-      env: JOBS=8 MASON_PUBLISH=true CXX="ccache clang++-3.9 -Qunused-arguments" CC="clang-3.9" TRIGGER=true
+      env: JOBS=8 CXX="ccache clang++-3.9 -Qunused-arguments" CC="clang-3.9" TRIGGER=true
       addons:
         apt:
           sources: [ 'ubuntu-toolchain-r-test']
@@ -50,7 +48,7 @@ matrix:
       compiler: ": clang-osx"
       # https://docs.travis-ci.com/user/languages/objective-c/#Supported-OS-X-iOS-SDK-versions
       osx_image: xcode7.3 # upgrades clang from 6 -> 7
-      env: JOBS=4 MASON_PUBLISH=true CXX="ccache clang++ -Qunused-arguments"
+      env: JOBS=4 CXX="ccache clang++ -Qunused-arguments"
 
 before_install:
  # workaround travis rvm bug
@@ -60,18 +58,12 @@ before_install:
      rvm get head || true
    fi
  - source scripts/travis-common.sh
- - export PYTHONUSERBASE=$(pwd)/mason_packages/.link
- - export PATH=${PREFIX}/bin:$(pwd)/mason_packages/.link/bin:${PYTHONUSERBASE}/bin:${PATH}
+ - export PATH=${PREFIX}/bin:$(pwd)/mason_packages/.link/bin:${PATH}
  - export COVERAGE=${COVERAGE:-false}
- - export MASON_PUBLISH=${MASON_PUBLISH:-false}
  - export BENCH=${BENCH:-false}
- - if [[ ${TRAVIS_BRANCH} != 'master' ]]; then export MASON_PUBLISH=false; fi
- - if [[ ${TRAVIS_PULL_REQUEST} != 'false' ]]; then export MASON_PUBLISH=false; fi
  - git_submodule_update --init --depth=10
 
 install:
- - on 'linux' export PYTHONPATH=${PYTHONUSERBASE}/lib/python2.7/site-packages
- - on 'osx' export PYTHONPATH=${PYTHONUSERBASE}/lib/python/site-packages
  - on 'osx' export DATA_PATH=$(brew --prefix)/var/postgres
  - on 'osx' rm -rf ${DATA_PATH}
  - on 'osx' initdb ${DATA_PATH} -E utf8
@@ -80,7 +72,8 @@ install:
  - on 'osx' createuser -s postgres
  - psql -c 'create database template_postgis;' -U postgres
  - psql -c 'create extension postgis;' -d template_postgis -U postgres
- - enabled ${COVERAGE} pip install --user cpp-coveralls
+ - enabled ${COVERAGE} curl -S -f https://codecov.io/bash -o codecov
+ - enabled ${COVERAGE} chmod +x codecov
 
 before_script:
  - source bootstrap.sh
@@ -113,12 +106,4 @@ script:
  # we allow visual failures with g++ for now: https://github.com/mapnik/mapnik/issues/3567
  - if [[ ${RESULT} != 0 ]] && [[ ${CXX} =~ 'clang++' ]]; then false; fi;
  - enabled ${COVERAGE} coverage
- - enabled ${BENCH} make bench
-
-after_success:
- - enabled ${TRIGGER} trigger_downstream
- - if enabled ${MASON_PUBLISH}; then
-     source ./.mason/mason.sh &&
-     ./mason_latest.sh build &&
-     ./mason_latest.sh publish;
-   fi
+ - enabled ${BENCH} make bench
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7ace7d6..02ed6d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,13 @@ Developers: Please commit along with changes.
 
 For a complete change history, see the git log.
 
+## 3.0.x
+
+#### Summary
+
+- Fixed problems with high levels of overzooming in the GDAL and raster plugin where data would be slightly offset
+- High levels of overzooming on raster data no longer results in the return of a transparent image.
+
 ## 3.0.13
 
 Released: February 8, 2017
@@ -15,14 +22,14 @@ Released: February 8, 2017
 #### Summary
 
 - Unbundle `unifont` font from distribution
-- GeoJSON: imporoved parsing grammar avoiding temp synthesised attribute (#3507)
+- GeoJSON: improved parsing grammar avoiding temp synthesised attribute (#3507)
 - GeoJSON: expose `num_features_to_query` datasource parameter + unit test (#3515)
 - Fixed intersecting extents in different projections (PR #3525 )
 - Fixed `blur` implementation by taking into account `scale_factor`
 - postgis.input - use 2D box for pgraster bounding box (PR #3551)
 - Fixed GroupSymbolizer PairLayout with 3+ items (#3526)
 - Simplified `hash` implementation (204d30e58d3553278ab6bcda2d4122b0f13f6392)
-- Simplified `mapnik::valu`e conversion rules (#3570)
+- Simplified `mapnik::value` conversion rules (#3570)
 - Changed `render_thunk_list` to `std::list<render_thunk>` (PR #3585)
 - Upgraded to variant `v1.1.5`
 - CSV.input - fixed `blank` line test (8a3a380b3b5c64681f2478b4f0d06f6a907f5eed)
diff --git a/benchmark/data/roads.xml b/benchmark/data/roads.xml
index 0ca938f..1c81bfa 100644
--- a/benchmark/data/roads.xml
+++ b/benchmark/data/roads.xml
@@ -2,7 +2,7 @@
 <!DOCTYPE Map[]>
 <Map
   srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"
-  font-directory="../../fonts/dejavu-fonts-ttf-2.35/ttf/DejaVuSans.ttf"
+  font-directory="../../fonts/dejavu-fonts-ttf-2.37/ttf/DejaVuSans.ttf"
   background-color="#dfd8c9">
 
 <Style name="marking" filter-mode="first">
diff --git a/bootstrap.sh b/bootstrap.sh
index 7f369ac..030c0dc 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -11,7 +11,7 @@ todo
 - shrink icu data
 '
 
-MASON_VERSION="v0.5.0"
+MASON_VERSION="v0.11.1"
 
 function setup_mason() {
     if [[ ! -d ./.mason ]]; then
@@ -44,45 +44,37 @@ function install() {
     mason link $1 $2
 }
 
-ICU_VERSION="55.1"
+ICU_VERSION="57.1"
 
 function install_mason_deps() {
-    FAIL=0
-    install ccache 3.3.0 &
-    install zlib system &
-    install jpeg_turbo 1.5.0 libjpeg &
-    install libpng 1.6.24 libpng &
-    install libtiff 4.0.6 libtiff &
-    install libpq 9.5.2 &
-    install sqlite 3.14.1 libsqlite3 &
-    install expat 2.2.0 libexpat &
-    install icu ${ICU_VERSION} &
-    install proj 4.9.2 libproj &
-    install pixman 0.34.0 libpixman-1 &
-    install cairo 1.14.6 libcairo &
-    install protobuf 2.6.1 &
+    install ccache 3.3.1
+    install zlib 1.2.8
+    install jpeg_turbo 1.5.1 libjpeg
+    install libpng 1.6.28 libpng
+    install libtiff 4.0.7 libtiff
+    install libpq 9.6.2
+    install sqlite 3.17.0 libsqlite3
+    install expat 2.2.0 libexpat
+    install icu ${ICU_VERSION}
+    install proj 4.9.3 libproj
+    install pixman 0.34.0 libpixman-1
+    install cairo 1.14.8 libcairo
+    install protobuf 3.2.0
     # technically protobuf is not a mapnik core dep, but installing
     # here by default helps make mapnik-vector-tile builds easier
-    install webp 0.5.1 libwebp &
-    install gdal 2.1.1 libgdal &
-    install boost 1.61.0 &
-    install boost_libsystem 1.61.0 &
-    install boost_libfilesystem 1.61.0 &
-    install boost_libprogram_options 1.61.0 &
-    install boost_libregex_icu 1.61.0 &
+    install webp 0.6.0 libwebp
+    install libgdal 2.1.3 libgdal
+    install boost 1.63.0
+    install boost_libsystem 1.63.0
+    install boost_libfilesystem 1.63.0
+    install boost_libprogram_options 1.63.0
+    install boost_libregex_icu57 1.63.0
     # technically boost thread and python are not a core dep, but installing
     # here by default helps make python-mapnik builds easier
-    install boost_libthread 1.61.0 &
-    install boost_libpython 1.61.0 &
-    install freetype 2.6.5 libfreetype &
-    install harfbuzz 1.3.0 libharfbuzz &
-    for job in $(jobs -p)
-    do
-        wait $job || let "FAIL+=1"
-    done
-    if [[ "$FAIL" != "0" ]]; then
-        exit ${FAIL}
-    fi
+    install boost_libthread 1.63.0
+    install boost_libpython 1.63.0
+    install freetype 2.7.1 libfreetype
+    install harfbuzz 1.4.4-ft libharfbuzz
 }
 
 MASON_LINKED_ABS=$(pwd)/mason_packages/.link
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 0000000..73fb4cf
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,10 @@
+ignore:
+  - "mason_packages"
+  - "benchmark"
+  - "deps"
+  - ".sconf_temp"
+  - "scons"
+  - "test"
+  - "demo"
+  - "docs"
+  - "fonts"
\ No newline at end of file
diff --git a/demo/viewer/main.cpp b/demo/viewer/main.cpp
index d8f06d2..fe90983 100644
--- a/demo/viewer/main.cpp
+++ b/demo/viewer/main.cpp
@@ -48,7 +48,7 @@ int main( int argc, char **argv )
         {
             settings.setArrayIndex(index);
             QString font_dir = settings.value("dir").toString();
-            freetype_engine::register_fonts(font_dir.toStdString());
+            freetype_engine::instance().register_fonts(font_dir.toStdString());
         }
         settings.endArray();
 
diff --git a/demo/viewer/viewer.pro b/demo/viewer/viewer.pro
index 8a97477..aad00b4 100644
--- a/demo/viewer/viewer.pro
+++ b/demo/viewer/viewer.pro
@@ -1,7 +1,6 @@
 ######################################################################
 # Mapnik viewer - Copyright (C) 2007 Artem Pavlenko
 ######################################################################
-QMAKE_MAC_SDK = macosx10.11
 TEMPLATE = app
 QT += core gui widgets
 QMAKE_CXX = $$system(mapnik-config --cxx)
diff --git a/include/mapnik/config_error.hpp b/include/mapnik/config_error.hpp
index b8bd31f..38cb70c 100644
--- a/include/mapnik/config_error.hpp
+++ b/include/mapnik/config_error.hpp
@@ -41,10 +41,8 @@ public:
     config_error(std::string const& what,
                  unsigned line_number,
                  std::string const& filename);
-    virtual ~config_error() throw() {}
-
-    virtual const char * what() const throw();
-
+    virtual ~config_error() {}
+    virtual const char * what() const noexcept;
     void append_context(std::string const& ctx) const;
     void append_context(std::string const& ctx, xml_node const& node) const;
     void append_context(xml_node const& node) const;
diff --git a/include/mapnik/datasource.hpp b/include/mapnik/datasource.hpp
index ec14a62..610e52d 100644
--- a/include/mapnik/datasource.hpp
+++ b/include/mapnik/datasource.hpp
@@ -46,14 +46,11 @@ class MAPNIK_DECL datasource_exception : public std::exception
 public:
     datasource_exception(std::string const& message)
       : message_(message)
-    {
-    }
+    {}
 
-    ~datasource_exception() throw()
-    {
-    }
+    ~datasource_exception() {}
 
-    virtual const char* what() const throw()
+    virtual const char* what() const noexcept
     {
         return message_.c_str();
     }
diff --git a/include/mapnik/enumeration.hpp b/include/mapnik/enumeration.hpp
index ded9dc0..1dd312e 100644
--- a/include/mapnik/enumeration.hpp
+++ b/include/mapnik/enumeration.hpp
@@ -44,9 +44,9 @@ public:
         what_( _what )
     {
     }
-    virtual ~illegal_enum_value() throw() {}
+    virtual ~illegal_enum_value() {}
 
-    virtual const char * what() const throw()
+    virtual const char * what() const noexcept
     {
         return what_.c_str();
     }
diff --git a/include/mapnik/font_engine_freetype.hpp b/include/mapnik/font_engine_freetype.hpp
index 73227cd..f35fa3d 100644
--- a/include/mapnik/font_engine_freetype.hpp
+++ b/include/mapnik/font_engine_freetype.hpp
@@ -25,9 +25,10 @@
 
 // mapnik
 #include <mapnik/config.hpp>
+#include <mapnik/util/singleton.hpp>
+#include <mapnik/util/noncopyable.hpp>
 #include <mapnik/font_set.hpp>
 #include <mapnik/text/font_library.hpp>
-#include <mapnik/util/noncopyable.hpp>
 
 // stl
 #include <memory>
@@ -35,10 +36,6 @@
 #include <utility> // pair
 #include <vector>
 
-#ifdef MAPNIK_THREADSAFE
-#include <mutex>
-#endif
-
 namespace boost { template <class T> class optional; }
 
 namespace mapnik
@@ -51,22 +48,17 @@ using face_set_ptr = std::unique_ptr<font_face_set>;
 class font_face;
 using face_ptr = std::shared_ptr<font_face>;
 
-class MAPNIK_DECL freetype_engine
+class MAPNIK_DECL freetype_engine : public singleton<freetype_engine, CreateUsingNew>,
+                                    private util::noncopyable
 {
+    friend class CreateUsingNew<freetype_engine>;
+    friend class Map;
 public:
     using font_file_mapping_type = std::map<std::string,std::pair<int,std::string>>;
     using font_memory_cache_type = std::map<std::string, std::pair<std::unique_ptr<char[]>, std::size_t>>;
+
     static bool is_font_file(std::string const& file_name);
-    /*! \brief register a font file
-     *  @param file_name path to a font file.
-     *  @return bool - true if at least one face was successfully registered in the file.
-     */
     static bool register_font(std::string const& file_name);
-    /*! \brief register a font files
-     *  @param dir - path to a directory containing fonts or subdirectories.
-     *  @param recurse - default false, whether to search for fonts in sub directories.
-     *  @return bool - true if at least one face was successfully registered.
-     */
     static bool register_fonts(std::string const& dir, bool recurse = false);
     static std::vector<std::string> face_names();
     static font_file_mapping_type const& get_mapping();
@@ -75,29 +67,42 @@ public:
                          font_library & library,
                          font_file_mapping_type const& font_file_mapping,
                          font_file_mapping_type const& global_font_file_mapping);
+
     static face_ptr create_face(std::string const& face_name,
-                         font_library & library,
-                         font_file_mapping_type const& font_file_mapping,
-                         freetype_engine::font_memory_cache_type const& font_cache,
-                         font_file_mapping_type const& global_font_file_mapping,
-                         freetype_engine::font_memory_cache_type & global_memory_fonts);
-    static bool register_font_impl(std::string const& file_name,
-                                   font_library & libary,
-                                   font_file_mapping_type & font_file_mapping);
-    static bool register_fonts_impl(std::string const& dir,
-                                    font_library & libary,
-                                    font_file_mapping_type & font_file_mapping,
-                                    bool recurse = false);
-    virtual ~freetype_engine();
-    freetype_engine();
+                                font_library & library,
+                                font_file_mapping_type const& font_file_mapping,
+                                freetype_engine::font_memory_cache_type const& font_cache,
+                                font_file_mapping_type const& global_font_file_mapping,
+                                freetype_engine::font_memory_cache_type & global_memory_fonts);
 private:
-    static bool register_font_impl(std::string const& file_name, FT_LibraryRec_ * library);
-    static bool register_fonts_impl(std::string const& dir, FT_LibraryRec_ * library, bool recurse = false);
-#ifdef MAPNIK_THREADSAFE
-    static std::mutex mutex_;
-#endif
-    static font_file_mapping_type global_font_file_mapping_;
-    static font_memory_cache_type global_memory_fonts_;
+    bool is_font_file_impl(std::string const& file_name);
+    std::vector<std::string> face_names_impl();
+    font_file_mapping_type const& get_mapping_impl();
+    font_memory_cache_type& get_cache_impl();
+    bool can_open_impl(std::string const& face_name,
+                  font_library & library,
+                  font_file_mapping_type const& font_file_mapping,
+                  font_file_mapping_type const& global_font_file_mapping);
+
+    face_ptr create_face_impl(std::string const& face_name,
+                              font_library & library,
+                              font_file_mapping_type const& font_file_mapping,
+                              freetype_engine::font_memory_cache_type const& font_cache,
+                              font_file_mapping_type const& global_font_file_mapping,
+                              freetype_engine::font_memory_cache_type & global_memory_fonts);
+    bool register_font_impl(std::string const& file_name);
+    bool register_fonts_impl(std::string const& dir, bool recurse);
+    bool register_font_impl(std::string const& file_name, FT_LibraryRec_ * library);
+    bool register_fonts_impl(std::string const& dir, FT_LibraryRec_ * library, bool recurse = false);
+    bool register_font_impl(std::string const& file_name,
+                            font_library & libary,
+                            font_file_mapping_type & font_file_mapping);
+    bool register_fonts_impl(std::string const& dir,
+                             font_library & libary,
+                             font_file_mapping_type & font_file_mapping,
+                             bool recurse = false);
+    font_file_mapping_type global_font_file_mapping_;
+    font_memory_cache_type global_memory_fonts_;
 };
 
 class MAPNIK_DECL face_manager
@@ -124,7 +129,7 @@ private:
 };
 
 using face_manager_freetype = face_manager;
-
+extern template class MAPNIK_DECL singleton<freetype_engine, CreateUsingNew>;
 }
 
 #endif // MAPNIK_FONT_ENGINE_FREETYPE_HPP
diff --git a/include/mapnik/gradient.hpp b/include/mapnik/gradient.hpp
index ae9acb5..5d00249 100644
--- a/include/mapnik/gradient.hpp
+++ b/include/mapnik/gradient.hpp
@@ -96,7 +96,7 @@ public:
     void get_control_points(double &x1, double &y1, double &x2, double &y2) const;
 
 private:
-    void swap(gradient& other) throw();
+    void swap(gradient& other) noexcept;
 };
 }
 
diff --git a/include/mapnik/image_reader.hpp b/include/mapnik/image_reader.hpp
index 6c1c232..2258da1 100644
--- a/include/mapnik/image_reader.hpp
+++ b/include/mapnik/image_reader.hpp
@@ -50,9 +50,9 @@ public:
     image_reader_exception(std::string const& message)
         : message_(message) {}
 
-    ~image_reader_exception() throw() {}
+    ~image_reader_exception() {}
 
-    virtual const char* what() const throw()
+    virtual const char* what() const noexcept
     {
         return message_.c_str();
     }
diff --git a/include/mapnik/image_util.hpp b/include/mapnik/image_util.hpp
index 0db5a37..baeb468 100644
--- a/include/mapnik/image_util.hpp
+++ b/include/mapnik/image_util.hpp
@@ -56,9 +56,9 @@ public:
     image_writer_exception(std::string const& message)
         : message_(message) {}
 
-    ~image_writer_exception() throw() {}
+    ~image_writer_exception(){}
 
-    virtual const char* what() const throw()
+    virtual const char* what() const noexcept
     {
         return message_.c_str();
     }
diff --git a/include/mapnik/json/geometry_generator_grammar_impl.hpp b/include/mapnik/json/geometry_generator_grammar_impl.hpp
index 87a60db..cd4c5d7 100644
--- a/include/mapnik/json/geometry_generator_grammar_impl.hpp
+++ b/include/mapnik/json/geometry_generator_grammar_impl.hpp
@@ -56,26 +56,24 @@ geometry_generator_grammar<OutputIterator, Geometry>::geometry_generator_grammar
         ;
 
     geometry_dispatch = eps[_a = geometry_type(_val)] <<
-        (&uint_(geometry::geometry_types::Point)[_1 = _a]
-         << (point | lit("null")))
+        (&uint_(geometry::geometry_types::Point)[_1 = _a] << point)
         |
         (&uint_(geometry::geometry_types::LineString)[_1 = _a]
-         << (linestring | lit("null")))
+         << (linestring | "{\"type\":\"LineString\",\"coordinates\":[]}"))
         |
         (&uint_(geometry::geometry_types::Polygon)[_1 = _a]
-         << (polygon | lit("null")))
+         << (polygon | "{\"type\":\"Polygon\",\"coordinates\":[[]]}"))
         |
         (&uint_(geometry::geometry_types::MultiPoint)[_1 = _a]
-         << (multi_point | lit("null")))
+         << (multi_point | "{\"type\":\"MultiPoint\",\"coordinates\":[]}"))
         |
         (&uint_(geometry::geometry_types::MultiLineString)[_1 = _a]
-         << (multi_linestring | lit("null")))
+         << (multi_linestring | "{\"type\":\"MultiLineString\",\"coordinates\":[[]]}"))
         |
         (&uint_(geometry::geometry_types::MultiPolygon)[_1 = _a]
-         << (multi_polygon | lit("null")))
+         << (multi_polygon | "{\"type\":\"MultiPolygon\",\"coordinates\":[[[]]]}"))
         |
-        (&uint_(geometry::geometry_types::GeometryCollection)[_1 = _a]
-         << (geometry_collection | lit("null")))
+        (&uint_(geometry::geometry_types::GeometryCollection)[_1 = _a] << geometry_collection)
         |
         lit("null")
         ;
@@ -96,7 +94,7 @@ geometry_generator_grammar<OutputIterator, Geometry>::geometry_generator_grammar
         ;
     point_coord = lit('[') << coordinate << lit(',') << coordinate  << lit(']')
         ;
-    linestring_coord = point_coord % lit(',')
+    linestring_coord = (point_coord % lit(','))
         ;
     polygon_coord = lit('[') << exterior_ring_coord << lit(']') << interior_ring_coord
         ;
diff --git a/include/mapnik/json/geometry_util.hpp b/include/mapnik/json/geometry_util.hpp
index cf538ae..ac5786f 100644
--- a/include/mapnik/json/geometry_util.hpp
+++ b/include/mapnik/json/geometry_util.hpp
@@ -43,7 +43,10 @@ struct create_point
     }
 
     template <typename T>
-    void operator()(T const&) const {} // no-op - shouldn't get here
+    void operator()(T const&) const
+    {
+        throw std::runtime_error("Failed to parse geojson geometry");
+    }
     Geometry & geom_;
 };
 
@@ -55,21 +58,21 @@ struct create_linestring
 
     void operator() (positions const& ring) const
     {
+        mapnik::geometry::line_string<double> line;
         std::size_t size = ring.size();
-        if (size > 1)
+        line.reserve(size);
+        for (auto && pt : ring)
         {
-            mapnik::geometry::line_string<double> line;
-            line.reserve(size);
-            for (auto && pt : ring)
-            {
-                line.emplace_back(std::move(pt));
-            }
-            geom_ = std::move(line);
+            line.emplace_back(std::move(pt));
         }
+        geom_ = std::move(line);
     }
 
     template <typename T>
-    void operator()(T const&) const {}  // no-op - shouldn't get here
+    void operator()(T const&) const
+    {
+        throw std::runtime_error("Failed to parse geojson geometry");
+    }
 
     Geometry & geom_;
 };
@@ -106,7 +109,10 @@ struct create_polygon
     }
 
     template <typename T>
-    void operator()(T const&) const {}  // no-op - shouldn't get here
+    void operator()(T const&) const
+    {
+        throw std::runtime_error("Failed to parse geojson geometry");
+    }
 
     Geometry & geom_;
 };
@@ -130,7 +136,10 @@ struct create_multipoint
     }
 
     template <typename T>
-    void operator()(T const&) const {}  // no-op - shouldn't get here
+    void operator()(T const&) const
+    {
+        throw std::runtime_error("Failed to parse geojson geometry");
+    }
 
     Geometry & geom_;
 };
@@ -160,7 +169,10 @@ struct create_multilinestring
     }
 
     template <typename T>
-    void operator()(T const&) const {}  // no-op - shouldn't get here
+    void operator()(T const&) const
+    {
+        throw std::runtime_error("Failed to parse geojson geometry");
+    }
 
     Geometry & geom_;
 };
@@ -201,7 +213,10 @@ struct create_multipolygon
     }
 
     template <typename T>
-    void operator()(T const&) const {}  // no-op - shouldn't get here
+    void operator()(T const&) const
+    {
+        throw std::runtime_error("Failed to parse geojson geometry");
+    }
 
     Geometry & geom_;
 };
diff --git a/include/mapnik/raster.hpp b/include/mapnik/raster.hpp
index 02022d3..2156119 100644
--- a/include/mapnik/raster.hpp
+++ b/include/mapnik/raster.hpp
@@ -40,15 +40,27 @@ class raster : private util::noncopyable
 {
 public:
     box2d<double> ext_;
+    box2d<double> query_ext_;
     image_any data_;
     double filter_factor_;
     boost::optional<double> nodata_;
+    
+    template <typename ImageData>
+    raster(box2d<double> const& ext,
+           box2d<double> const& query_ext,
+           ImageData && data,
+           double filter_factor)
+        : ext_(ext),
+          query_ext_(query_ext),
+          data_(std::move(data)),
+          filter_factor_(filter_factor) {}
 
     template <typename ImageData>
     raster(box2d<double> const& ext,
            ImageData && data,
            double filter_factor)
         : ext_(ext),
+          query_ext_(ext),
           data_(std::move(data)),
           filter_factor_(filter_factor) {}
 
@@ -71,7 +83,6 @@ public:
     {
         filter_factor_ = factor;
     }
-
 };
 }
 
diff --git a/include/mapnik/renderer_common/process_raster_symbolizer.hpp b/include/mapnik/renderer_common/process_raster_symbolizer.hpp
index 7ca90a0..54726ea 100644
--- a/include/mapnik/renderer_common/process_raster_symbolizer.hpp
+++ b/include/mapnik/renderer_common/process_raster_symbolizer.hpp
@@ -53,6 +53,7 @@ struct image_dispatcher
     image_dispatcher(int start_x, int start_y,
                           int width, int height,
                           double scale_x, double scale_y,
+                          double offset_x, double offset_y,
                           scaling_method_e method, double filter_factor,
                           double opacity, composite_mode_e comp_op,
                           raster_symbolizer const& sym, feature_impl const& feature,
@@ -63,15 +64,17 @@ struct image_dispatcher
           height_(height),
           scale_x_(scale_x),
           scale_y_(scale_y),
+          offset_x_(offset_x),
+          offset_y_(offset_y),
           method_(method),
           filter_factor_(filter_factor),
-        opacity_(opacity),
-        comp_op_(comp_op),
-        sym_(sym),
-        feature_(feature),
-        composite_(composite),
-        nodata_(nodata),
-        need_scaling_(need_scaling) {}
+          opacity_(opacity),
+          comp_op_(comp_op),
+          sym_(sym),
+          feature_(feature),
+          composite_(composite),
+          nodata_(nodata),
+          need_scaling_(need_scaling) {}
 
     void operator() (image_null const&) const {}  //no-op
     void operator() (image_rgba8 const& data_in) const
@@ -79,7 +82,7 @@ struct image_dispatcher
         if (need_scaling_)
         {
             image_rgba8 data_out(width_, height_, true, true);
-            scale_image_agg(data_out, data_in,  method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_, nodata_);
+            scale_image_agg(data_out, data_in,  method_, scale_x_, scale_y_, offset_x_, offset_y_, filter_factor_, nodata_);
             composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
         }
         else
@@ -97,7 +100,7 @@ struct image_dispatcher
         if (need_scaling_)
         {
             image_type data_out(width_, height_);
-            scale_image_agg(data_out, data_in,  method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_, nodata_);
+            scale_image_agg(data_out, data_in,  method_, scale_x_, scale_y_, offset_x_, offset_y_, filter_factor_, nodata_);
             if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
         }
         else
@@ -114,6 +117,8 @@ private:
     int height_;
     double scale_x_;
     double scale_y_;
+    double offset_x_;
+    double offset_y_;
     scaling_method_e method_;
     double filter_factor_;
     double opacity_;
@@ -210,12 +215,18 @@ void render_raster_symbolizer(raster_symbolizer const& sym,
     if (source)
     {
         box2d<double> target_ext = box2d<double>(source->ext_);
-        prj_trans.backward(target_ext, PROJ_ENVELOPE_POINTS);
+        box2d<double> target_query_ext = box2d<double>(source->query_ext_);
+        if (!prj_trans.equal())
+        {
+            prj_trans.backward(target_ext, PROJ_ENVELOPE_POINTS);
+            prj_trans.backward(target_query_ext, PROJ_ENVELOPE_POINTS);
+        }
         box2d<double> ext = common.t_.forward(target_ext);
-        int start_x = static_cast<int>(std::floor(ext.minx()+.5));
-        int start_y = static_cast<int>(std::floor(ext.miny()+.5));
-        int end_x = static_cast<int>(std::floor(ext.maxx()+.5));
-        int end_y = static_cast<int>(std::floor(ext.maxy()+.5));
+        box2d<double> query_ext = common.t_.forward(target_query_ext);
+        int start_x = static_cast<int>(std::floor(query_ext.minx()+.5));
+        int start_y = static_cast<int>(std::floor(query_ext.miny()+.5));
+        int end_x = static_cast<int>(std::floor(query_ext.maxx()+.5));
+        int end_y = static_cast<int>(std::floor(query_ext.maxy()+.5));
         int raster_width = end_x - start_x;
         int raster_height = end_y - start_y;
         if (raster_width > 0 && raster_height > 0)
@@ -236,17 +247,20 @@ void render_raster_symbolizer(raster_symbolizer const& sym,
 
             if (!prj_trans.equal())
             {
-                double offset_x = ext.minx() - start_x;
-                double offset_y = ext.miny() - start_y;
+                // This path does not currently work and is still being figured out. 
+                double offset_x = query_ext.minx() - start_x;
+                double offset_y = query_ext.miny() - start_y;
                 unsigned mesh_size = static_cast<unsigned>(get<value_integer>(sym,keys::mesh_size,feature, common.vars_, 16));
                 detail::image_warp_dispatcher<F> dispatcher(prj_trans, start_x, start_y, raster_width, raster_height,
-                                                                 target_ext, source->ext_, offset_x, offset_y, mesh_size,
+                                                                 target_query_ext, source->ext_, offset_x, offset_y, mesh_size,
                                                                  scaling_method, source->get_filter_factor(),
                                                                  opacity, comp_op, sym, feature, composite, source->nodata());
                 util::apply_visitor(dispatcher, source->data_);
             }
             else
             {
+                double offset_x = query_ext.minx() - ext.minx();
+                double offset_y = query_ext.miny() - ext.miny();
                 double image_ratio_x = ext.width() / source->data_.width();
                 double image_ratio_y = ext.height() / source->data_.height();
                 double eps = 1e-5;
@@ -256,6 +270,7 @@ void render_raster_symbolizer(raster_symbolizer const& sym,
                      (std::abs(start_y) > eps);
                 detail::image_dispatcher<F> dispatcher(start_x, start_y, raster_width, raster_height,
                                                             image_ratio_x, image_ratio_y,
+                                                            offset_x, offset_y,
                                                             scaling_method, source->get_filter_factor(),
                                                             opacity, comp_op, sym, feature, composite, source->nodata(), scale);
                 util::apply_visitor(dispatcher, source->data_);
diff --git a/include/mapnik/svg/svg_parser_exception.hpp b/include/mapnik/svg/svg_parser_exception.hpp
index 89139da..739c618 100644
--- a/include/mapnik/svg/svg_parser_exception.hpp
+++ b/include/mapnik/svg/svg_parser_exception.hpp
@@ -38,9 +38,9 @@ public:
     svg_parser_exception(std::string const& message)
       : message_(message) {}
 
-    ~svg_parser_exception() throw() {}
+    ~svg_parser_exception() {}
 
-    virtual const char* what() const throw()
+    virtual const char* what() const noexcept
     {
         return message_.c_str();
     }
diff --git a/include/mapnik/util/file_io.hpp b/include/mapnik/util/file_io.hpp
index b8bc22f..ee8076c 100644
--- a/include/mapnik/util/file_io.hpp
+++ b/include/mapnik/util/file_io.hpp
@@ -83,7 +83,8 @@ public:
         if (!size_) return nullptr;
         std::fseek(file_.get(), 0, SEEK_SET);
         data_type buffer(new char[size_]);
-        std::fread(buffer.get(), size_, 1, file_.get());
+        auto count = std::fread(buffer.get(), size_, 1, file_.get());
+        if (count != 1) return nullptr;
         return buffer;
     }
 private:
diff --git a/include/mapnik/value_error.hpp b/include/mapnik/value_error.hpp
index 68df622..01cce90 100644
--- a/include/mapnik/value_error.hpp
+++ b/include/mapnik/value_error.hpp
@@ -41,9 +41,9 @@ public:
     {
     }
 
-    virtual ~value_error() throw() {}
+    virtual ~value_error() {}
 
-    virtual const char * what() const throw()
+    virtual const char * what() const noexcept
     {
         return what_.c_str();
     }
diff --git a/include/mapnik/version.hpp b/include/mapnik/version.hpp
index 5f19a43..afa1f3a 100644
--- a/include/mapnik/version.hpp
+++ b/include/mapnik/version.hpp
@@ -27,7 +27,7 @@
 
 #define MAPNIK_MAJOR_VERSION 3
 #define MAPNIK_MINOR_VERSION 0
-#define MAPNIK_PATCH_VERSION 13
+#define MAPNIK_PATCH_VERSION 14
 
 #define MAPNIK_VERSION (MAPNIK_MAJOR_VERSION*100000) + (MAPNIK_MINOR_VERSION*100) + (MAPNIK_PATCH_VERSION)
 
diff --git a/include/mapnik/xml_node.hpp b/include/mapnik/xml_node.hpp
index bf7130c..4dd08c6 100644
--- a/include/mapnik/xml_node.hpp
+++ b/include/mapnik/xml_node.hpp
@@ -53,8 +53,8 @@ class MAPNIK_DECL node_not_found: public std::exception
 {
 public:
     node_not_found(std::string const& node_name);
-    virtual const char* what() const throw();
-    ~node_not_found() throw ();
+    virtual const char* what() const noexcept;
+    ~node_not_found();
 private:
     std::string node_name_;
 protected:
@@ -65,8 +65,8 @@ class MAPNIK_DECL attribute_not_found: public std::exception
 {
 public:
     attribute_not_found(std::string const& node_name, std::string const& attribute_name);
-    virtual const char* what() const throw();
-    ~attribute_not_found() throw ();
+    virtual const char* what() const noexcept;
+    ~attribute_not_found();
 private:
     std::string node_name_;
     std::string attribute_name_;
@@ -78,8 +78,8 @@ class MAPNIK_DECL more_than_one_child: public std::exception
 {
 public:
     more_than_one_child(std::string const& node_name);
-    virtual const char* what() const throw();
-    ~more_than_one_child() throw ();
+    virtual const char* what() const noexcept;
+    ~more_than_one_child();
 private:
     std::string node_name_;
 protected:
diff --git a/plugins/input/gdal/build.py b/plugins/input/gdal/build.py
index 0db10c2..4dc631d 100644
--- a/plugins/input/gdal/build.py
+++ b/plugins/input/gdal/build.py
@@ -38,7 +38,7 @@ plugin_env['LIBS'] = []
 plugin_env.Append(LIBS=env['PLUGINS']['gdal']['lib'])
 
 if env['RUNTIME_LINK'] == 'static':
-    cmd = 'gdal-config --dep-libs'
+    cmd = '%s --dep-libs' % plugin_env['GDAL_CONFIG']
     plugin_env.ParseConfig(cmd)
 
 # Link Library to Dependencies
diff --git a/plugins/input/gdal/gdal_featureset.cpp b/plugins/input/gdal/gdal_featureset.cpp
index 1377322..f71535f 100644
--- a/plugins/input/gdal/gdal_featureset.cpp
+++ b/plugins/input/gdal/gdal_featureset.cpp
@@ -187,19 +187,9 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
     int width = end_x - x_off;
     int height = end_y - y_off;
 
-    // don't process almost invisible data
-    if (box.width() < 0.5)
-    {
-        width = 0;
-    }
-    if (box.height() < 0.5)
-    {
-        height = 0;
-    }
-
     //calculate actual box2d of returned raster
     box2d<double> feature_raster_extent(x_off, y_off, x_off + width, y_off + height);
-    intersect = t.backward(feature_raster_extent);
+    feature_raster_extent = t.backward(feature_raster_extent);
 
     MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Raster extent=" << raster_extent_;
     MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: View extent=" << intersect;
@@ -208,374 +198,380 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
 
     if (width > 0 && height > 0)
     {
-        double width_res = std::get<0>(q.resolution());
-        double height_res = std::get<1>(q.resolution());
-        int im_width = int(width_res * intersect.width() + 0.5);
-        int im_height = int(height_res * intersect.height() + 0.5);
-
-        double filter_factor = q.get_filter_factor();
-        im_width = int(im_width * filter_factor + 0.5);
-        im_height = int(im_height * filter_factor + 0.5);
-
-        // case where we need to avoid upsampling so that the
-        // image can be later scaled within raster_symbolizer
-        if (im_width >= width || im_height >= height)
-        {
-            im_width = width;
-            im_height = height;
-        }
-
-        if (im_width > 0 && im_height > 0)
+        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Image Size=(" << width << "," << height << ")";
+        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Reading band=" << band_;
+        if (band_ > 0) // we are querying a single band
         {
-            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Image Size=(" << im_width << "," << im_height << ")";
-            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Reading band=" << band_;
-            if (band_ > 0) // we are querying a single band
+            GDALRasterBand * band = dataset_.GetRasterBand(band_);
+            if (band_ > nbands_)
             {
-                GDALRasterBand * band = dataset_.GetRasterBand(band_);
-                if (band_ > nbands_)
-                {
-                    std::ostringstream s;
-                    s << "GDAL Plugin: " << band_ << " is an invalid band, dataset only has " << nbands_ << "bands";
-                    throw datasource_exception(s.str());
-                }
-                GDALDataType band_type = band->GetRasterDataType();
-                switch (band_type)
-                {
-                case GDT_Byte:
+                std::ostringstream s;
+                s << "GDAL Plugin: " << band_ << " is an invalid band, dataset only has " << nbands_ << "bands";
+                throw datasource_exception(s.str());
+            }
+            GDALDataType band_type = band->GetRasterDataType();
+            switch (band_type)
+            {
+            case GDT_Byte:
+            {
+                mapnik::image_gray8 image(width, height);
+                image.set(std::numeric_limits<std::uint8_t>::max());
+                raster_nodata = band->GetNoDataValue(&raster_has_nodata);
+                raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
+                                                 image.data(), image.width(), image.height(),
+                                                 GDT_Byte, 0, 0);
+                if (raster_io_error == CE_Failure)
                 {
-                    mapnik::image_gray8 image(im_width, im_height);
-                    image.set(std::numeric_limits<std::uint8_t>::max());
-                    raster_nodata = band->GetNoDataValue(&raster_has_nodata);
-                    raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
-                                                     image.data(), image.width(), image.height(),
-                                                     GDT_Byte, 0, 0);
-                    if (raster_io_error == CE_Failure)
-                    {
-                        throw datasource_exception(CPLGetLastErrorMsg());
-                    }
-                    mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
-                    // set nodata value to be used in raster colorizer
-                    if (nodata_value_) raster->set_nodata(*nodata_value_);
-                    else raster->set_nodata(raster_nodata);
-                    feature->set_raster(raster);
-                    break;
+                    throw datasource_exception(CPLGetLastErrorMsg());
                 }
-                case GDT_Float64:
-                case GDT_Float32:
+                mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, image, 0.0);
+                // set nodata value to be used in raster colorizer
+                if (nodata_value_) raster->set_nodata(*nodata_value_);
+                else raster->set_nodata(raster_nodata);
+                feature->set_raster(raster);
+                break;
+            }
+            case GDT_Float64:
+            case GDT_Float32:
+            {
+                mapnik::image_gray32f image(width, height);
+                image.set(std::numeric_limits<float>::max());
+                raster_nodata = band->GetNoDataValue(&raster_has_nodata);
+                raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
+                                                 image.data(), image.width(), image.height(),
+                                                 GDT_Float32, 0, 0);
+                if (raster_io_error == CE_Failure)
                 {
-                    mapnik::image_gray32f image(im_width, im_height);
-                    image.set(std::numeric_limits<float>::max());
-                    raster_nodata = band->GetNoDataValue(&raster_has_nodata);
-                    raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
-                                                     image.data(), image.width(), image.height(),
-                                                     GDT_Float32, 0, 0);
-                    if (raster_io_error == CE_Failure)
-                    {
-                        throw datasource_exception(CPLGetLastErrorMsg());
-                    }
-                    mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
-                    // set nodata value to be used in raster colorizer
-                    if (nodata_value_) raster->set_nodata(*nodata_value_);
-                    else raster->set_nodata(raster_nodata);
-                    feature->set_raster(raster);
-                    break;
+                    throw datasource_exception(CPLGetLastErrorMsg());
                 }
-                case GDT_UInt16:
+                mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, image, 0.0);
+                // set nodata value to be used in raster colorizer
+                if (nodata_value_) raster->set_nodata(*nodata_value_);
+                else raster->set_nodata(raster_nodata);
+                feature->set_raster(raster);
+                break;
+            }
+            case GDT_UInt16:
+            {
+                mapnik::image_gray16 image(width, height);
+                image.set(std::numeric_limits<std::uint16_t>::max());
+                raster_nodata = band->GetNoDataValue(&raster_has_nodata);
+                raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
+                                                 image.data(), image.width(), image.height(),
+                                                 GDT_UInt16, 0, 0);
+                if (raster_io_error == CE_Failure)
                 {
-                    mapnik::image_gray16 image(im_width, im_height);
-                    image.set(std::numeric_limits<std::uint16_t>::max());
-                    raster_nodata = band->GetNoDataValue(&raster_has_nodata);
-                    raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
-                                                     image.data(), image.width(), image.height(),
-                                                     GDT_UInt16, 0, 0);
-                    if (raster_io_error == CE_Failure)
-                    {
-                        throw datasource_exception(CPLGetLastErrorMsg());
-                    }
-                    mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
-                    // set nodata value to be used in raster colorizer
-                    if (nodata_value_) raster->set_nodata(*nodata_value_);
-                    else raster->set_nodata(raster_nodata);
-                    feature->set_raster(raster);
-                    break;
+                    throw datasource_exception(CPLGetLastErrorMsg());
                 }
-                default:
-                case GDT_Int16:
+                mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, image, 0.0);
+                // set nodata value to be used in raster colorizer
+                if (nodata_value_) raster->set_nodata(*nodata_value_);
+                else raster->set_nodata(raster_nodata);
+                feature->set_raster(raster);
+                break;
+            }
+            default:
+            case GDT_Int16:
+            {
+                mapnik::image_gray16s image(width, height);
+                image.set(std::numeric_limits<std::int16_t>::max());
+                raster_nodata = band->GetNoDataValue(&raster_has_nodata);
+                raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
+                                                 image.data(), image.width(), image.height(),
+                                                 GDT_Int16, 0, 0);
+                if (raster_io_error == CE_Failure)
                 {
-                    mapnik::image_gray16s image(im_width, im_height);
-                    image.set(std::numeric_limits<std::int16_t>::max());
-                    raster_nodata = band->GetNoDataValue(&raster_has_nodata);
-                    raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height,
-                                                     image.data(), image.width(), image.height(),
-                                                     GDT_Int16, 0, 0);
-                    if (raster_io_error == CE_Failure)
-                    {
-                        throw datasource_exception(CPLGetLastErrorMsg());
-                    }
-                    mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
-                    // set nodata value to be used in raster colorizer
-                    if (nodata_value_) raster->set_nodata(*nodata_value_);
-                    else raster->set_nodata(raster_nodata);
-                    feature->set_raster(raster);
-                    break;
-                }
+                    throw datasource_exception(CPLGetLastErrorMsg());
                 }
+                mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, image, 0.0);
+                // set nodata value to be used in raster colorizer
+                if (nodata_value_) raster->set_nodata(*nodata_value_);
+                else raster->set_nodata(raster_nodata);
+                feature->set_raster(raster);
+                break;
+            }
             }
-            else // working with all bands
+        }
+        else // working with all bands
+        {
+            mapnik::image_rgba8 image(width, height);
+            image.set(std::numeric_limits<std::uint32_t>::max());
+            for (int i = 0; i < nbands_; ++i)
             {
-                mapnik::image_rgba8 image(im_width, im_height);
-                image.set(std::numeric_limits<std::uint32_t>::max());
-                for (int i = 0; i < nbands_; ++i)
-                {
-                    GDALRasterBand * band = dataset_.GetRasterBand(i + 1);
+                GDALRasterBand * band = dataset_.GetRasterBand(i + 1);
 #ifdef MAPNIK_LOG
-                    get_overview_meta(band);
+                get_overview_meta(band);
 #endif
-                    GDALColorInterp color_interp = band->GetColorInterpretation();
-                    switch (color_interp)
-                    {
-                    case GCI_RedBand:
-                        red = band;
-                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found red band";
-                        break;
-                    case GCI_GreenBand:
-                        green = band;
-                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found green band";
-                        break;
-                    case GCI_BlueBand:
-                        blue = band;
-                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found blue band";
-                        break;
-                    case GCI_AlphaBand:
-                        alpha = band;
-                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found alpha band";
-                        break;
-                    case GCI_GrayIndex:
-                        grey = band;
-                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band";
-                        break;
-                    case GCI_PaletteIndex:
-                    {
-                        grey = band;
+                GDALColorInterp color_interp = band->GetColorInterpretation();
+                switch (color_interp)
+                {
+                case GCI_RedBand:
+                    red = band;
+                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found red band";
+                    break;
+                case GCI_GreenBand:
+                    green = band;
+                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found green band";
+                    break;
+                case GCI_BlueBand:
+                    blue = band;
+                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found blue band";
+                    break;
+                case GCI_AlphaBand:
+                    alpha = band;
+                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found alpha band";
+                    break;
+                case GCI_GrayIndex:
+                    grey = band;
+                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band";
+                    break;
+                case GCI_PaletteIndex:
+                {
+                    grey = band;
 #ifdef MAPNIK_LOG
-                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band, and colortable...";
-                        GDALColorTable *color_table = band->GetColorTable();
+                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band, and colortable...";
+                    GDALColorTable *color_table = band->GetColorTable();
 
-                        if (color_table)
-                        {
-                            int count = color_table->GetColorEntryCount();
-                            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color Table count=" << count;
+                    if (color_table)
+                    {
+                        int count = color_table->GetColorEntryCount();
+                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color Table count=" << count;
 
-                            for (int j = 0; j < count; j++)
-                            {
-                                const GDALColorEntry *ce = color_table->GetColorEntry (j);
-                                if (! ce) continue;
-                                MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color entry RGB=" << ce->c1 << "," <<ce->c2 << "," << ce->c3;
-                            }
+                        for (int j = 0; j < count; j++)
+                        {
+                            const GDALColorEntry *ce = color_table->GetColorEntry (j);
+                            if (! ce) continue;
+                            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color entry RGB=" << ce->c1 << "," <<ce->c2 << "," << ce->c3;
                         }
-#endif
-                        break;
                     }
-                    case GCI_Undefined:
+#endif
+                    break;
+                }
+                case GCI_Undefined:
 #if GDAL_VERSION_NUM <= 1730
-                        if (nbands_ == 4)
-                        {
-                            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming alpha band)";
-                            alpha = band;
-                        }
-                        else
-                        {
-                            MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming gray band)";
-                            grey = band;
-                        }
-#else
+                    if (nbands_ == 4)
+                    {
+                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming alpha band)";
+                        alpha = band;
+                    }
+                    else
+                    {
                         MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming gray band)";
                         grey = band;
-#endif
-                        break;
-                    default:
-                        MAPNIK_LOG_WARN(gdal) << "gdal_featureset: Band type unknown!";
-                        break;
                     }
+#else
+                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming gray band)";
+                    grey = band;
+#endif
+                    break;
+                default:
+                    MAPNIK_LOG_WARN(gdal) << "gdal_featureset: Band type unknown!";
+                    break;
                 }
-                if (red && green && blue)
+            }
+            if (red && green && blue)
+            {
+                MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing rgb bands...";
+                raster_nodata = red->GetNoDataValue(&raster_has_nodata);
+                GDALColorTable *color_table = red->GetColorTable();
+                bool has_nodata = nodata_value_ || raster_has_nodata;
+
+                // we can deduce the alpha channel from nodata in the Byte case
+                // by reusing the reading of R,G,B bands directly
+                if (has_nodata && !color_table && red->GetRasterDataType() == GDT_Byte)
                 {
-                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing rgb bands...";
-                    raster_nodata = red->GetNoDataValue(&raster_has_nodata);
-                    GDALColorTable *color_table = red->GetColorTable();
-                    bool has_nodata = nodata_value_ || raster_has_nodata;
-
-                    // we can deduce the alpha channel from nodata in the Byte case
-                    // by reusing the reading of R,G,B bands directly
-                    if (has_nodata && !color_table && red->GetRasterDataType() == GDT_Byte)
+                    double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata;
+                    // read the data in and create an alpha channel from the nodata values
+                    // TODO - we assume here the nodata value for the red band applies to all bands
+                    // more details about this at http://trac.osgeo.org/gdal/ticket/2734
+                    float* imageData = (float*)image.bytes();
+                    raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height,
+                                                    imageData, image.width(), image.height(),
+                                                    GDT_Float32, 0, 0);
+                    if (raster_io_error == CE_Failure) {
+                        throw datasource_exception(CPLGetLastErrorMsg());
+                    }
+                    int len = image.width() * image.height();
+                    for (int i = 0; i < len; ++i)
                     {
-                        double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata;
-                        // read the data in and create an alpha channel from the nodata values
-                        // TODO - we assume here the nodata value for the red band applies to all bands
-                        // more details about this at http://trac.osgeo.org/gdal/ticket/2734
-                        float* imageData = (float*)image.bytes();
-                        raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height,
-                                                        imageData, image.width(), image.height(),
-                                                        GDT_Float32, 0, 0);
-                        if (raster_io_error == CE_Failure) {
-                            throw datasource_exception(CPLGetLastErrorMsg());
+                        if (std::fabs(apply_nodata - imageData[i]) < nodata_tolerance_)
+                        {
+                            *reinterpret_cast<unsigned *>(&imageData[i]) = 0;
                         }
-                        int len = image.width() * image.height();
-                        for (int i = 0; i < len; ++i)
+                        else
                         {
-                            if (std::fabs(apply_nodata - imageData[i]) < nodata_tolerance_)
-                            {
-                                *reinterpret_cast<unsigned *>(&imageData[i]) = 0;
-                            }
-                            else
-                            {
-                                *reinterpret_cast<unsigned *>(&imageData[i]) = 0xFFFFFFFF;
-                            }
+                            *reinterpret_cast<unsigned *>(&imageData[i]) = 0xFFFFFFFF;
                         }
                     }
+                }
 
-                    /* Use dataset RasterIO in priority in 99.9% of the cases */
-                    if( red->GetBand() == 1 && green->GetBand() == 2 && blue->GetBand() == 3 )
+                /* Use dataset RasterIO in priority in 99.9% of the cases */
+                if( red->GetBand() == 1 && green->GetBand() == 2 && blue->GetBand() == 3 )
+                {
+                    int nBandsToRead = 3;
+                    if( alpha != nullptr && alpha->GetBand() == 4 && !raster_has_nodata )
                     {
-                        int nBandsToRead = 3;
-                        if( alpha != nullptr && alpha->GetBand() == 4 && !raster_has_nodata )
-                        {
-                            nBandsToRead = 4;
-                            alpha = nullptr; // to avoid reading it again afterwards
-                        }
-                        raster_io_error = dataset_.RasterIO(GF_Read, x_off, y_off, width, height,
-                                                            image.bytes(),
-                                                            image.width(), image.height(), GDT_Byte,
-                                                            nBandsToRead, nullptr,
-                                                            4, 4 * image.width(), 1);
-                        if (raster_io_error == CE_Failure) {
-                            throw datasource_exception(CPLGetLastErrorMsg());
-                        }
+                        nBandsToRead = 4;
+                        alpha = nullptr; // to avoid reading it again afterwards
                     }
-                    else
-                    {
-                        raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 0,
-                                                        image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
-                        if (raster_io_error == CE_Failure) {
-                            throw datasource_exception(CPLGetLastErrorMsg());
-                        }
-                        raster_io_error = green->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 1,
-                                                        image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
-                        if (raster_io_error == CE_Failure) {
-                            throw datasource_exception(CPLGetLastErrorMsg());
-                        }
-                        raster_io_error = blue->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 2,
-                                                        image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
-                        if (raster_io_error == CE_Failure) {
-                            throw datasource_exception(CPLGetLastErrorMsg());
-                        }
+                    raster_io_error = dataset_.RasterIO(GF_Read, x_off, y_off, width, height,
+                                                        image.bytes(),
+                                                        image.width(), image.height(), GDT_Byte,
+                                                        nBandsToRead, nullptr,
+                                                        4, 4 * image.width(), 1);
+                    if (raster_io_error == CE_Failure) {
+                        throw datasource_exception(CPLGetLastErrorMsg());
                     }
-
-                    // In the case we skipped initializing the alpha channel
-                    if (has_nodata && !color_table && red->GetRasterDataType() == GDT_Byte)
-                    {
-                        double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata;
-                        if( apply_nodata >= 0 && apply_nodata <= 255 )
-                        {
-                            int len = image.width() * image.height();
-                            GByte* pabyBytes = (GByte*) image.bytes();
-                            for (int i = 0; i < len; ++i)
-                            {
-                                // TODO - we assume here the nodata value for the red band applies to all bands
-                                // more details about this at http://trac.osgeo.org/gdal/ticket/2734
-                                if (std::fabs(apply_nodata - pabyBytes[4*i]) < nodata_tolerance_)
-                                    pabyBytes[4*i + 3] = 0;
-                                else
-                                    pabyBytes[4*i + 3] = 255;
-                            }
-                        }
+                }
+                else
+                {
+                    raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 0,
+                                                    image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
+                    if (raster_io_error == CE_Failure) {
+                        throw datasource_exception(CPLGetLastErrorMsg());
+                    }
+                    raster_io_error = green->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 1,
+                                                    image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
+                    if (raster_io_error == CE_Failure) {
+                        throw datasource_exception(CPLGetLastErrorMsg());
+                    }
+                    raster_io_error = blue->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 2,
+                                                    image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
+                    if (raster_io_error == CE_Failure) {
+                        throw datasource_exception(CPLGetLastErrorMsg());
                     }
                 }
-                else if (grey)
+
+                // In the case we skipped initializing the alpha channel
+                if (has_nodata && !color_table && red->GetRasterDataType() == GDT_Byte)
                 {
-                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing gray band...";
-                    raster_nodata = grey->GetNoDataValue(&raster_has_nodata);
-                    GDALColorTable* color_table = grey->GetColorTable();
-                    bool has_nodata = nodata_value_ || raster_has_nodata;
-                    if (!color_table && has_nodata)
+                    double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata;
+                    if( apply_nodata >= 0 && apply_nodata <= 255 )
                     {
-                        double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata;
-                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: applying nodata value for layer=" << apply_nodata;
-                        // first read the data in and create an alpha channel from the nodata values
-                        float* imageData = (float*)image.bytes();
-                        raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height,
-                                                         imageData, image.width(), image.height(),
-                                                         GDT_Float32, 0, 0);
-                        if (raster_io_error == CE_Failure)
-                        {
-                            throw datasource_exception(CPLGetLastErrorMsg());
-                        }
                         int len = image.width() * image.height();
+                        GByte* pabyBytes = (GByte*) image.bytes();
                         for (int i = 0; i < len; ++i)
                         {
-                            if (std::fabs(apply_nodata - imageData[i]) < nodata_tolerance_)
-                            {
-                                *reinterpret_cast<unsigned *>(&imageData[i]) = 0;
-                            }
+                            // TODO - we assume here the nodata value for the red band applies to all bands
+                            // more details about this at http://trac.osgeo.org/gdal/ticket/2734
+                            if (std::fabs(apply_nodata - pabyBytes[4*i]) < nodata_tolerance_)
+                                pabyBytes[4*i + 3] = 0;
                             else
-                            {
-                                *reinterpret_cast<unsigned *>(&imageData[i]) = 0xFFFFFFFF;
-                            }
+                                pabyBytes[4*i + 3] = 255;
                         }
                     }
-
-                    raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 0,
-                                                     image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
+                }
+            }
+            else if (grey)
+            {
+                MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing gray band...";
+                raster_nodata = grey->GetNoDataValue(&raster_has_nodata);
+                GDALColorTable* color_table = grey->GetColorTable();
+                bool has_nodata = nodata_value_ || raster_has_nodata;
+                if (!color_table && has_nodata)
+                {
+                    double apply_nodata = nodata_value_ ? *nodata_value_ : raster_nodata;
+                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: applying nodata value for layer=" << apply_nodata;
+                    // first read the data in and create an alpha channel from the nodata values
+                    float* imageData = (float*)image.bytes();
+                    raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height,
+                                                     imageData, image.width(), image.height(),
+                                                     GDT_Float32, 0, 0);
                     if (raster_io_error == CE_Failure)
                     {
                         throw datasource_exception(CPLGetLastErrorMsg());
                     }
-
-                    raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.bytes() + 1,
-                                                     image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
-                    if (raster_io_error == CE_Failure)
+                    int len = image.width() * image.height();
+                    for (int i = 0; i < len; ++i)
                     {
-                        throw datasource_exception(CPLGetLastErrorMsg());
+                        if (std::fabs(apply_nodata - imageData[i]) < nodata_tolerance_)
+                        {
+                            *reinterpret_cast<unsigned *>(&imageData[i]) = 0;
+                        }
+                        else
+                        {
+                            *reinterpret_cast<unsigned *>(&imageData[i]) = 0xFFFFFFFF;
+                        }
                     }
+                }
 
-                    raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.bytes() + 2,
-                                                     image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
+                raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 0,
+                                                 image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
+                if (raster_io_error == CE_Failure)
+                {
+                    throw datasource_exception(CPLGetLastErrorMsg());
+                }
 
-                    if (raster_io_error == CE_Failure)
-                    {
-                        throw datasource_exception(CPLGetLastErrorMsg());
-                    }
+                raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.bytes() + 1,
+                                                 image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
+                if (raster_io_error == CE_Failure)
+                {
+                    throw datasource_exception(CPLGetLastErrorMsg());
+                }
 
-                    if (color_table)
+                raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.bytes() + 2,
+                                                 image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
+
+                if (raster_io_error == CE_Failure)
+                {
+                    throw datasource_exception(CPLGetLastErrorMsg());
+                }
+
+                if (color_table)
+                {
+                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Loading color table...";
+                    for (unsigned y = 0; y < image.height(); ++y)
                     {
-                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Loading color table...";
-                        for (unsigned y = 0; y < image.height(); ++y)
+                        unsigned int* row = image.get_row(y);
+                        for (unsigned x = 0; x < image.width(); ++x)
                         {
-                            unsigned int* row = image.get_row(y);
-                            for (unsigned x = 0; x < image.width(); ++x)
+                            unsigned value = row[x] & 0xff;
+                            const GDALColorEntry *ce = color_table->GetColorEntry(value);
+                            if (ce)
+                            {
+                                row[x] = (ce->c4 << 24)| (ce->c3 << 16) |  (ce->c2 << 8) | (ce->c1) ;
+                            }
+                            else
                             {
-                                unsigned value = row[x] & 0xff;
-                                const GDALColorEntry *ce = color_table->GetColorEntry(value);
-                                if (ce)
-                                {
-                                    row[x] = (ce->c4 << 24)| (ce->c3 << 16) |  (ce->c2 << 8) | (ce->c1) ;
-                                }
-                                else
-                                {
-                                    // make lacking color entry fully alpha
-                                    // note - gdal_translate makes black
-                                    row[x] = 0;
-                                }
+                                // make lacking color entry fully alpha
+                                // note - gdal_translate makes black
+                                row[x] = 0;
                             }
                         }
                     }
                 }
-                if (alpha)
+            }
+            if (alpha)
+            {
+                MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: processing alpha band...";
+                if (!raster_has_nodata)
                 {
-                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: processing alpha band...";
+                    raster_io_error = alpha->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 3,
+                                                      image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
+                    if (raster_io_error == CE_Failure) {
+                        throw datasource_exception(CPLGetLastErrorMsg());
+                    }
+                }
+                else
+                {
+                    MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of alpha band";
+                }
+            }
+            else if( dataset_.GetRasterCount() > 0 && dataset_.GetRasterBand(1) )
+            {
+                // Check if we have a non-alpha mask band (for example a TIFF internal mask)
+                int flags = dataset_.GetRasterBand(1)->GetMaskFlags();
+                GDALRasterBand* mask = 0;
+                if (flags == GMF_PER_DATASET)
+                {
+                    mask = dataset_.GetRasterBand(1)->GetMaskBand();
+                }
+                if (mask)
+                {
+                    MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: found and processing mask band...";
                     if (!raster_has_nodata)
                     {
-                        raster_io_error = alpha->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 3,
+                        raster_io_error = mask->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 3,
                                                           image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
                         if (raster_io_error == CE_Failure) {
                             throw datasource_exception(CPLGetLastErrorMsg());
@@ -583,48 +579,22 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q)
                     }
                     else
                     {
-                        MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of alpha band";
+                        MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of mask band";
                     }
                 }
-                else if( dataset_.GetRasterCount() > 0 && dataset_.GetRasterBand(1) )
-                {
-                    // Check if we have a non-alpha mask band (for example a TIFF internal mask)
-                    int flags = dataset_.GetRasterBand(1)->GetMaskFlags();
-                    GDALRasterBand* mask = 0;
-                    if (flags == GMF_PER_DATASET)
-                    {
-                        mask = dataset_.GetRasterBand(1)->GetMaskBand();
-                    }
-                    if (mask)
-                    {
-                        MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: found and processing mask band...";
-                        if (!raster_has_nodata)
-                        {
-                            raster_io_error = mask->RasterIO(GF_Read, x_off, y_off, width, height, image.bytes() + 3,
-                                                              image.width(), image.height(), GDT_Byte, 4, 4 * image.width());
-                            if (raster_io_error == CE_Failure) {
-                                throw datasource_exception(CPLGetLastErrorMsg());
-                            }
-                        }
-                        else
-                        {
-                            MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of mask band";
-                        }
-                    }
-                }
-                mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, image, filter_factor);
-                // set nodata value to be used in raster colorizer
-                if (nodata_value_) raster->set_nodata(*nodata_value_);
-                else raster->set_nodata(raster_nodata);
-                feature->set_raster(raster);
-            }
-            // report actual/original source nodata in feature attributes
-            if (raster_has_nodata)
-            {
-                feature->put("nodata",raster_nodata);
             }
-            return feature;
+            mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, image, 0.0);
+            // set nodata value to be used in raster colorizer
+            if (nodata_value_) raster->set_nodata(*nodata_value_);
+            else raster->set_nodata(raster_nodata);
+            feature->set_raster(raster);
+        }
+        // report actual/original source nodata in feature attributes
+        if (raster_has_nodata)
+        {
+            feature->put("nodata",raster_nodata);
         }
+        return feature;
     }
     return feature_ptr();
 }
diff --git a/plugins/input/ogr/build.py b/plugins/input/ogr/build.py
index 143289d..1681d0b 100644
--- a/plugins/input/ogr/build.py
+++ b/plugins/input/ogr/build.py
@@ -42,7 +42,7 @@ plugin_env['LIBS'] = []
 plugin_env.Append(LIBS=env['PLUGINS']['ogr']['lib'])
 
 if env['RUNTIME_LINK'] == 'static':
-    cmd = 'gdal-config --dep-libs'
+    cmd = '%s --dep-libs' % plugin_env['GDAL_CONFIG']
     plugin_env.ParseConfig(cmd)
 
 # Link Library to Dependencies
diff --git a/plugins/input/raster/raster_featureset.cpp b/plugins/input/raster/raster_featureset.cpp
index 26cac96..edea943 100644
--- a/plugins/input/raster/raster_featureset.cpp
+++ b/plugins/input/raster/raster_featureset.cpp
@@ -89,33 +89,34 @@ feature_ptr raster_featureset<LookupPolicy>::next()
                     box2d<double> intersect = bbox_.intersect(curIter_->envelope());
                     box2d<double> ext = t.forward(intersect);
                     box2d<double> rem = policy_.transform(ext);
-                    if (ext.width() > 0.5 && ext.height() > 0.5 )
-                    {
-                        // select minimum raster containing whole ext
-                        int x_off = static_cast<int>(std::floor(ext.minx()));
-                        int y_off = static_cast<int>(std::floor(ext.miny()));
-                        int end_x = static_cast<int>(std::ceil(ext.maxx()));
-                        int end_y = static_cast<int>(std::ceil(ext.maxy()));
-
-                        // clip to available data
-                        if (x_off < 0) x_off = 0;
-                        if (y_off < 0) y_off = 0;
-                        if (end_x > image_width)  end_x = image_width;
-                        if (end_y > image_height) end_y = image_height;
-
-                        int width = end_x - x_off;
-                        int height = end_y - y_off;
-
-                        // calculate actual box2d of returned raster
-                        box2d<double> feature_raster_extent(rem.minx() + x_off,
-                                                            rem.miny() + y_off,
-                                                            rem.maxx() + x_off + width,
-                                                            rem.maxy() + y_off + height);
-                        intersect = t.backward(feature_raster_extent);
-                        mapnik::image_any data = reader->read(x_off, y_off, width, height);
-                        mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(intersect, std::move(data), 1.0);
-                        feature->set_raster(raster);
-                    }
+                    // select minimum raster containing whole ext
+                    int x_off = static_cast<int>(std::floor(ext.minx()));
+                    int y_off = static_cast<int>(std::floor(ext.miny()));
+                    int end_x = static_cast<int>(std::ceil(ext.maxx()));
+                    int end_y = static_cast<int>(std::ceil(ext.maxy()));
+
+                    // clip to available data
+                    if (x_off >= image_width) x_off = image_width - 1;
+                    if (y_off >= image_width) y_off = image_width - 1;
+                    if (x_off < 0) x_off = 0;
+                    if (y_off < 0) y_off = 0;
+                    if (end_x > image_width)  end_x = image_width;
+                    if (end_y > image_height) end_y = image_height;
+
+                    int width = end_x - x_off;
+                    int height = end_y - y_off;
+                    if (width < 1) width = 1;
+                    if (height < 1) height = 1;
+
+                    // calculate actual box2d of returned raster
+                    box2d<double> feature_raster_extent(rem.minx() + x_off,
+                                                        rem.miny() + y_off,
+                                                        rem.maxx() + x_off + width,
+                                                        rem.maxy() + y_off + height);
+                    feature_raster_extent = t.backward(feature_raster_extent);
+                    mapnik::image_any data = reader->read(x_off, y_off, width, height);
+                    mapnik::raster_ptr raster = std::make_shared<mapnik::raster>(feature_raster_extent, intersect, std::move(data), 1.0);
+                    feature->set_raster(raster);
                 }
             }
         }
diff --git a/plugins/input/raster/raster_info.cpp b/plugins/input/raster/raster_info.cpp
index 54b17c4..676cd5a 100644
--- a/plugins/input/raster/raster_info.cpp
+++ b/plugins/input/raster/raster_info.cpp
@@ -44,7 +44,7 @@ raster_info::raster_info(const raster_info& rhs)
 {
 }
 
-void raster_info::swap(raster_info& other) //throw()
+void raster_info::swap(raster_info& other)
 {
     std::swap(file_,other.file_);
     std::swap(format_,other.format_);
diff --git a/plugins/input/shape/dbfile.cpp b/plugins/input/shape/dbfile.cpp
index d64d373..a8505b0 100644
--- a/plugins/input/shape/dbfile.cpp
+++ b/plugins/input/shape/dbfile.cpp
@@ -137,7 +137,7 @@ const field_descriptor& dbf_file::descriptor(int col) const
 }
 
 
-void dbf_file::add_attribute(int col, mapnik::transcoder const& tr, mapnik::feature_impl & f) const throw()
+void dbf_file::add_attribute(int col, mapnik::transcoder const& tr, mapnik::feature_impl & f) const
 {
     using namespace boost::spirit;
 
diff --git a/plugins/input/shape/dbfile.hpp b/plugins/input/shape/dbfile.hpp
index 9ff0224..86807f3 100644
--- a/plugins/input/shape/dbfile.hpp
+++ b/plugins/input/shape/dbfile.hpp
@@ -77,7 +77,7 @@ public:
     field_descriptor const& descriptor(int col) const;
     void move_to(int index);
     std::string string_value(int col) const;
-    void add_attribute(int col, mapnik::transcoder const& tr, mapnik::feature_impl & f) const throw();
+    void add_attribute(int col, mapnik::transcoder const& tr, mapnik::feature_impl & f) const;
 private:
     void read_header();
     int read_short();
diff --git a/scripts/check-padding b/scripts/check-padding
index b10d34b..107d636 100755
--- a/scripts/check-padding
+++ b/scripts/check-padding
@@ -26,7 +26,7 @@ function add() {
 CXX=${CXX:-clang++}
 
 function compile() {
-    ${CXX} -o ${app} ${cpp} -Wpadded -I./ -isystem ./mason_packages/.link/include `mapnik-config --all-flags` -Ideps -Lsrc -Ideps/agg/include -Iinclude
+    ${CXX} -o ${app} ${cpp} -Wpadded -I./ -I./deps/mapbox/variant/include -isystem ./mason_packages/.link/include -std=c++11 -Ideps -Lsrc -Ideps/agg/include -Iinclude
 }
 
 if [[ ${1:-unset} == "unset" ]] || [[ ${2:-unset} == "unset" ]] || [[ $@ == '-h' ]] || [[ $@ == '--help' ]]; then
diff --git a/scripts/travis-common.sh b/scripts/travis-common.sh
index 288fcc1..d3ce79f 100644
--- a/scripts/travis-common.sh
+++ b/scripts/travis-common.sh
@@ -46,15 +46,6 @@ git_submodule_update () {
     git submodule update "$@"
 }
 
-# install and call pip
-pip () {
-    if ! which pip >/dev/null; then
-        easy_install --user pip && \
-        export PATH="$HOME/Library/Python/2.7/bin:$PATH"
-    fi
-    command pip "$@"
-}
-
 # commit_message_contains TEXT
 #   - returns 0 (true) if TEXT is found in commit message
 #   - case-insensitive, plain-text search, not regex
@@ -92,13 +83,7 @@ configure () {
 }
 
 coverage () {
-    ./mason_packages/.link/bin/cpp-coveralls \
-        --gcov ${LLVM_COV} \
-        --exclude mason_packages \
-        --exclude .sconf_temp --exclude benchmark --exclude deps \
-        --exclude scons --exclude test --exclude demo --exclude docs \
-        --exclude fonts \
-        > /dev/null
+    ./codecov -x "llvm-cov gcov" -Z
 }
 
 trigger_downstream() {
diff --git a/src/config_error.cpp b/src/config_error.cpp
index 8de7970..b5b069f 100644
--- a/src/config_error.cpp
+++ b/src/config_error.cpp
@@ -37,7 +37,7 @@ config_error::config_error(std::string const& what,
 {
 }
 
-char const* config_error::what() const throw()
+char const* config_error::what() const noexcept
 {
     msg_ = what_;
     if (!node_name_.empty())
diff --git a/src/font_engine_freetype.cpp b/src/font_engine_freetype.cpp
index 9721d70..4d504a8 100644
--- a/src/font_engine_freetype.cpp
+++ b/src/font_engine_freetype.cpp
@@ -51,9 +51,7 @@ extern "C"
 
 namespace mapnik
 {
-
-freetype_engine::freetype_engine() {}
-freetype_engine::~freetype_engine() {}
+template class MAPNIK_DECL singleton<freetype_engine, CreateUsingNew>;
 
 bool freetype_engine::is_font_file(std::string const& file_name)
 {
@@ -80,6 +78,11 @@ unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char *
 
 bool freetype_engine::register_font(std::string const& file_name)
 {
+    return instance().register_font_impl(file_name);
+}
+
+bool freetype_engine::register_font_impl(std::string const& file_name)
+{
 #ifdef MAPNIK_THREADSAFE
     std::lock_guard<std::mutex> lock(mutex_);
 #endif
@@ -162,6 +165,11 @@ bool freetype_engine::register_font_impl(std::string const& file_name,
 
 bool freetype_engine::register_fonts(std::string const& dir, bool recurse)
 {
+    return instance().register_fonts_impl(dir, recurse);
+}
+
+bool freetype_engine::register_fonts_impl(std::string const& dir, bool recurse)
+{
 #ifdef MAPNIK_THREADSAFE
     std::lock_guard<std::mutex> lock(mutex_);
 #endif
@@ -216,8 +224,12 @@ bool freetype_engine::register_fonts_impl(std::string const& dir,
     return success;
 }
 
+std::vector<std::string> freetype_engine::face_names()
+{
+    return instance().face_names_impl();
+}
 
-std::vector<std::string> freetype_engine::face_names ()
+std::vector<std::string> freetype_engine::face_names_impl()
 {
     std::vector<std::string> names;
     for (auto const& kv : global_font_file_mapping_)
@@ -229,11 +241,21 @@ std::vector<std::string> freetype_engine::face_names ()
 
 freetype_engine::font_file_mapping_type const& freetype_engine::get_mapping()
 {
+    return instance().get_mapping_impl();
+}
+
+freetype_engine::font_file_mapping_type const& freetype_engine::get_mapping_impl()
+{
     return global_font_file_mapping_;
 }
 
 freetype_engine::font_memory_cache_type & freetype_engine::get_cache()
 {
+    return instance().get_cache_impl();
+}
+
+freetype_engine::font_memory_cache_type & freetype_engine::get_cache_impl()
+{
     return global_memory_fonts_;
 }
 
@@ -242,6 +264,14 @@ bool freetype_engine::can_open(std::string const& face_name,
                                font_file_mapping_type const& font_file_mapping,
                                font_file_mapping_type const& global_font_file_mapping)
 {
+    return instance().can_open_impl(face_name, library, font_file_mapping, global_font_file_mapping);
+}
+
+bool freetype_engine::can_open_impl(std::string const& face_name,
+                               font_library & library,
+                               font_file_mapping_type const& font_file_mapping,
+                               font_file_mapping_type const& global_font_file_mapping)
+{
     bool found_font_file = false;
     font_file_mapping_type::const_iterator itr = font_file_mapping.find(face_name);
     if (itr != font_file_mapping.end())
@@ -279,12 +309,12 @@ bool freetype_engine::can_open(std::string const& face_name,
     return true;
 }
 
-face_ptr freetype_engine::create_face(std::string const& family_name,
-                                      font_library & library,
-                                      freetype_engine::font_file_mapping_type const& font_file_mapping,
-                                      freetype_engine::font_memory_cache_type const& font_cache,
-                                      freetype_engine::font_file_mapping_type const& global_font_file_mapping,
-                                      freetype_engine::font_memory_cache_type & global_memory_fonts)
+face_ptr freetype_engine::create_face_impl(std::string const& family_name,
+                                           font_library & library,
+                                           freetype_engine::font_file_mapping_type const& font_file_mapping,
+                                           freetype_engine::font_memory_cache_type const& font_cache,
+                                           freetype_engine::font_file_mapping_type const& global_font_file_mapping,
+                                           freetype_engine::font_memory_cache_type & global_memory_fonts)
 {
     bool found_font_file = false;
     font_file_mapping_type::const_iterator itr = font_file_mapping.find(family_name);
@@ -356,6 +386,20 @@ face_ptr freetype_engine::create_face(std::string const& family_name,
     return face_ptr();
 }
 
+face_ptr freetype_engine::create_face(std::string const& family_name,
+                                      font_library & library,
+                                      freetype_engine::font_file_mapping_type const& font_file_mapping,
+                                      freetype_engine::font_memory_cache_type const& font_cache,
+                                      freetype_engine::font_file_mapping_type const& global_font_file_mapping,
+                                      freetype_engine::font_memory_cache_type & global_memory_fonts)
+{
+    return instance().create_face_impl(family_name,
+                                       library,
+                                       font_file_mapping,
+                                       font_cache,
+                                       global_font_file_mapping,
+                                       global_memory_fonts);
+}
 
 face_manager::face_manager(font_library & library,
                            freetype_engine::font_file_mapping_type const& font_file_mapping,
@@ -386,8 +430,8 @@ face_ptr face_manager::get_face(std::string const& name)
                                                      library_,
                                                      font_file_mapping_,
                                                      font_memory_cache_,
-                                                     freetype_engine::get_mapping(),
-                                                     freetype_engine::get_cache());
+                                                     freetype_engine::instance().get_mapping(),
+                                                     freetype_engine::instance().get_cache());
         if (face)
         {
             face_cache_->emplace(name, face);
@@ -441,10 +485,4 @@ face_set_ptr face_manager::get_face_set(std::string const& name, boost::optional
     }
 }
 
-#ifdef MAPNIK_THREADSAFE
-std::mutex freetype_engine::mutex_;
-#endif
-freetype_engine::font_file_mapping_type freetype_engine::global_font_file_mapping_;
-freetype_engine::font_memory_cache_type freetype_engine::global_memory_fonts_;
-
 }
diff --git a/src/gradient.cpp b/src/gradient.cpp
index 0c9c6b8..6a760ba 100644
--- a/src/gradient.cpp
+++ b/src/gradient.cpp
@@ -121,7 +121,7 @@ stop_array const& gradient::get_stop_array() const
     return stops_;
 }
 
-void gradient::swap(gradient& other) throw()
+void gradient::swap(gradient& other) noexcept
 {
     std::swap(gradient_type_, other.gradient_type_);
     std::swap(stops_, other.stops_);
diff --git a/src/image_scaling.cpp b/src/image_scaling.cpp
index 413948c..4c6bb49 100644
--- a/src/image_scaling.cpp
+++ b/src/image_scaling.cpp
@@ -133,6 +133,7 @@ void scale_image_agg(T & target, T const& source, scaling_method_e scaling_metho
 
     // create a scaling matrix
     agg::trans_affine img_mtx;
+    img_mtx *= agg::trans_affine_translation(x_off_f, y_off_f);
     img_mtx /= agg::trans_affine_scaling(image_ratio_x, image_ratio_y);
 
     // create a linear interpolator for our scaling matrix
@@ -141,11 +142,10 @@ void scale_image_agg(T & target, T const& source, scaling_method_e scaling_metho
     double scaled_width = target.width();
     double scaled_height = target.height();
     ras.reset();
-    ras.move_to_d(x_off_f,                y_off_f);
-    ras.line_to_d(x_off_f + scaled_width, y_off_f);
-    ras.line_to_d(x_off_f + scaled_width, y_off_f + scaled_height);
-    ras.line_to_d(x_off_f,                y_off_f + scaled_height);
-
+    ras.move_to_d(0.0, 0.0);
+    ras.line_to_d(scaled_width, 0.0);
+    ras.line_to_d(scaled_width, scaled_height);
+    ras.line_to_d(0.0, scaled_height);
     if (scaling_method == SCALING_NEAR)
     {
         using span_gen_type = typename detail::agg_scaling_traits<image_type>::span_image_filter;
diff --git a/src/image_view.cpp b/src/image_view.cpp
index 44e4d77..54028bf 100644
--- a/src/image_view.cpp
+++ b/src/image_view.cpp
@@ -29,7 +29,6 @@
 namespace mapnik
 {
 
-template class MAPNIK_DECL image_view<image_null>;
 template class MAPNIK_DECL image_view<image_rgba8>;
 template class MAPNIK_DECL image_view<image_gray8>;
 template class MAPNIK_DECL image_view<image_gray8s>;
diff --git a/src/json/mapnik_json_geometry_parser.cpp b/src/json/mapnik_json_geometry_parser.cpp
index 278d2c4..a517e86 100644
--- a/src/json/mapnik_json_geometry_parser.cpp
+++ b/src/json/mapnik_json_geometry_parser.cpp
@@ -37,7 +37,15 @@ bool from_geojson(std::string const& json, mapnik::geometry::geometry<double> &
     standard::space_type space;
     char const* start = json.c_str();
     char const* end = start + json.length();
-    return qi::phrase_parse(start, end, g, space, geom);
+    try
+    {
+        if (!qi::phrase_parse(start, end, g, space, geom))
+        {
+            throw std::runtime_error("Can't parser GeoJSON Geometry");
+        }
+    }
+    catch (...) { return false; }
+    return true;
 }
 
 }}
diff --git a/src/load_map.cpp b/src/load_map.cpp
index bf6324d..5a8e122 100644
--- a/src/load_map.cpp
+++ b/src/load_map.cpp
@@ -84,7 +84,7 @@ using boost::optional;
 
 constexpr unsigned name2int(const char *str, int off = 0)
 {
-    return !str[off] ? 5381 : (name2int(str, off+1)*33) ^ static_cast<unsigned>(str[off]);
+    return !str[off] ? 5381 : (name2int(str, off + 1) * 33) ^ static_cast<unsigned>(str[off]);
 }
 
 class map_parser : util::noncopyable
@@ -133,7 +133,7 @@ private:
     void find_unused_nodes_recursive(xml_node const& node, std::string & error_text);
     std::string ensure_relative_to_xml(boost::optional<std::string> const& opt_path);
     void ensure_exists(std::string const& file_path);
-    void check_styles(Map const & map) const throw (config_error);
+    void check_styles(Map const & map);
     boost::optional<color> get_opt_color_attr(boost::property_tree::ptree const& node,
                                               std::string const& name);
 
@@ -1155,10 +1155,14 @@ void map_parser::parse_shield_symbolizer(rule & rule, xml_node const& node)
         if (placement_type)
         {
             placements = placements::registry::instance().from_xml(*placement_type, node, fontsets_, true);
-        } else {
+            if (!placements)
+                return;
+        }
+        else
+        {
             placements = std::make_shared<text_placements_dummy>();
+            placements->defaults.from_xml(node, fontsets_, true);
         }
-        placements->defaults.from_xml(node, fontsets_, true);
         if (strict_ &&
             !placements->defaults.format_defaults.fontset)
         {
@@ -1691,7 +1695,7 @@ void map_parser::find_unused_nodes_recursive(xml_node const& node, std::string &
     }
 }
 
-void map_parser::check_styles(Map const & map) const throw (config_error)
+void map_parser::check_styles(Map const & map)
 {
     for (auto const & layer : map.layers())
     {
diff --git a/src/map.cpp b/src/map.cpp
index ec0d9f8..e94d061 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -285,7 +285,7 @@ std::map<std::string,font_set> & Map::fontsets()
 bool Map::register_fonts(std::string const& dir, bool recurse)
 {
     font_library library;
-    return freetype_engine::register_fonts_impl(dir, library, font_file_mapping_, recurse);
+    return freetype_engine::instance().register_fonts_impl(dir, library, font_file_mapping_, recurse);
 }
 
 bool Map::load_fonts()
diff --git a/src/tiff_reader.cpp b/src/tiff_reader.cpp
index 157e4d0..81ac112 100644
--- a/src/tiff_reader.cpp
+++ b/src/tiff_reader.cpp
@@ -2,7 +2,7 @@
  *
  * This file is part of Mapnik (c++ mapping toolkit)
  *
- * Copyright (C) 2015 Artem Pavlenko
+ * Copyright (C) 2017 Artem Pavlenko
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -162,8 +162,12 @@ private:
     tiff_reader(const tiff_reader&);
     tiff_reader& operator=(const tiff_reader&);
     void init();
-    void read_generic(std::size_t x,std::size_t y,image_rgba8& image);
-    void read_stripped(std::size_t x,std::size_t y,image_rgba8& image);
+
+    template <typename ImageData>
+    void read_generic(std::size_t x,std::size_t y, ImageData & image);
+
+    template <typename ImageData>
+    void read_stripped(std::size_t x,std::size_t y, ImageData & image);
 
     template <typename ImageData>
     void read_tiled(std::size_t x,std::size_t y, ImageData & image);
@@ -257,25 +261,24 @@ void tiff_reader<T>::init()
     TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&photometric_);
     TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &bands_);
 
-    MAPNIK_LOG_DEBUG(tiff_reader) << "bits per sample: " << bps_;
-    MAPNIK_LOG_DEBUG(tiff_reader) << "sample format: " << sample_format_;
-    MAPNIK_LOG_DEBUG(tiff_reader) << "photometric: " << photometric_;
-    MAPNIK_LOG_DEBUG(tiff_reader) << "bands: " << bands_;
+    MAPNIK_LOG_DEBUG(tiff_reader) << "bits per sample: " << bps_ ;
+    MAPNIK_LOG_DEBUG(tiff_reader) << "sample format: " << sample_format_ ;
+    MAPNIK_LOG_DEBUG(tiff_reader) << "photometric: " << photometric_ ;
+    MAPNIK_LOG_DEBUG(tiff_reader) << "bands: " << bands_ ;
 
     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width_);
     TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height_);
 
     TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar_config_);
     TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression_ );
-    TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip_);
 
     std::uint16_t orientation;
     if (TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation) == 0)
     {
         orientation = 1;
     }
-    MAPNIK_LOG_DEBUG(tiff_reader) << "orientation: " << orientation;
-
+    MAPNIK_LOG_DEBUG(tiff_reader) << "orientation: " << orientation ;
+    MAPNIK_LOG_DEBUG(tiff_reader) << "planar-config: " << planar_config_ ;
     is_tiled_ = TIFFIsTiled(tif);
 
     if (is_tiled_)
@@ -285,7 +288,7 @@ void tiff_reader<T>::init()
         MAPNIK_LOG_DEBUG(tiff_reader) << "tiff is tiled";
         read_method_ = tiled;
     }
-    else if (TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rows_per_strip_)!=0)
+    else if (TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip_) != 0)
     {
         MAPNIK_LOG_DEBUG(tiff_reader) << "tiff is stripped";
         read_method_ = stripped;
@@ -311,9 +314,9 @@ void tiff_reader<T>::init()
         if (TIFFGetField(tif, 33550, &count, &pixelscale) == 1 && count == 3
             && TIFFGetField(tif, 33922 , &count,  &tilepoint) == 1 && count == 6)
         {
-            MAPNIK_LOG_DEBUG(tiff_reader) << "PixelScale:" << pixelscale[0] << "," << pixelscale[1] << "," <<  pixelscale[2];
-            MAPNIK_LOG_DEBUG(tiff_reader) << "TilePoint:" << tilepoint[0] << "," << tilepoint[1] << "," << tilepoint[2];
-            MAPNIK_LOG_DEBUG(tiff_reader) << "          " << tilepoint[3] << "," << tilepoint[4] << "," << tilepoint[5];
+            MAPNIK_LOG_DEBUG(tiff_reader) << "PixelScale:" << pixelscale[0] << "," << pixelscale[1] << "," <<  pixelscale[2] ;
+            MAPNIK_LOG_DEBUG(tiff_reader) << "TilePoint:" << tilepoint[0] << "," << tilepoint[1] << "," << tilepoint[2] ;
+            MAPNIK_LOG_DEBUG(tiff_reader) << "          " << tilepoint[3] << "," << tilepoint[4] << "," << tilepoint[5] ;
 
             // assuming upper-left
             double lox = tilepoint[3];
@@ -321,7 +324,7 @@ void tiff_reader<T>::init()
             double hix = lox + pixelscale[0] * width_;
             double hiy = loy - pixelscale[1] * height_;
             bbox_.reset(box2d<double>(lox, loy, hix, hiy));
-            MAPNIK_LOG_DEBUG(tiff_reader) << "Bounding Box:" << *bbox_;
+            MAPNIK_LOG_DEBUG(tiff_reader) << "Bounding Box:" << *bbox_ ;
         }
 
     }
@@ -391,10 +394,17 @@ image_any tiff_reader<T>::read_any_gray(std::size_t x0, std::size_t y0, std::siz
     using pixel_type = typename image_type::pixel_type;
     if (read_method_ == tiled)
     {
-        image_type data(width,height);
+        image_type data(width, height);
         read_tiled<image_type>(x0, y0, data);
         return image_any(std::move(data));
     }
+    // TODO: temp disable and default to `scanline` method for stripped images.
+    else if (read_method_ == stripped)
+    {
+        image_type data(width, height);
+        read_stripped<image_type>(x0, y0, data);
+        return image_any(std::move(data));
+    }
     else
     {
         TIFF* tif = open(stream_);
@@ -407,14 +417,52 @@ image_any tiff_reader<T>::read_any_gray(std::size_t x0, std::size_t y0, std::siz
             std::size_t start_x = x0;
             std::size_t end_x = std::min(x0 + width, width_);
             std::size_t element_size = sizeof(pixel_type);
+            MAPNIK_LOG_DEBUG(tiff_reader) << "SCANLINE SIZE=" << TIFFScanlineSize(tif);
             std::size_t size_to_allocate = (TIFFScanlineSize(tif) + element_size - 1)/element_size;
-            const std::unique_ptr<pixel_type[]> scanline(new pixel_type[size_to_allocate]);
-            for  (std::size_t y = start_y; y < end_y; ++y)
+            std::unique_ptr<pixel_type[]> const scanline(new pixel_type[size_to_allocate]);
+            if (planar_config_ == PLANARCONFIG_CONTIG)
+            {
+                for  (std::size_t y = start_y; y < end_y; ++y)
+                {
+                    // we have to read all scanlines sequentially from start_y
+                    // to be able to use scanline interface with compressed blocks.
+                    if (-1 != TIFFReadScanline(tif, scanline.get(), y) && (y >= y0))
+                    {
+                        pixel_type * row = data.get_row(y - y0);
+                        if (bands_ == 1)
+                        {
+                            std::transform(scanline.get() + start_x, scanline.get() + end_x, row, [](pixel_type const& p) { return p;});
+                        }
+                        else if (size_to_allocate == bands_ * width_)
+                        {
+                            // bands_ > 1 => packed bands in grayscale image e.g an extra alpha channel.
+                            // Just pick first one for now.
+                            pixel_type * buf = scanline.get() + start_x * bands_;
+                            std::size_t x_index = 0;
+                            for (std::size_t j = 0; j < end_x * bands_; ++j)
+                            {
+                                if (x_index >= width) break;
+                                if (j % bands_ == 0)
+                                {
+                                    row[x_index++] = buf[j];
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            else if (planar_config_ == PLANARCONFIG_SEPARATE)
             {
-                if (-1 != TIFFReadScanline(tif, scanline.get(), y) && (y >= y0))
+                for (std::size_t s = 0 ; s < bands_ ; ++s)
                 {
-                    pixel_type * row = data.get_row(y - y0);
-                    std::transform(scanline.get() + start_x, scanline.get() + end_x, row, [](pixel_type const& p) { return p;});
+                    for  (std::size_t y = start_y; y < end_y; ++y)
+                    {
+                        if (-1 != TIFFReadScanline(tif, scanline.get(), y) && (y >= y0))
+                        {
+                            pixel_type * row = data.get_row(y - y0);
+                            std::transform(scanline.get() + start_x, scanline.get() + end_x, row, [](pixel_type const& p) { return p;});
+                        }
+                    }
                 }
             }
             return image_any(std::move(data));
@@ -446,9 +494,17 @@ struct tiff_reader_traits
 {
     using image_type = T;
     using pixel_type = typename image_type::pixel_type;
+
+    constexpr static bool reverse = false;
     static bool read_tile(TIFF * tif, std::size_t x, std::size_t y, pixel_type* buf, std::size_t tile_width, std::size_t tile_height)
     {
-        return (TIFFReadEncodedTile(tif, TIFFComputeTile(tif, x,y,0,0), buf, tile_width * tile_height * sizeof(pixel_type)) != -1);
+        std::uint32_t tile_size = TIFFTileSize(tif);
+        return (TIFFReadEncodedTile(tif, TIFFComputeTile(tif, x, y, 0, 0), buf, tile_size) != -1);
+    }
+
+    static bool read_strip(TIFF * tif, std::size_t y, std::size_t rows_per_strip, std::size_t strip_width, pixel_type * buf)
+    {
+        return (TIFFReadEncodedStrip(tif, y/rows_per_strip, buf, -1) != -1);
     }
 };
 
@@ -456,18 +512,17 @@ struct tiff_reader_traits
 template <>
 struct tiff_reader_traits<image_rgba8>
 {
+    using image_type = image_rgba8;
     using pixel_type = std::uint32_t;
+    constexpr static bool reverse = true;
     static bool read_tile(TIFF * tif, std::size_t x0, std::size_t y0, pixel_type* buf, std::size_t tile_width, std::size_t tile_height)
     {
-        if (TIFFReadRGBATile(tif, x0, y0, buf) != -1)
-        {
-            for (std::size_t y = 0; y < tile_height/2; ++y)
-            {
-                std::swap_ranges(buf + y * tile_width, buf + (y + 1) * tile_width, buf + (tile_height - y - 1) * tile_width);
-            }
-            return true;
-        }
-        return false;
+        return (TIFFReadRGBATile(tif, x0, y0, buf) != 0);
+    }
+
+    static bool read_strip(TIFF * tif, std::size_t y, std::size_t rows_per_strip, std::size_t strip_width, pixel_type * buf)
+    {
+        return (TIFFReadRGBAStrip(tif, y, buf) != 0);
     }
 };
 
@@ -591,7 +646,8 @@ image_any tiff_reader<T>::read(unsigned x, unsigned y, unsigned width, unsigned
 }
 
 template <typename T>
-void tiff_reader<T>::read_generic(std::size_t, std::size_t, image_rgba8&)
+template <typename ImageData>
+void tiff_reader<T>::read_generic(std::size_t, std::size_t, ImageData &)
 {
     throw std::runtime_error("tiff_reader: TODO - tiff is not stripped or tiled");
 }
@@ -605,7 +661,8 @@ void tiff_reader<T>::read_tiled(std::size_t x0,std::size_t y0, ImageData & image
     TIFF* tif = open(stream_);
     if (tif)
     {
-        std::unique_ptr<pixel_type[]> buf(new pixel_type[tile_width_*tile_height_]);
+        std::uint32_t tile_size = TIFFTileSize(tif);
+        std::unique_ptr<pixel_type[]> tile(new pixel_type[tile_size]);
         std::size_t width = image.width();
         std::size_t height = image.height();
         std::size_t start_y = (y0 / tile_height_) * tile_height_;
@@ -614,7 +671,7 @@ void tiff_reader<T>::read_tiled(std::size_t x0,std::size_t y0, ImageData & image
         std::size_t end_x = ((x0 + width) / tile_width_ + 1) * tile_width_;
         end_y = std::min(end_y, height_);
         end_x = std::min(end_x, width_);
-
+        bool pick_first_band = (bands_ > 1) && (tile_size / (tile_width_ * tile_height_ * sizeof(pixel_type)) == bands_);
         for (std::size_t y = start_y; y < end_y; y += tile_height_)
         {
             std::size_t ty0 = std::max(y0, y) - y;
@@ -622,56 +679,98 @@ void tiff_reader<T>::read_tiled(std::size_t x0,std::size_t y0, ImageData & image
 
             for (std::size_t x = start_x; x < end_x; x += tile_width_)
             {
-                if (!detail::tiff_reader_traits<ImageData>::read_tile(tif, x, y, buf.get(), tile_width_, tile_height_))
+                if (!detail::tiff_reader_traits<ImageData>::read_tile(tif, x, y, tile.get(), tile_width_, tile_height_))
                 {
                     MAPNIK_LOG_DEBUG(tiff_reader) <<  "read_tile(...) failed at " << x << "/" << y << " for " << width_ << "/" << height_ << "\n";
                     break;
                 }
+                if (pick_first_band)
+                {
+                    std::uint32_t size = tile_width_ * tile_height_ * sizeof(pixel_type);
+                    for (std::uint32_t n = 0; n < size; ++n)
+                    {
+                        tile[n] = tile[n * bands_];
+                    }
+                }
                 std::size_t tx0 = std::max(x0, x);
                 std::size_t tx1 = std::min(width + x0, x + tile_width_);
-                std::size_t row = y + ty0 - y0;
-                for (std::size_t ty = ty0; ty < ty1; ++ty, ++row)
+                std::size_t row_index = y + ty0 - y0;
+
+                if (detail::tiff_reader_traits<ImageData>::reverse)
+                {
+                    for (std::size_t ty = ty0; ty < ty1; ++ty, ++row_index)
+                    {
+                        // This is in reverse because the TIFFReadRGBATile reads are inverted
+                        image.set_row(row_index, tx0 - x0, tx1 - x0, &tile[(tile_height_ - ty - 1) * tile_width_ + tx0 - x]);
+                    }
+                }
+                else
                 {
-                    image.set_row(row, tx0 - x0, tx1 - x0, &buf[ty * tile_width_ + tx0 - x]);
+                    for (std::size_t ty = ty0; ty < ty1; ++ty, ++row_index)
+                    {
+                        image.set_row(row_index, tx0 - x0, tx1 - x0, &tile[ty * tile_width_ + tx0 - x]);
+                    }
                 }
             }
         }
     }
 }
 
-
 template <typename T>
-void tiff_reader<T>::read_stripped(std::size_t x0,std::size_t y0,image_rgba8& image)
+template <typename ImageData>
+void tiff_reader<T>::read_stripped(std::size_t x0, std::size_t y0, ImageData & image)
 {
+    using pixel_type = typename detail::tiff_reader_traits<ImageData>::pixel_type;
     TIFF* tif = open(stream_);
     if (tif)
     {
-        image_rgba8 strip(width_,rows_per_strip_,false);
-        std::size_t width=image.width();
-        std::size_t height=image.height();
+        std::uint32_t strip_size = TIFFStripSize(tif);
+        std::unique_ptr<pixel_type[]> strip(new pixel_type[strip_size]);
+        std::size_t width = image.width();
+        std::size_t height = image.height();
 
-        std::size_t start_y=(y0/rows_per_strip_)*rows_per_strip_;
-        std::size_t end_y=std::min(y0+height, height_);
-        std::size_t tx0,tx1,ty0,ty1;
+        std::size_t start_y = (y0 / rows_per_strip_) * rows_per_strip_;
+        std::size_t end_y = std::min(y0 + height, height_);
+        std::size_t tx0, tx1, ty0, ty1;
 
-        tx0=x0;
-        tx1=std::min(width+x0,width_);
+        tx0 = x0;
+        tx1 = std::min(width + x0, width_);
         std::size_t row = 0;
-        for (std::size_t y=start_y; y < end_y; y+=rows_per_strip_)
+        bool pick_first_band = (bands_ > 1) && (strip_size / (width_ * rows_per_strip_ * sizeof(pixel_type)) == bands_);
+        for (std::size_t y = start_y; y < end_y; y += rows_per_strip_)
         {
-            ty0 = std::max(y0,y)-y;
-            ty1 = std::min(end_y,y+rows_per_strip_)-y;
+            ty0 = std::max(y0, y) - y;
+            ty1 = std::min(end_y, y + rows_per_strip_) - y;
 
-            if (!TIFFReadRGBAStrip(tif,y,strip.data()))
+            if (!detail::tiff_reader_traits<ImageData>::read_strip(tif, y, rows_per_strip_, width_, strip.get()))
             {
-                MAPNIK_LOG_DEBUG(tiff_reader) << "TIFFReadRGBAStrip failed at " << y << " for " << width_ << "/" << height_ << "\n";
+                MAPNIK_LOG_DEBUG(tiff_reader) << "TIFFRead(Encoded|RGBA)Strip failed at " << y << " for " << width_ << "/" << height_ << "\n";
                 break;
             }
-            // This is in reverse because the TIFFReadRGBAStrip reads inverted
-            for (std::size_t ty = ty1; ty > ty0; --ty)
+            if (pick_first_band)
             {
-                image.set_row(row,tx0-x0,tx1-x0,&strip.data()[(ty-1)*width_+tx0]);
-                ++row;
+                std::uint32_t size = width_ * rows_per_strip_ * sizeof(pixel_type);
+                for (std::uint32_t n = 0; n < size; ++n)
+                {
+                    strip[n] = strip[bands_ * n];
+                }
+            }
+
+            if (detail::tiff_reader_traits<ImageData>::reverse)
+            {
+                std::size_t num_rows = std::min(end_y - y, static_cast<std::size_t>(rows_per_strip_));
+                for (std::size_t ty = ty0; ty < ty1; ++ty)
+                {
+                    // This is in reverse because the TIFFReadRGBAStrip reads are inverted
+                    image.set_row(row++, tx0 - x0, tx1 - x0, &strip[(num_rows - ty - 1) * width_ + tx0]);
+                }
+            }
+            else
+            {
+                for (std::size_t ty = ty0; ty < ty1; ++ty)
+                {
+                    image.set_row(row++, tx0 - x0, tx1 - x0, &strip[ty * width_ + tx0]);
+                }
             }
         }
     }
diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp
index 2e2a7df..7a41007 100644
--- a/src/xml_tree.cpp
+++ b/src/xml_tree.cpp
@@ -133,13 +133,13 @@ node_not_found::node_not_found(std::string const& node_name)
     : node_name_(node_name),
       msg_() {}
 
-const char* node_not_found::what() const throw()
+const char* node_not_found::what() const noexcept
 {
     msg_ = std::string("Node "+node_name_+ "not found");
     return msg_.c_str();
 }
 
-node_not_found::~node_not_found() throw() {}
+node_not_found::~node_not_found() {}
 
 
 attribute_not_found::attribute_not_found(std::string const& node_name,
@@ -148,25 +148,25 @@ attribute_not_found::attribute_not_found(std::string const& node_name,
       attribute_name_(attribute_name),
       msg_() {}
 
-const char* attribute_not_found::what() const throw()
+const char* attribute_not_found::what() const noexcept
 {
     msg_ = std::string("Attribute '" + attribute_name_ +"' not found in node '"+node_name_+ "'");
     return msg_.c_str();
 }
 
-attribute_not_found::~attribute_not_found() throw() {}
+attribute_not_found::~attribute_not_found() {}
 
 more_than_one_child::more_than_one_child(std::string const& node_name)
     : node_name_(node_name),
       msg_() {}
 
-const char* more_than_one_child::what() const throw()
+const char* more_than_one_child::what() const noexcept
 {
     msg_ = std::string("More than one child node in node '" + node_name_ +"'");
     return msg_.c_str();
 }
 
-more_than_one_child::~more_than_one_child() throw() {}
+more_than_one_child::~more_than_one_child() {}
 
 xml_node::xml_node(xml_tree &tree, std::string && name, unsigned line, bool is_text)
     : tree_(tree),
diff --git a/test/unit/datasource/geojson.cpp b/test/unit/datasource/geojson.cpp
index 337f809..c442590 100644
--- a/test/unit/datasource/geojson.cpp
+++ b/test/unit/datasource/geojson.cpp
@@ -28,9 +28,12 @@
 #include <mapnik/datasource_cache.hpp>
 #include <mapnik/geometry.hpp>
 #include <mapnik/geometry_type.hpp>
+#include <mapnik/json/geometry_parser.hpp> // from_geojson
+#include <mapnik/util/geometry_to_geojson.hpp>
 #include <mapnik/util/fs.hpp>
 #include <cstdlib>
-
+#include <locale>
+#include <algorithm>
 #include <boost/optional/optional_io.hpp>
 
 /*
@@ -115,6 +118,50 @@ TEST_CASE("geojson") {
             }
         }
 
+        SECTION("GeoJSON empty Geometries handling")
+        {
+            auto valid_empty_geometries =
+                {
+                    "null", // Point can't be empty
+                    "{ \"type\": \"LineString\", \"coordinates\": [] }",
+                    "{ \"type\": \"Polygon\", \"coordinates\": [ [ ] ] } ",
+                    "{ \"type\": \"MultiPoint\", \"coordinates\": [ ] }",
+                    "{ \"type\": \"MultiLineString\", \"coordinates\": [ [] ] }",
+                    "{ \"type\": \"MultiPolygon\", \"coordinates\": [[ []] ] }"
+                };
+
+            for (auto const& in  : valid_empty_geometries)
+            {
+                std::string json(in);
+                mapnik::geometry::geometry<double> geom;
+                CHECK(mapnik::json::from_geojson(json, geom));
+                // round trip
+                std::string json_out;
+                CHECK(mapnik::util::to_geojson(json_out, geom));
+                json.erase(std::remove_if(
+                               std::begin(json), std::end(json),
+                               [](char ch) { return std::isspace(ch, std::locale{}); }
+                               ), std::end(json));
+                REQUIRE(json == json_out);
+            }
+
+            auto invalid_empty_geometries =
+                {
+                    "{ \"type\": \"Point\", \"coordinates\": [] }",
+                    "{ \"type\": \"LineString\", \"coordinates\": [[]] }"
+                    "{ \"type\": \"Polygon\", \"coordinates\": [[[]]] }",
+                    "{ \"type\": \"MultiPoint\", \"coordinates\": [[]] }",
+                    "{ \"type\": \"MultiLineString\", \"coordinates\": [[[]]] }",
+                    "{ \"type\": \"MultiPolygon\", \"coordinates\": [[[[]]]] }"
+                };
+
+            for (auto const& json  : invalid_empty_geometries)
+            {
+                mapnik::geometry::geometry<double> geom;
+                CHECK(!mapnik::json::from_geojson(json, geom));
+            }
+        }
+
         SECTION("GeoJSON num_features_to_query")
         {
             std::string filename = "./test/data/json/featurecollection-multipleprops.geojson";
@@ -557,8 +604,7 @@ TEST_CASE("geojson") {
         {
             mapnik::parameters params;
             params["type"] = "geojson";
-            for (auto const& c_str : {"./test/data/json/featurecollection-malformed.json",
-                        "./test/data/json/featurecollection-malformed-2.json"})
+            for (auto const& c_str : {"./test/data/json/featurecollection-malformed.json"})
             {
                 std::string filename(c_str);
                 params["file"] = filename;
diff --git a/test/unit/datasource/shapeindex.cpp b/test/unit/datasource/shapeindex.cpp
index 51f47ac..494bba2 100644
--- a/test/unit/datasource/shapeindex.cpp
+++ b/test/unit/datasource/shapeindex.cpp
@@ -162,9 +162,13 @@ TEST_CASE("shapeindex")
                         // count features
                         std::size_t feature_count = count_shapefile_features(path);
                         // create *.index
-                        REQUIRE(create_shapefile_index(path, index_parts) == 0);
-                        if (feature_count == 0)
+                        if (feature_count > 0)
                         {
+                            REQUIRE(create_shapefile_index(path, index_parts) == EXIT_SUCCESS);
+                        }
+                        else
+                        {
+                            REQUIRE(create_shapefile_index(path, index_parts) != EXIT_SUCCESS);
                             REQUIRE(!mapnik::util::exists(index_path)); // index won't be created if there's no features
                         }
                         // count features
diff --git a/test/unit/imaging/tiff_io.cpp b/test/unit/imaging/tiff_io.cpp
index 14f9e5f..2c53800 100644
--- a/test/unit/imaging/tiff_io.cpp
+++ b/test/unit/imaging/tiff_io.cpp
@@ -5,280 +5,398 @@
 
 #include "catch.hpp"
 
+#include <mapnik/color.hpp>
+#include <mapnik/image_util.hpp>
+#include <mapnik/image_view.hpp>
 #include <mapnik/image_reader.hpp>
 #include <mapnik/util/file_io.hpp>
+#include <mapnik/util/fs.hpp>
 
 #include "../../../src/tiff_reader.cpp"
 
-#define TIFF_ASSERT(filename) \
-    mapnik::tiff_reader<std::filebuf> tiff_reader(filename);    \
-    REQUIRE( tiff_reader.width() == 256 ); \
-    REQUIRE( tiff_reader.height() == 256 ); \
-    REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); \
+#define TIFF_ASSERT(filename)                                           \
+    mapnik::tiff_reader<std::filebuf> tiff_reader(filename);            \
+    REQUIRE( tiff_reader.width() == 256 );                              \
+    REQUIRE( tiff_reader.height() == 256 );                             \
+    REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG );      \
     std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff")); \
-    REQUIRE( reader->width() == 256 ); \
-    REQUIRE( reader->height() == 256 ); \
-    mapnik::util::file file(filename); \
+    REQUIRE( reader->width() == 256 );                                  \
+    REQUIRE( reader->height() == 256 );                                 \
+    mapnik::util::file file(filename);                                  \
     mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size()); \
-    REQUIRE( tiff_reader2.width() == 256 ); \
-    REQUIRE( tiff_reader2.height() == 256 ); \
+    REQUIRE( tiff_reader2.width() == 256 );                             \
+    REQUIRE( tiff_reader2.height() == 256 );                            \
     std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size())); \
-    REQUIRE( reader2->width() == 256 ); \
-    REQUIRE( reader2->height() == 256 ); \
-
-#define TIFF_ASSERT_ALPHA( data ) \
-    REQUIRE( tiff_reader.has_alpha() == true ); \
-    REQUIRE( reader->has_alpha() == true ); \
-    REQUIRE( tiff_reader2.has_alpha() == true ); \
-    REQUIRE( reader2->has_alpha() == true ); \
-    REQUIRE( data.get_premultiplied() == true ); \
-
-#define TIFF_ASSERT_NO_ALPHA_RGB( data ) \
-    REQUIRE( tiff_reader.has_alpha() == false ); \
-    REQUIRE( reader->has_alpha() == false ); \
-    REQUIRE( tiff_reader2.has_alpha() == false ); \
-    REQUIRE( reader2->has_alpha() == false ); \
-    REQUIRE( data.get_premultiplied() == true ); \
-
-#define TIFF_ASSERT_NO_ALPHA_GRAY( data ) \
-    REQUIRE( tiff_reader.has_alpha() == false ); \
-    REQUIRE( reader->has_alpha() == false ); \
-    REQUIRE( tiff_reader2.has_alpha() == false ); \
-    REQUIRE( reader2->has_alpha() == false ); \
-    REQUIRE( data.get_premultiplied() == false ); \
-
-#define TIFF_ASSERT_SIZE( data,reader ) \
-    REQUIRE( data.width() == reader->width() ); \
-    REQUIRE( data.height() == reader->height() ); \
-
-#define TIFF_READ_ONE_PIXEL \
-    mapnik::image_any subimage = reader->read(1, 1, 1, 1); \
-    REQUIRE( subimage.width() == 1 ); \
-    REQUIRE( subimage.height() == 1 ); \
+    REQUIRE( reader2->width() == 256 );                                 \
+    REQUIRE( reader2->height() == 256 );                                \
 
-TEST_CASE("tiff io")
+#define TIFF_ASSERT_ALPHA( data )                       \
+    REQUIRE( tiff_reader.has_alpha() == true );         \
+    REQUIRE( reader->has_alpha() == true );             \
+    REQUIRE( tiff_reader2.has_alpha() == true );        \
+    REQUIRE( reader2->has_alpha() == true );            \
+    REQUIRE( data.get_premultiplied() == true );        \
+
+#define TIFF_ASSERT_NO_ALPHA_RGB( data )                \
+    REQUIRE( tiff_reader.has_alpha() == false );        \
+    REQUIRE( reader->has_alpha() == false );            \
+    REQUIRE( tiff_reader2.has_alpha() == false );       \
+    REQUIRE( reader2->has_alpha() == false );           \
+    REQUIRE( data.get_premultiplied() == true );        \
+
+#define TIFF_ASSERT_NO_ALPHA_GRAY( data )               \
+    REQUIRE( tiff_reader.has_alpha() == false );        \
+    REQUIRE( reader->has_alpha() == false );            \
+    REQUIRE( tiff_reader2.has_alpha() == false );       \
+    REQUIRE( reader2->has_alpha() == false );           \
+    REQUIRE( data.get_premultiplied() == false );       \
+
+#define TIFF_ASSERT_SIZE( data,reader )                 \
+    REQUIRE( data.width() == reader->width() );         \
+    REQUIRE( data.height() == reader->height() );       \
+
+#define TIFF_READ_ONE_PIXEL                                     \
+    mapnik::image_any subimage = reader->read(1, 1, 1, 1);      \
+    REQUIRE( subimage.width() == 1 );                           \
+    REQUIRE( subimage.height() == 1 );                          \
+
+
+namespace {
+
+template <typename Image>
+struct test_image_traits
 {
+    using value_type = mapnik::color;
+    static value_type const& get_value(mapnik::color const& c)
+    {
+        return c;
+    }
+};
 
-SECTION("scan rgb8 striped")
+template <>
+struct test_image_traits<mapnik::image_gray8>
 {
-    std::string filename("./test/data/tiff/scan_512x512_rgb8_striped.tif");
-    mapnik::tiff_reader<std::filebuf> tiff_reader(filename);
-    REQUIRE( tiff_reader.width() == 512 );
-    REQUIRE( tiff_reader.height() == 512 );
-    REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG );
-    REQUIRE( tiff_reader.rows_per_strip() == 16 );
-    REQUIRE( tiff_reader.bits_per_sample() == 8 );
-    REQUIRE( tiff_reader.is_tiled() == false );
-    REQUIRE( tiff_reader.tile_width() == 0 );
-    REQUIRE( tiff_reader.tile_height() == 0 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
-    std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff"));
-    REQUIRE( reader->width() == 512 );
-    REQUIRE( reader->height() == 512 );
-    mapnik::util::file file(filename);
-    mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size());
-    REQUIRE( tiff_reader2.width() == 512 );
-    REQUIRE( tiff_reader2.height() == 512 );
-    std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size()));
-    REQUIRE( reader2->width() == 512 );
-    REQUIRE( reader2->height() == 512 );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_rgba8>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_NO_ALPHA_RGB( data );
-    TIFF_READ_ONE_PIXEL
-}
+    using value_type = std::uint8_t;
+    static value_type get_value(mapnik::color const& c)
+    {
+        return c.green(); // use green channel for gray scale images
+    }
+};
 
-SECTION("scan rgb8 tiled") {
-    std::string filename("./test/data/tiff/scan_512x512_rgb8_tiled.tif");
-    mapnik::tiff_reader<std::filebuf> tiff_reader(filename);
-    REQUIRE( tiff_reader.width() == 512 );
-    REQUIRE( tiff_reader.height() == 512 );
-    REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG );
-    REQUIRE( tiff_reader.rows_per_strip() == 0 );
-    REQUIRE( tiff_reader.bits_per_sample() == 8 );
-    REQUIRE( tiff_reader.is_tiled() == true );
-    REQUIRE( tiff_reader.tile_width() == 256 );
-    REQUIRE( tiff_reader.tile_height() == 256 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
-    std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff"));
-    REQUIRE( reader->width() == 512 );
-    REQUIRE( reader->height() == 512 );
-    mapnik::util::file file(filename);
-    mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size());
-    REQUIRE( tiff_reader2.width() == 512 );
-    REQUIRE( tiff_reader2.height() == 512 );
-    std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size()));
-    REQUIRE( reader2->width() == 512 );
-    REQUIRE( reader2->height() == 512 );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_rgba8>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_NO_ALPHA_RGB( data );
-    TIFF_READ_ONE_PIXEL
-}
 
-SECTION("rgba8 striped") {
-    TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgba8_striped.tif")
-    REQUIRE( tiff_reader.rows_per_strip() == 1 );
-    REQUIRE( tiff_reader.bits_per_sample() == 8 );
-    REQUIRE( tiff_reader.is_tiled() == false );
-    REQUIRE( tiff_reader.tile_width() == 0 );
-    REQUIRE( tiff_reader.tile_height() == 0 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_ADOBE_DEFLATE );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_rgba8>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_ALPHA( data );
-    TIFF_READ_ONE_PIXEL
-}
+template <typename Image>
+Image generate_test_image()
+{
 
-SECTION("rgba8 tiled") {
-    TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgba8_tiled.tif")
-    REQUIRE( tiff_reader.rows_per_strip() == 0 );
-    REQUIRE( tiff_reader.bits_per_sample() == 8 );
-    REQUIRE( tiff_reader.is_tiled() == true );
-    REQUIRE( tiff_reader.tile_width() == 256 );
-    REQUIRE( tiff_reader.tile_height() == 256 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_rgba8>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_ALPHA( data );
-    TIFF_READ_ONE_PIXEL
+    std::size_t tile_size = 16;
+    Image im(64, 64);
+    mapnik::color colors[] = {{mapnik::color("red")},
+                              {mapnik::color("blue")},
+                              {mapnik::color("green")},
+                              {mapnik::color("yellow")}};
+    std::size_t index = 0;
+    for (std::size_t j = 0; j < im.height()/tile_size; ++j)
+    {
+        ++index;
+        for (std::size_t i = 0; i < im.width()/tile_size; ++i)
+        {
+            ++index;
+            for (std::size_t x = 0; x < tile_size; ++x)
+            {
+                for (std::size_t y = 0; y < tile_size; ++y)
+                {
+                    auto value = test_image_traits<Image>::get_value(colors[index % 4]);
+                    mapnik::set_pixel(im, i * tile_size + x, j * tile_size + y, value );
+                }
+            }
+        }
+    }
+    return im;
 }
 
-SECTION("rgb8 striped") {
-    TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgb8_striped.tif")
-    REQUIRE( tiff_reader.rows_per_strip() == 10 );
-    REQUIRE( tiff_reader.bits_per_sample() == 8 );
-    REQUIRE( tiff_reader.is_tiled() == false );
-    REQUIRE( tiff_reader.tile_width() == 0 );
-    REQUIRE( tiff_reader.tile_height() == 0 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_rgba8>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_NO_ALPHA_RGB( data );
-    TIFF_READ_ONE_PIXEL
-}
+template <typename Image1, typename Image2>
+bool identical(Image1 const& im1, Image2 const& im2)
+{
+    if ((im1.width() != im2.width()) || (im1.height() != im2.height()))
+        return false;
 
-SECTION("rgb8 tiled") {
-    TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgb8_tiled.tif")
-    REQUIRE( tiff_reader.rows_per_strip() == 0 );
-    REQUIRE( tiff_reader.bits_per_sample() == 8 );
-    REQUIRE( tiff_reader.is_tiled() == true );
-    REQUIRE( tiff_reader.tile_width() == 256 );
-    REQUIRE( tiff_reader.tile_height() == 256 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_rgba8>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_NO_ALPHA_RGB( data );
-    TIFF_READ_ONE_PIXEL
+    for (std::size_t i = 0; i < im1.width(); ++i)
+    {
+        for (std::size_t j = 0; j < im1.height(); ++j)
+        {
+            if (im1(i,j) != im2(i,j)) return false;
+        }
+    }
+    return true;
 }
 
-SECTION("gray8 striped") {
-    TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray8_striped.tif")
-    REQUIRE( tiff_reader.rows_per_strip() == 32 );
-    REQUIRE( tiff_reader.bits_per_sample() == 8 );
-    REQUIRE( tiff_reader.is_tiled() == false );
-    REQUIRE( tiff_reader.tile_width() == 0 );
-    REQUIRE( tiff_reader.tile_height() == 0 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_gray8>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_NO_ALPHA_GRAY( data );
-    TIFF_READ_ONE_PIXEL
-}
+template <typename Image>
+void test_tiff_reader(std::string const& pattern)
+{
+    // generate expected image (rgba8 or gray8)
+    auto im = generate_test_image<Image>();
 
-SECTION("gray8 tiled") {
-    TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray8_tiled.tif")
-    REQUIRE( tiff_reader.rows_per_strip() == 0 );
-    REQUIRE( tiff_reader.bits_per_sample() == 8 );
-    REQUIRE( tiff_reader.is_tiled() == true );
-    REQUIRE( tiff_reader.tile_width() == 256 );
-    REQUIRE( tiff_reader.tile_height() == 256 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_gray8>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_NO_ALPHA_GRAY( data );
-    TIFF_READ_ONE_PIXEL
+    for (auto const& path : mapnik::util::list_directory("test/data/tiff/"))
+    {
+        if (boost::iends_with(path,".tif")
+            && boost::istarts_with(mapnik::util::basename(path), pattern))
+        {
+            mapnik::tiff_reader<std::filebuf> tiff_reader(path);
+            auto width = tiff_reader.width();
+            auto height = tiff_reader.height();
+            {
+                // whole image
+                auto tiff = tiff_reader.read(0, 0, width, height);
+                CHECK(tiff.is<Image>());
+                auto im2 = tiff.get<Image>();
+                REQUIRE(identical(im, im2));
+            }
+            {
+                // portion
+                auto tiff = tiff_reader.read(11, 13, width - 11, height - 13);
+                CHECK(tiff.is<Image>());
+                auto im2 = tiff.get<Image>();
+                auto view = mapnik::image_view<Image>(11, 13, width, height, im);
+                REQUIRE(identical(view, im2));
+            }
+        }
+    }
 }
 
-SECTION("gray16 striped") {
-    TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray16_striped.tif")
-    REQUIRE( tiff_reader.rows_per_strip() == 16 );
-    REQUIRE( tiff_reader.bits_per_sample() == 16 );
-    REQUIRE( tiff_reader.is_tiled() == false );
-    REQUIRE( tiff_reader.tile_width() == 0 );
-    REQUIRE( tiff_reader.tile_height() == 0 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_gray16>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_NO_ALPHA_GRAY( data );
-    TIFF_READ_ONE_PIXEL
 }
 
-SECTION("gray16 tiled") {
-    TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray16_tiled.tif")
-    REQUIRE( tiff_reader.rows_per_strip() == 0 );
-    REQUIRE( tiff_reader.bits_per_sample() == 16 );
-    REQUIRE( tiff_reader.is_tiled() == true );
-    REQUIRE( tiff_reader.tile_width() == 256 );
-    REQUIRE( tiff_reader.tile_height() == 256 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_gray16>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_NO_ALPHA_GRAY( data );
-    TIFF_READ_ONE_PIXEL
-}
+TEST_CASE("tiff io")
+{
+    SECTION("tiff-reader rgb8+rgba8")
+    {
+        test_tiff_reader<mapnik::image_rgba8>("tiff_rgb");
+    }
 
-SECTION("gray32f striped") {
-    TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray32f_striped.tif")
-    REQUIRE( tiff_reader.rows_per_strip() == 8 );
-    REQUIRE( tiff_reader.bits_per_sample() == 32 );
-    REQUIRE( tiff_reader.is_tiled() == false );
-    REQUIRE( tiff_reader.tile_width() == 0 );
-    REQUIRE( tiff_reader.tile_height() == 0 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_gray32f>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_NO_ALPHA_GRAY( data );
-    TIFF_READ_ONE_PIXEL
-}
+    SECTION("tiff-reader gray8")
+    {
+        test_tiff_reader<mapnik::image_gray8>("tiff_gray");
+    }
 
-SECTION("gray32f tiled") {
-    TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray32f_tiled.tif")
-    REQUIRE( tiff_reader.rows_per_strip() == 0 );
-    REQUIRE( tiff_reader.bits_per_sample() == 32 );
-    REQUIRE( tiff_reader.is_tiled() == true );
-    REQUIRE( tiff_reader.tile_width() == 256 );
-    REQUIRE( tiff_reader.tile_height() == 256 );
-    REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
-    REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
-    mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
-    REQUIRE( data.is<mapnik::image_gray32f>() == true );
-    TIFF_ASSERT_SIZE( data,reader );
-    TIFF_ASSERT_NO_ALPHA_GRAY( data );
-    TIFF_READ_ONE_PIXEL
-}
+    SECTION("scan rgb8 striped")
+    {
+        std::string filename("./test/data/tiff/scan_512x512_rgb8_striped.tif");
+        mapnik::tiff_reader<std::filebuf> tiff_reader(filename);
+        REQUIRE( tiff_reader.width() == 512 );
+        REQUIRE( tiff_reader.height() == 512 );
+        REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG );
+        REQUIRE( tiff_reader.rows_per_strip() == 16 );
+        REQUIRE( tiff_reader.bits_per_sample() == 8 );
+        REQUIRE( tiff_reader.is_tiled() == false );
+        REQUIRE( tiff_reader.tile_width() == 0 );
+        REQUIRE( tiff_reader.tile_height() == 0 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
+        std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff"));
+        REQUIRE( reader->width() == 512 );
+        REQUIRE( reader->height() == 512 );
+        mapnik::util::file file(filename);
+        mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size());
+        REQUIRE( tiff_reader2.width() == 512 );
+        REQUIRE( tiff_reader2.height() == 512 );
+        std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size()));
+        REQUIRE( reader2->width() == 512 );
+        REQUIRE( reader2->height() == 512 );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_rgba8>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_NO_ALPHA_RGB( data );
+        TIFF_READ_ONE_PIXEL
+    }
+
+    SECTION("scan rgb8 tiled") {
+        std::string filename("./test/data/tiff/scan_512x512_rgb8_tiled.tif");
+        mapnik::tiff_reader<std::filebuf> tiff_reader(filename);
+        REQUIRE( tiff_reader.width() == 512 );
+        REQUIRE( tiff_reader.height() == 512 );
+        REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG );
+        REQUIRE( tiff_reader.rows_per_strip() == 0 );
+        REQUIRE( tiff_reader.bits_per_sample() == 8 );
+        REQUIRE( tiff_reader.is_tiled() == true );
+        REQUIRE( tiff_reader.tile_width() == 256 );
+        REQUIRE( tiff_reader.tile_height() == 256 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
+        std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(filename,"tiff"));
+        REQUIRE( reader->width() == 512 );
+        REQUIRE( reader->height() == 512 );
+        mapnik::util::file file(filename);
+        mapnik::tiff_reader<mapnik::util::char_array_buffer> tiff_reader2(file.data().get(),file.size());
+        REQUIRE( tiff_reader2.width() == 512 );
+        REQUIRE( tiff_reader2.height() == 512 );
+        std::unique_ptr<mapnik::image_reader> reader2(mapnik::get_image_reader(file.data().get(),file.size()));
+        REQUIRE( reader2->width() == 512 );
+        REQUIRE( reader2->height() == 512 );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_rgba8>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_NO_ALPHA_RGB( data );
+        TIFF_READ_ONE_PIXEL
+    }
+
+    SECTION("rgba8 striped") {
+        TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgba8_striped.tif")
+            REQUIRE( tiff_reader.rows_per_strip() == 1 );
+        REQUIRE( tiff_reader.bits_per_sample() == 8 );
+        REQUIRE( tiff_reader.is_tiled() == false );
+        REQUIRE( tiff_reader.tile_width() == 0 );
+        REQUIRE( tiff_reader.tile_height() == 0 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_ADOBE_DEFLATE );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_rgba8>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_ALPHA( data );
+        TIFF_READ_ONE_PIXEL
+    }
+
+    SECTION("rgba8 tiled") {
+        TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgba8_tiled.tif")
+            REQUIRE( tiff_reader.rows_per_strip() == 0 );
+        REQUIRE( tiff_reader.bits_per_sample() == 8 );
+        REQUIRE( tiff_reader.is_tiled() == true );
+        REQUIRE( tiff_reader.tile_width() == 256 );
+        REQUIRE( tiff_reader.tile_height() == 256 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_rgba8>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_ALPHA( data );
+        TIFF_READ_ONE_PIXEL
+            }
+
+    SECTION("rgb8 striped") {
+        TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgb8_striped.tif")
+            REQUIRE( tiff_reader.rows_per_strip() == 10 );
+        REQUIRE( tiff_reader.bits_per_sample() == 8 );
+        REQUIRE( tiff_reader.is_tiled() == false );
+        REQUIRE( tiff_reader.tile_width() == 0 );
+        REQUIRE( tiff_reader.tile_height() == 0 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_rgba8>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_NO_ALPHA_RGB( data );
+        TIFF_READ_ONE_PIXEL
+    }
+
+    SECTION("rgb8 tiled") {
+        TIFF_ASSERT("./test/data/tiff/ndvi_256x256_rgb8_tiled.tif")
+            REQUIRE( tiff_reader.rows_per_strip() == 0 );
+        REQUIRE( tiff_reader.bits_per_sample() == 8 );
+        REQUIRE( tiff_reader.is_tiled() == true );
+        REQUIRE( tiff_reader.tile_width() == 32 );
+        REQUIRE( tiff_reader.tile_height() == 32 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_rgba8>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_NO_ALPHA_RGB( data );
+        TIFF_READ_ONE_PIXEL
+    }
+
+    SECTION("gray8 striped") {
+        TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray8_striped.tif")
+            REQUIRE( tiff_reader.rows_per_strip() == 32 );
+        REQUIRE( tiff_reader.bits_per_sample() == 8 );
+        REQUIRE( tiff_reader.is_tiled() == false );
+        REQUIRE( tiff_reader.tile_width() == 0 );
+        REQUIRE( tiff_reader.tile_height() == 0 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_gray8>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_NO_ALPHA_GRAY( data );
+        TIFF_READ_ONE_PIXEL
+    }
+
+    SECTION("gray8 tiled") {
+        TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray8_tiled.tif")
+            REQUIRE( tiff_reader.rows_per_strip() == 0 );
+        REQUIRE( tiff_reader.bits_per_sample() == 8 );
+        REQUIRE( tiff_reader.is_tiled() == true );
+        REQUIRE( tiff_reader.tile_width() == 256 );
+        REQUIRE( tiff_reader.tile_height() == 256 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_gray8>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_NO_ALPHA_GRAY( data );
+        TIFF_READ_ONE_PIXEL
+    }
+
+    SECTION("gray16 striped") {
+        TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray16_striped.tif")
+            REQUIRE( tiff_reader.rows_per_strip() == 16 );
+        REQUIRE( tiff_reader.bits_per_sample() == 16 );
+        REQUIRE( tiff_reader.is_tiled() == false );
+        REQUIRE( tiff_reader.tile_width() == 0 );
+        REQUIRE( tiff_reader.tile_height() == 0 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_gray16>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_NO_ALPHA_GRAY( data );
+        TIFF_READ_ONE_PIXEL
+    }
+
+    SECTION("gray16 tiled") {
+        TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray16_tiled.tif")
+            REQUIRE( tiff_reader.rows_per_strip() == 0 );
+        REQUIRE( tiff_reader.bits_per_sample() == 16 );
+        REQUIRE( tiff_reader.is_tiled() == true );
+        REQUIRE( tiff_reader.tile_width() == 256 );
+        REQUIRE( tiff_reader.tile_height() == 256 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_gray16>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_NO_ALPHA_GRAY( data );
+        TIFF_READ_ONE_PIXEL
+    }
+
+    SECTION("gray32f striped") {
+        TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray32f_striped.tif")
+            REQUIRE( tiff_reader.rows_per_strip() == 8 );
+        REQUIRE( tiff_reader.bits_per_sample() == 32 );
+        REQUIRE( tiff_reader.is_tiled() == false );
+        REQUIRE( tiff_reader.tile_width() == 0 );
+        REQUIRE( tiff_reader.tile_height() == 0 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_NONE );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_gray32f>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_NO_ALPHA_GRAY( data );
+        TIFF_READ_ONE_PIXEL
+    }
+
+    SECTION("gray32f tiled") {
+        TIFF_ASSERT("./test/data/tiff/ndvi_256x256_gray32f_tiled.tif")
+            REQUIRE( tiff_reader.rows_per_strip() == 0 );
+        REQUIRE( tiff_reader.bits_per_sample() == 32 );
+        REQUIRE( tiff_reader.is_tiled() == true );
+        REQUIRE( tiff_reader.tile_width() == 256 );
+        REQUIRE( tiff_reader.tile_height() == 256 );
+        REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK );
+        REQUIRE( tiff_reader.compression() == COMPRESSION_LZW );
+        mapnik::image_any data = reader->read(0, 0, reader->width(), reader->height());
+        REQUIRE( data.is<mapnik::image_gray32f>() == true );
+        TIFF_ASSERT_SIZE( data,reader );
+        TIFF_ASSERT_NO_ALPHA_GRAY( data );
+        TIFF_READ_ONE_PIXEL
+    }
 
 }
 
diff --git a/utils/pgsql2sqlite/build.py b/utils/pgsql2sqlite/build.py
index 45d9003..9d909df 100644
--- a/utils/pgsql2sqlite/build.py
+++ b/utils/pgsql2sqlite/build.py
@@ -39,6 +39,20 @@ source = Split(
 program_env['CXXFLAGS'] = copy(env['LIBMAPNIK_CXXFLAGS'])
 program_env['LINKFLAGS'] = copy(env['LIBMAPNIK_LINKFLAGS'])
 program_env.Append(CPPDEFINES = env['LIBMAPNIK_DEFINES'])
+program_env['LIBS'] = []
+
+if env['RUNTIME_LINK'] == 'static':
+    # pkg-config is more reliable than pg_config across platforms
+    cmd = 'pkg-config libpq --libs --static'
+    try:
+        program_env.ParseConfig(cmd)
+    except OSError, e:
+        program_env.Append(LIBS='pq')
+else:
+    program_env.Append(LIBS='pq')
+
+# Link Library to Dependencies
+libraries = copy(program_env['LIBS'])
 
 if env['HAS_CAIRO']:
     program_env.PrependUnique(CPPPATH=env['CAIRO_CPPPATHS'])
@@ -46,9 +60,8 @@ if env['HAS_CAIRO']:
 
 program_env.PrependUnique(CPPPATH=['#plugins/input/postgis'])
 
-libraries = []
 boost_program_options = 'boost_program_options%s' % env['BOOST_APPEND']
-libraries.extend([boost_program_options,'sqlite3','pq',env['MAPNIK_NAME'],'icuuc'])
+libraries.extend([boost_program_options,'sqlite3',env['MAPNIK_NAME'],'icuuc'])
 
 if env.get('BOOST_LIB_VERSION_FROM_HEADER'):
     boost_version_from_header = int(env['BOOST_LIB_VERSION_FROM_HEADER'].split('_')[1])
@@ -59,13 +72,8 @@ if env.get('BOOST_LIB_VERSION_FROM_HEADER'):
 if env['SQLITE_LINKFLAGS']:
     program_env.Append(LINKFLAGS=env['SQLITE_LINKFLAGS'])
 
-if env['RUNTIME_LINK'] == 'static':
-    if env['PLATFORM'] == 'Darwin':
-        libraries.extend(['ldap', 'pam', 'ssl', 'crypto', 'krb5'])
-    else:
-        # TODO - parse back into libraries variable
-        program_env.ParseConfig('pg_config --libs')
-        libraries.append('dl')
+if env['RUNTIME_LINK'] == 'static' and env['PLATFORM'] == 'Linux':
+    libraries.append('dl')
 
 pgsql2sqlite = program_env.Program('pgsql2sqlite', source, LIBS=libraries)
 Depends(pgsql2sqlite, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME']))
diff --git a/utils/shapeindex/shapeindex.cpp b/utils/shapeindex/shapeindex.cpp
index 9dcff11..bad45d2 100644
--- a/utils/shapeindex/shapeindex.cpp
+++ b/utils/shapeindex/shapeindex.cpp
@@ -37,7 +37,7 @@
 #pragma GCC diagnostic pop
 
 const int DEFAULT_DEPTH = 8;
-const double DEFAULT_RATIO=0.55;
+const double DEFAULT_RATIO = 0.55;
 
 int main (int argc,char** argv)
 {
@@ -278,7 +278,8 @@ int main (int argc,char** argv)
         }
         else
         {
-            std::clog << "No non-empty geometries in shapefile" << std::endl;
+            std::clog << "Failed to read any features from \"" << filename << "\"" << std::endl;
+            return EXIT_FAILURE;
         }
     }
 

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



More information about the Pkg-grass-devel mailing list