Merge remote-tracking branch 'upstream/master' into libimagequant

Conflicts:
	src/image_util_png.cpp
This commit is contained in:
Daniel Patterson 2015-05-16 12:42:12 -07:00
commit b89e721d1b
57 changed files with 1161 additions and 595 deletions

View file

@ -42,6 +42,7 @@ before_install:
- export COVERAGE=${COVERAGE:-false}
- export MASON_PUBLISH=${MASON_PUBLISH:-false}
- if [[ ${TRAVIS_BRANCH} != 'master' ]]; then export MASON_PUBLISH=false; fi
- if [[ ${TRAVIS_PULL_REQUEST} != 'false' ]]; then export MASON_PUBLISH=false; fi
install:
- if [[ $(uname -s) == 'Linux' ]]; then

View file

@ -330,8 +330,8 @@ struct gray8T
//--------------------------------------------------------------------
self_type& opacity(double a_)
{
if (a_ < 0) a_ = 0;
else if (a_ > 1) a_ = 1;
if (a_ < 0) a = 0;
else if (a_ > 1) a = 1;
else a = (value_type)uround(a_ * double(base_mask));
return *this;
}

View file

@ -80,8 +80,8 @@ struct rgba
//--------------------------------------------------------------------
rgba& opacity(double a_)
{
if (a_ < 0) a_ = 0;
else if (a_ > 1) a_ = 1;
if (a_ < 0) a = 0;
else if (a_ > 1) a = 1;
else a = a_;
return *this;
}
@ -472,8 +472,8 @@ struct rgba8T
//--------------------------------------------------------------------
self_type& opacity(double a_)
{
if (a_ < 0) a_ = 0;
else if (a_ > 1) a_ = 1;
if (a_ < 0) a = 0;
else if (a_ > 1) a = 1;
else a = (value_type)uround(a_ * double(base_mask));
return *this;
}
@ -882,8 +882,8 @@ struct rgba16
//--------------------------------------------------------------------
AGG_INLINE self_type& opacity(double a_)
{
if (a_ < 0) a_ = 0;
if (a_ > 1) a_ = 1;
if (a_ < 0) a = 0;
if (a_ > 1) a = 1;
a = value_type(uround(a_ * double(base_mask)));
return *this;
}
@ -1238,8 +1238,8 @@ struct rgba32
//--------------------------------------------------------------------
AGG_INLINE self_type& opacity(double a_)
{
if (a_ < 0) a_ = 0;
else if (a_ > 1) a_ = 1;
if (a_ < 0) a = 0;
else if (a_ > 1) a = 1;
else a = value_type(a_);
return *this;
}

View file

@ -18,8 +18,6 @@ Developers with commit access can update test data like:
git remote set-url origin git@github.com:mapnik/test-data
git commit -a -m "update test data"
git push origin HEAD:master
cd ../../
git commit test/data -m "update test-data submodule"
And the visual test data can up updated like:
@ -27,6 +25,7 @@ And the visual test data can up updated like:
git remote set-url origin git@github.com:mapnik/test-data-visual
git add styles/* images/*
git commit -a -m "add more visual tests"
git push origin HEAD:master
After updating the test data you can then do:
@ -35,7 +34,7 @@ After updating the test data you can then do:
# the submodule should be marked dirty
git status
# now commit the changes to the submodule
git commit -a -m "update visual tests and data"
git commit test/data test/data-visual -m "update visual tests and data"
## Community

View file

@ -48,8 +48,6 @@ namespace mapnik
(((std::uint64_t) ((std::uint8_t) (A)[1])) << 48) | \
(((std::uint64_t) ((std::uint8_t) (A)[0])) << 56))
using byte = std::uint8_t;
#define float8net(V,M) do { double def_temp; \
((std::uint8_t*) &def_temp)[0]=(M)[7]; \
((std::uint8_t*) &def_temp)[1]=(M)[6]; \

View file

@ -98,7 +98,7 @@ class hextree : private util::noncopyable
// penalty of using this node as color
double reduce_cost;
// number of !=0 positions in children_ array
byte children_count;
std::uint8_t children_count;
};
// highest reduce_cost first
@ -184,7 +184,7 @@ public:
}
// process alpha value based on trans_mode_
byte preprocessAlpha(byte a) const
std::uint8_t preprocessAlpha(std::uint8_t a) const
{
switch(trans_mode_)
{
@ -199,7 +199,7 @@ public:
void insert(T const& data)
{
byte a = preprocessAlpha(data.a);
std::uint8_t a = preprocessAlpha(data.a);
unsigned level = 0;
node * cur_node = root_.get();
if (a < InsertPolicy::MIN_ALPHA)
@ -238,7 +238,7 @@ public:
// return color index in returned earlier palette
int quantize(unsigned val) const
{
byte a = preprocessAlpha(U2ALPHA(val));
std::uint8_t a = preprocessAlpha(U2ALPHA(val));
unsigned ind=0;
if (a < InsertPolicy::MIN_ALPHA || colors_ == 0)
{
@ -396,12 +396,12 @@ private:
if (itr->count != 0)
{
unsigned count = itr->count;
byte a = byte(itr->alphas/float(count));
std::uint8_t a = std::uint8_t(itr->alphas/float(count));
if (a > InsertPolicy::MAX_ALPHA) a = 255;
if (a < InsertPolicy::MIN_ALPHA) a = 0;
palette.push_back(rgba((byte)round(gamma(itr->reds / count, gamma_)),
(byte)round(gamma(itr->greens / count, gamma_)),
(byte)round(gamma(itr->blues / count, gamma_)), a));
palette.push_back(rgba((std::uint8_t)round(gamma(itr->reds / count, gamma_)),
(std::uint8_t)round(gamma(itr->greens / count, gamma_)),
(std::uint8_t)round(gamma(itr->blues / count, gamma_)), a));
}
for (unsigned idx=0; idx < 16; ++idx)
{

View file

@ -39,7 +39,10 @@ struct MAPNIK_DECL buffer
~buffer();
buffer& operator=(buffer rhs);
bool operator!() const;
inline bool operator!() const
{
return (data_ == nullptr)? true : false;
}
void swap(buffer & rhs);
unsigned char* data();

View file

@ -0,0 +1,38 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_IMAGE_OPTIONS_HPP
#define MAPNIK_IMAGE_OPTIONS_HPP
#include <map>
#include <string>
#include <boost/optional.hpp>
namespace mapnik {
using image_options_map = std::map<std::string, boost::optional<std::string> >;
inline std::string to_string(boost::optional<std::string> const& val) { return val ? *val : "<unitialised>";}
image_options_map parse_image_options(std::string const& options);
}
#endif // MAPNIK_IMAGE_OPTIONS_HPP

View file

@ -26,11 +26,6 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/pixel_types.hpp>
//#include <mapnik/image.hpp>
//#include <mapnik/image_any.hpp>
//#include <mapnik/image_view.hpp>
//#include <mapnik/image_view_any.hpp>
//#include <mapnik/color.hpp>
// boost
#pragma GCC diagnostic push
@ -53,15 +48,15 @@ struct image_view_any;
template <typename T> class image_view;
class color;
class ImageWriterException : public std::exception
class image_writer_exception : public std::exception
{
private:
std::string message_;
public:
ImageWriterException(std::string const& message)
image_writer_exception(std::string const& message)
: message_(message) {}
~ImageWriterException() throw() {}
~image_writer_exception() throw() {}
virtual const char* what() const throw()
{
@ -420,7 +415,6 @@ void add_border(T & image)
image(image.width()-1,y) = 0xffff0000; // blue
}
}
}
#endif // MAPNIK_IMAGE_UTIL_HPP

View file

@ -97,24 +97,24 @@ public:
std::vector<std::string>& styles();
/*!
* @param min_zoom The minimum zoom level to set
* @param minimum_scale_denom The minimum scale denominator
*/
void set_min_zoom(double min_zoom);
void set_minimum_scale_denominator(double minimum_scale_denom);
/*!
* @param max_zoom The maximum zoom level to set
* @param maximum_scale_denom The maximum scale denominator
*/
void set_max_zoom(double max_zoom);
void set_maximum_scale_denominator(double maximum_scale_denom);
/*!
* @return the minimum zoom level of the layer.
*/
double min_zoom() const;
double minimum_scale_denominator() const;
/*!
* @return the maximum zoom level of the layer.
*/
double max_zoom() const;
double maximum_scale_denominator() const;
/*!
* @brief Set whether this layer is active and will be rendered.
@ -137,18 +137,18 @@ public:
bool queryable() const;
/*!
* @brief Get the visability for a specific scale.
* @brief Get the visibility for a specific scale denominator.
*
* @param scale Accepts an integer or float input.
* @param scale_denom Accepts an integer or float input.
*
* @return true if this layer's data is active and visible at a given scale.
* @return true if this layer's data is active and visible at a given scale denominator.
* Otherwise returns False.
* false if:
* scale >= minzoom - 1e-6
* scale_denominator >= minimum_scale_denominator - 1e-6
* or
* scale < maxzoom + 1e-6
* scale_denominator < maximum_scale_denominator + 1e-6
*/
bool visible(double scale) const;
bool visible(double scale_denom) const;
/*!
* @param clear_cache Set whether this layer's labels are cached.
@ -207,8 +207,8 @@ public:
private:
std::string name_;
std::string srs_;
double min_zoom_;
double max_zoom_;
double minimum_scale_denom_;
double maximum_scale_denom_;
bool active_;
bool queryable_;
bool clear_label_cache_;

View file

@ -25,25 +25,22 @@
// mapnik
#include <mapnik/image.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/svg/svg_storage.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/util/variant.hpp>
// agg
#include "agg_array.h"
// boost
#include <boost/optional.hpp>
// stl
#include <memory>
namespace mapnik
{
struct image_any;
namespace svg { struct path_attributes; }
using attr_storage = agg::pod_bvector<mapnik::svg::path_attributes>;
using svg_storage_type = mapnik::svg::svg_storage<mapnik::svg::svg_path_storage,attr_storage>;
using svg_path_ptr = std::shared_ptr<svg_storage_type>;

View file

@ -31,7 +31,6 @@
// boost
#include <boost/unordered_map.hpp>
#include <memory>
#include <boost/optional.hpp>
namespace mapnik
{

View file

@ -23,39 +23,32 @@
#ifndef MAPNIK_MARKER_HELPERS_HPP
#define MAPNIK_MARKER_HELPERS_HPP
#include <mapnik/color.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/color.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/geometry_type.hpp>
#include <mapnik/geometry_centroid.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/expression_node.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/svg/svg_converter.hpp>
#include <mapnik/marker.hpp> // for svg_storage_type
#include <mapnik/markers_placement.hpp>
#include <mapnik/attribute.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/vertex_converters.hpp>
#include <mapnik/vertex_processor.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/renderer_common/apply_vertex_converter.hpp>
// agg
#include "agg_trans_affine.h"
// boost
#include <boost/optional.hpp>
// stl
#include <memory>
#include <type_traits> // remove_reference
#include <cmath>
namespace mapnik {
struct clip_poly_tag;
namespace svg { struct path_attributes; }
using svg_attribute_type = agg::pod_bvector<svg::path_attributes>;
template <typename Detector>

View file

@ -23,13 +23,19 @@
#ifndef MAPNIK_MARKERS_PLACEMENTS_POINT_HPP
#define MAPNIK_MARKERS_PLACEMENTS_POINT_HPP
#include <mapnik/box2d.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/geometry_types.hpp>
#include <mapnik/util/math.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/symbolizer_enumerations.hpp>
#include <mapnik/util/noncopyable.hpp>
#include "agg_basics.h"
#include "agg_trans_affine.h"
#include <cmath>
namespace mapnik {
struct markers_placement_params

View file

@ -88,8 +88,8 @@ class octree : private util::noncopyable
unsigned count;
double reduce_cost;
unsigned count_cum;
byte children_count;
byte index;
std::uint8_t children_count;
std::uint8_t index;
};
struct node_cmp
{
@ -297,9 +297,9 @@ public:
if (itr->count != 0)
{
unsigned count = itr->count;
palette.push_back(rgb(byte(itr->reds/float(count)),
byte(itr->greens/float(count)),
byte(itr->blues/float(count))));
palette.push_back(rgb(std::uint8_t(itr->reds/float(count)),
std::uint8_t(itr->greens/float(count)),
std::uint8_t(itr->blues/float(count))));
itr->index = static_cast<unsigned>(palette.size()) - 1;
}
for (unsigned i=0; i < 8 ;++i)

View file

@ -51,11 +51,11 @@ namespace mapnik {
struct rgba;
struct MAPNIK_DECL rgb {
byte r;
byte g;
byte b;
std::uint8_t r;
std::uint8_t g;
std::uint8_t b;
inline rgb(byte r_, byte g_, byte b_) : r(r_), g(g_), b(b_) {}
inline rgb(std::uint8_t r_, std::uint8_t g_, std::uint8_t b_) : r(r_), g(g_), b(b_) {}
rgb(rgba const& c);
inline bool operator==(const rgb& y) const
@ -66,12 +66,12 @@ struct MAPNIK_DECL rgb {
struct MAPNIK_DECL rgba
{
byte r;
byte g;
byte b;
byte a;
std::uint8_t r;
std::uint8_t g;
std::uint8_t b;
std::uint8_t a;
inline rgba(byte r_, byte g_, byte b_, byte a_)
inline rgba(std::uint8_t r_, std::uint8_t g_, std::uint8_t b_, std::uint8_t a_)
: r(r_),
g(g_),
b(b_),

View file

@ -182,7 +182,7 @@ void reduce_8(T const& in,
for (unsigned x = 0; x < width; ++x)
{
unsigned val = row[x];
byte index = 0;
std::uint8_t index = 0;
int idx = -1;
for(int j=levels-1; j>0; j--)
{
@ -233,7 +233,7 @@ void reduce_4(T const& in,
for (unsigned x = 0; x < width; ++x)
{
unsigned val = row[x];
byte index = 0;
std::uint8_t index = 0;
int idx=-1;
for(int j=levels-1; j>0; j--)
{
@ -642,7 +642,7 @@ void save_as_png8(T1 & file,
{
mapnik::image_rgba8::pixel_type const * row = image.get_row(y);
mapnik::image_gray8::pixel_type * row_out = reduced_image.get_row(y);
byte index = 0;
std::uint8_t index = 0;
for (unsigned x = 0; x < width; ++x)
{

View file

@ -25,8 +25,7 @@
// mapnik
#include <mapnik/pixel_position.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/marker_helpers.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/renderer_common.hpp>

View file

@ -23,7 +23,6 @@
#ifndef MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP
#include <mapnik/renderer_common.hpp>
#include <mapnik/svg/svg_storage.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/vertex_converters.hpp>

View file

@ -190,7 +190,7 @@ struct tag_setter
void operator() (T const&) const
{
// Assume this would be null type
throw ImageWriterException("Could not write TIFF - unknown image type provided");
throw image_writer_exception("Could not write TIFF - unknown image type provided");
}
inline void operator() (image_rgba8 const& data) const
@ -358,7 +358,7 @@ struct tag_setter
inline void operator() (image_null const&) const
{
// Assume this would be null type
throw ImageWriterException("Could not write TIFF - Null image provided");
throw image_writer_exception("Could not write TIFF - Null image provided");
}
private:
@ -406,7 +406,7 @@ void save_as_tiff(T1 & file, T2 const& image, tiff_config const& config)
tiff_dummy_unmap_proc);
if (! output)
{
throw ImageWriterException("Could not write TIFF");
throw image_writer_exception("Could not write TIFF");
}
TIFFSetField(output, TIFFTAG_IMAGEWIDTH, width);
@ -453,7 +453,7 @@ void save_as_tiff(T1 & file, T2 const& image, tiff_config const& config)
}
if (TIFFWriteEncodedStrip(output, TIFFComputeStrip(output, y, 0), strip_buffer.get(), strip_size * sizeof(pixel_type)) == -1)
{
throw ImageWriterException("Could not write TIFF - TIFF Tile Write failed");
throw image_writer_exception("Could not write TIFF - TIFF Tile Write failed");
}
}
}
@ -504,7 +504,7 @@ void save_as_tiff(T1 & file, T2 const& image, tiff_config const& config)
}
if (TIFFWriteEncodedTile(output, TIFFComputeTile(output, x, y, 0, 0), image_out.get(), tile_size * sizeof(pixel_type)) == -1)
{
throw ImageWriterException("Could not write TIFF - TIFF Tile Write failed");
throw image_writer_exception("Could not write TIFF - TIFF Tile Write failed");
}
}
}

View file

@ -208,7 +208,7 @@ vertex_cache::vertex_cache(T & path)
current_subpath_->add_segment(new_x, new_y, 0);
first = false;
}
if (agg::is_line_to(cmd))
else if (agg::is_line_to(cmd))
{
if (first)
{
@ -220,6 +220,14 @@ vertex_cache::vertex_cache(T & path)
double segment_length = std::sqrt(dx*dx + dy*dy);
current_subpath_->add_segment(new_x, new_y, segment_length);
}
else if (agg::is_closed(cmd) && !current_subpath_->vector.empty())
{
segment const & first_segment = current_subpath_->vector[0];
double dx = old_x - first_segment.pos.x;
double dy = old_y - first_segment.pos.y;
double segment_length = std::sqrt(dx*dx + dy*dy);
current_subpath_->add_segment(first_segment.pos.x, first_segment.pos.y, segment_length);
}
old_x = new_x;
old_y = new_y;
}

View file

@ -24,9 +24,12 @@
#define MAPNIK_VIEW_STRATEGY_HPP
// mapnik
#include <mapnik/coord.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/proj_strategy.hpp>
#include <mapnik/view_transform.hpp>
// boost
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/numeric/conversion/cast.hpp>
namespace mapnik
{

View file

@ -5,4 +5,17 @@ if [ $(uname -s) = 'Darwin' ]; then
export DYLD_LIBRARY_PATH="${CURRENT_DIR}/src/":${DYLD_LIBRARY_PATH}
else
export LD_LIBRARY_PATH="${CURRENT_DIR}/src/":${LD_LIBRARY_PATH}
fi
fi
export PATH=$(pwd)/utils/nik2img/:${PATH}
# mapnik-settings.env is an optional file to store
# environment variables that should be used before
# running tests like PROJ_LIB, GDAL_DATA, and ICU_DATA
# These do not normally need to be set except when
# building against binary versions of dependencies like
# done via bootstrap.sh
if [[ -f mapnik-settings.env ]]; then
echo "Inheriting from mapnik-settings.env"
source mapnik-settings.env
fi

View file

@ -27,8 +27,13 @@
#include <algorithm>
// boost
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#include <boost/algorithm/string.hpp>
#include <boost/spirit/include/qi.hpp>
#pragma GCC diagnostic pop
// mapnik
#include <mapnik/boolean.hpp>
#include <mapnik/unicode.hpp>

View file

@ -47,7 +47,6 @@
#include <sstream>
#include <string>
using mapnik::byte;
using mapnik::feature_factory;
using mapnik::context_ptr;

View file

@ -154,10 +154,6 @@ postgis_datasource::postgis_datasource(parameters const& params)
schema_ = geometry_table_.substr(0, idx);
geometry_table_ = geometry_table_.substr(idx + 1);
}
else
{
geometry_table_ = geometry_table_.substr(0);
}
// NOTE: geometry_table_ how should ideally be a table name, but
// there are known edge cases where this will break down and
@ -234,6 +230,10 @@ postgis_datasource::postgis_datasource(parameters const& params)
s << "SELECT ST_SRID(\"" << geometryColumn_ << "\") AS srid FROM ";
if (!geometry_table_.empty())
{
if (!schema_.empty())
{
s << schema_ << '.';
}
s << geometry_table_;
}
else

View file

@ -41,7 +41,6 @@
#include <string>
#include <memory>
using mapnik::byte;
using mapnik::geometry_utils;
using mapnik::feature_factory;
using mapnik::context_ptr;

View file

@ -53,8 +53,9 @@
#include "agg_span_allocator.h"
#include "agg_image_accessors.h"
#include "agg_span_image_filter_rgba.h"
// boost
#include <boost/math/special_functions/round.hpp>
#include <boost/optional.hpp>
// stl
#include <cmath>
@ -415,8 +416,6 @@ struct agg_render_marker_visitor
using blender_type = agg::comp_op_adaptor_rgba_pre<color_type, order_type>; // comp blender
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
using renderer_type = agg::renderer_scanline_aa_solid<renderer_base>;
using svg_attribute_type = agg::pod_bvector<mapnik::svg::path_attributes>;
ras_ptr_->reset();
if (gamma_method_ != GAMMA_POWER || gamma_ != 1.0)
@ -574,7 +573,7 @@ void agg_renderer<T0,T1>::debug_draw_box(R& buf, box2d<double> const& box,
renderer_base renb(pixf);
renderer_type ren(renb);
// compute tranformation matrix
// compute transformation matrix
agg::trans_affine tr = agg::trans_affine_rotation(angle).translate(x, y);
// prepare path
agg::path_storage pbox;

View file

@ -181,6 +181,7 @@ source = Split(
image_view.cpp
image_view_any.cpp
image_any.cpp
image_options.cpp
image_util.cpp
image_util_jpeg.cpp
image_util_png.cpp

View file

@ -55,7 +55,7 @@ void save_to_cairo_file(mapnik::Map const& map, std::string const& filename, dou
{
save_to_cairo_file(map,filename,*type,scale_factor,scale_denominator);
}
else throw ImageWriterException("Could not write file to " + filename );
else throw image_writer_exception("Could not write file to " + filename );
}
void save_to_cairo_file(mapnik::Map const& map,
@ -75,7 +75,7 @@ void save_to_cairo_file(mapnik::Map const& map,
#ifdef CAIRO_HAS_PDF_SURFACE
surface = cairo_surface_ptr(cairo_pdf_surface_create(filename.c_str(),width,height),cairo_surface_closer());
#else
throw ImageWriterException("PDFSurface not supported in the cairo backend");
throw image_writer_exception("PDFSurface not supported in the cairo backend");
#endif
}
#ifdef CAIRO_HAS_SVG_SURFACE
@ -102,7 +102,7 @@ void save_to_cairo_file(mapnik::Map const& map,
#endif
else
{
throw ImageWriterException("unknown file type: " + type);
throw image_writer_exception("unknown file type: " + type);
}
//cairo_t * ctx = cairo_create(surface);

View file

@ -71,11 +71,6 @@ void buffer::swap(buffer & rhs)
std::swap(data_, rhs.data_);
}
inline bool buffer::operator!() const
{
return (data_ == nullptr)? false : true;
}
unsigned char* buffer::data()
{
return data_;

73
src/image_options.cpp Normal file
View file

@ -0,0 +1,73 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2015 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#include <mapnik/image_options.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace mapnik { namespace detail {
namespace qi = boost::spirit::qi;
template <typename Iterator>
struct image_options_grammar
: qi::grammar<Iterator, image_options_map(), boost::spirit::ascii::space_type>
{
using pair_type = std::pair<std::string, boost::optional<std::string>>;
image_options_grammar()
: image_options_grammar::base_type(start)
{
qi::lit_type lit;
qi::char_type char_;
start = pair >> *(lit(':') >> pair)
;
pair = key >> -('=' >> value)
;
key = char_("a-zA-Z_") >> *char_("a-zA-Z_0-9\\.\\-")
;
value = +char_("a-zA-Z_0-9\\.\\-")
;
}
qi::rule<Iterator, image_options_map(), boost::spirit::ascii::space_type> start;
qi::rule<Iterator, pair_type(), boost::spirit::ascii::space_type> pair;
qi::rule<Iterator, std::string(), boost::spirit::ascii::space_type> key, value;
};
} // ns detail
image_options_map parse_image_options(std::string const& str)
{
auto const begin = str.begin();
auto const end = str.end();
boost::spirit::ascii::space_type space;
mapnik::detail::image_options_grammar<std::string::const_iterator> g;
image_options_map options;
bool success = boost::spirit::qi::phrase_parse(begin, end, g, space, options);
if (!success)
{
throw std::runtime_error("Can't parse image options: " + str);
}
return options; // RVO
}
} // ns mapnik

View file

@ -54,14 +54,13 @@
// boost
#include <boost/numeric/conversion/cast.hpp>
namespace mapnik
{
using boost::numeric_cast;
using boost::numeric::positive_overflow;
using boost::numeric::negative_overflow;
namespace mapnik
{
template <typename T>
MAPNIK_DECL std::string save_to_string(T const& image,
std::string const& type,
@ -92,7 +91,7 @@ MAPNIK_DECL void save_to_file(T const& image,
{
save_to_stream<T>(image, file, type, palette);
}
else throw ImageWriterException("Could not write file to " + filename );
else throw image_writer_exception("Could not write file to " + filename );
}
template <typename T>
@ -105,7 +104,7 @@ MAPNIK_DECL void save_to_file(T const& image,
{
save_to_stream<T>(image, file, type);
}
else throw ImageWriterException("Could not write file to " + filename );
else throw image_writer_exception("Could not write file to " + filename );
}
template <typename T>
@ -125,15 +124,15 @@ MAPNIK_DECL void save_to_stream(T const& image,
}
else if (boost::algorithm::starts_with(t, "tif"))
{
throw ImageWriterException("palettes are not currently supported when writing to tiff format (yet)");
throw image_writer_exception("palettes are not currently supported when writing to tiff format (yet)");
}
else if (boost::algorithm::starts_with(t, "jpeg"))
{
throw ImageWriterException("palettes are not currently supported when writing to jpeg format");
throw image_writer_exception("palettes are not currently supported when writing to jpeg format");
}
else throw ImageWriterException("unknown file type: " + type);
else throw image_writer_exception("unknown file type: " + type);
}
else throw ImageWriterException("Could not write to empty stream" );
else throw image_writer_exception("Could not write to empty stream" );
}
// This can be removed once image_any and image_view_any are the only
@ -156,15 +155,15 @@ MAPNIK_DECL void save_to_stream<image_rgba8>(image_rgba8 const& image,
}
else if (boost::algorithm::starts_with(t, "tif"))
{
throw ImageWriterException("palettes are not currently supported when writing to tiff format (yet)");
throw image_writer_exception("palettes are not currently supported when writing to tiff format (yet)");
}
else if (boost::algorithm::starts_with(t, "jpeg"))
{
throw ImageWriterException("palettes are not currently supported when writing to jpeg format");
throw image_writer_exception("palettes are not currently supported when writing to jpeg format");
}
else throw ImageWriterException("unknown file type: " + type);
else throw image_writer_exception("unknown file type: " + type);
}
else throw ImageWriterException("Could not write to empty stream" );
else throw image_writer_exception("Could not write to empty stream" );
}
// This can be removed once image_any and image_view_any are the only
@ -187,15 +186,15 @@ MAPNIK_DECL void save_to_stream<image_view_rgba8>(image_view_rgba8 const& image,
}
else if (boost::algorithm::starts_with(t, "tif"))
{
throw ImageWriterException("palettes are not currently supported when writing to tiff format (yet)");
throw image_writer_exception("palettes are not currently supported when writing to tiff format (yet)");
}
else if (boost::algorithm::starts_with(t, "jpeg"))
{
throw ImageWriterException("palettes are not currently supported when writing to jpeg format");
throw image_writer_exception("palettes are not currently supported when writing to jpeg format");
}
else throw ImageWriterException("unknown file type: " + type);
else throw image_writer_exception("unknown file type: " + type);
}
else throw ImageWriterException("Could not write to empty stream" );
else throw image_writer_exception("Could not write to empty stream" );
}
template <typename T>
@ -227,9 +226,9 @@ MAPNIK_DECL void save_to_stream(T const& image,
webp_saver visitor(stream, t);
util::apply_visitor(visitor, image);
}
else throw ImageWriterException("unknown file type: " + type);
else throw image_writer_exception("unknown file type: " + type);
}
else throw ImageWriterException("Could not write to empty stream" );
else throw image_writer_exception("Could not write to empty stream" );
}
// This can be removed once image_any and image_view_any are the only
@ -267,9 +266,9 @@ MAPNIK_DECL void save_to_stream<image_rgba8>(image_rgba8 const& image,
visitor(image);
//util::apply_visitor(visitor, image);
}
else throw ImageWriterException("unknown file type: " + type);
else throw image_writer_exception("unknown file type: " + type);
}
else throw ImageWriterException("Could not write to empty stream" );
else throw image_writer_exception("Could not write to empty stream" );
}
// This can be removed once image_any and image_view_any are the only
@ -307,9 +306,9 @@ MAPNIK_DECL void save_to_stream<image_view_rgba8>(image_view_rgba8 const& image,
visitor(image);
//util::apply_visitor(visitor, image);
}
else throw ImageWriterException("unknown file type: " + type);
else throw image_writer_exception("unknown file type: " + type);
}
else throw ImageWriterException("Could not write to empty stream" );
else throw image_writer_exception("Could not write to empty stream" );
}
template <typename T>
@ -320,7 +319,7 @@ MAPNIK_DECL void save_to_file(T const& image, std::string const& filename)
{
save_to_file<T>(image, filename, *type);
}
else throw ImageWriterException("Could not write file to " + filename );
else throw image_writer_exception("Could not write file to " + filename );
}
template <typename T>
@ -331,7 +330,7 @@ MAPNIK_DECL void save_to_file(T const& image, std::string const& filename, rgba_
{
save_to_file<T>(image, filename, *type, palette);
}
else throw ImageWriterException("Could not write file to " + filename );
else throw image_writer_exception("Could not write file to " + filename );
}
// image_rgba8
@ -410,18 +409,18 @@ namespace detail {
struct is_solid_visitor
{
bool operator() (image_view_null const&)
bool operator() (image_view_null const&) const
{
return true;
}
bool operator() (image_null const&)
bool operator() (image_null const&) const
{
return true;
}
template <typename T>
bool operator() (T const & data)
bool operator() (T const & data) const
{
using pixel_type = typename T::pixel_type;
if (data.width() > 0 && data.height() > 0)
@ -492,7 +491,7 @@ namespace detail {
struct premultiply_visitor
{
bool operator() (image_rgba8 & data)
bool operator() (image_rgba8 & data) const
{
if (!data.get_premultiplied())
{
@ -506,7 +505,7 @@ struct premultiply_visitor
}
template <typename T>
bool operator() (T &)
bool operator() (T &) const
{
return false;
}
@ -514,7 +513,7 @@ struct premultiply_visitor
struct demultiply_visitor
{
bool operator() (image_rgba8 & data)
bool operator() (image_rgba8 & data) const
{
if (data.get_premultiplied())
{
@ -528,7 +527,7 @@ struct demultiply_visitor
}
template <typename T>
bool operator() (T &)
bool operator() (T &) const
{
return false;
}
@ -540,12 +539,12 @@ struct set_premultiplied_visitor
: status_(status) {}
template <typename T>
void operator() (T & data)
void operator() (T & data) const
{
data.set_premultiplied(status_);
}
private:
bool status_;
bool const status_;
};
} // end detail ns
@ -624,23 +623,24 @@ template MAPNIK_DECL void set_premultiplied_alpha(image_gray64f &, bool);
namespace detail {
namespace {
template <typename T>
inline T clamp(T d, T min, T max)
{
T const t = d < min ? min : d;
return t > max ? max : t;
}
}
struct visitor_set_alpha
{
visitor_set_alpha(float opacity)
: opacity_(opacity) {}
: opacity_(clamp(opacity, 0.0f, 1.0f)) {}
void operator() (image_rgba8 & data)
void operator() (image_rgba8 & data) const
{
using pixel_type = image_rgba8::pixel_type;
if (opacity_ > 1.0)
{
opacity_ = 1.0;
}
if (opacity_ < 0.0)
{
opacity_ = 0.0;
}
pixel_type a1 = static_cast<pixel_type>(255.0 * opacity_);
for (unsigned int y = 0; y < data.height(); ++y)
{
@ -649,7 +649,6 @@ struct visitor_set_alpha
{
pixel_type rgba = row_to[x];
pixel_type a0 = (rgba >> 24) & 0xff;
//unsigned a1 = opacity;
if (a0 == a1) continue;
pixel_type r = rgba & 0xff;
@ -662,14 +661,13 @@ struct visitor_set_alpha
}
template <typename T>
void operator() (T & data)
void operator() (T & data) const
{
throw std::runtime_error("Error: set_alpha with " + std::string(typeid(data).name()) + " is not supported");
}
private:
float opacity_;
float const opacity_;
};
} // end detail ns
@ -715,9 +713,9 @@ namespace detail {
struct visitor_multiply_alpha
{
visitor_multiply_alpha(float opacity)
: opacity_(opacity) {}
: opacity_(clamp(opacity, 0.0f, 1.0f)) {}
void operator() (image_rgba8 & data)
void operator() (image_rgba8 & data) const
{
using pixel_type = image_rgba8::pixel_type;
for (unsigned int y = 0; y < data.height(); ++y)
@ -726,40 +724,23 @@ struct visitor_multiply_alpha
for (unsigned int x = 0; x < data.width(); ++x)
{
pixel_type rgba = row_to[x];
pixel_type a0 = (rgba >> 24) & 0xff;
pixel_type a1;
try
{
a1 = numeric_cast<std::uint8_t>(((rgba >> 24) & 0xff) * opacity_);
}
catch(negative_overflow&)
{
a1 = std::numeric_limits<std::uint8_t>::min();
}
catch(positive_overflow&)
{
a1 = std::numeric_limits<std::uint8_t>::max();
}
//unsigned a1 = opacity;
if (a0 == a1) continue;
pixel_type a = static_cast<uint8_t>(((rgba >> 24) & 0xff) * opacity_);
pixel_type r = rgba & 0xff;
pixel_type g = (rgba >> 8 ) & 0xff;
pixel_type b = (rgba >> 16) & 0xff;
row_to[x] = (a1 << 24)| (b << 16) | (g << 8) | (r) ;
row_to[x] = (a << 24) | (b << 16) | (g << 8) | (r);
}
}
}
template <typename T>
void operator() (T & data)
void operator() (T & data) const
{
throw std::runtime_error("Error: multiply_alpha with " + std::string(typeid(data).name()) + " is not supported");
}
private:
float opacity_;
private:
float const opacity_;
};
@ -805,7 +786,7 @@ namespace detail {
struct visitor_set_grayscale_to_alpha
{
void operator() (image_rgba8 & data)
void operator() (image_rgba8 & data) const
{
using pixel_type = image_rgba8::pixel_type;
for (unsigned int y = 0; y < data.height(); ++y)
@ -827,7 +808,7 @@ struct visitor_set_grayscale_to_alpha
}
template <typename T>
void operator() (T & data)
void operator() (T & data) const
{
MAPNIK_LOG_WARN(image_util) << "Warning: set_grayscale_to_alpha with " + std::string(typeid(data).name()) + " is not supported, image was not modified";
}
@ -838,7 +819,7 @@ struct visitor_set_grayscale_to_alpha_c
visitor_set_grayscale_to_alpha_c(color const& c)
: c_(c) {}
void operator() (image_rgba8 & data)
void operator() (image_rgba8 & data) const
{
using pixel_type = image_rgba8::pixel_type;
for (unsigned int y = 0; y < data.height(); ++y)
@ -860,7 +841,7 @@ struct visitor_set_grayscale_to_alpha_c
}
template <typename T>
void operator() (T & data)
void operator() (T & data) const
{
MAPNIK_LOG_WARN(image_util) << "Warning: set_grayscale_to_alpha with " + std::string(typeid(data).name()) + " is not supported, image was not modified";
}
@ -950,7 +931,7 @@ struct visitor_set_color_to_alpha
visitor_set_color_to_alpha(color const& c)
: c_(c) {}
void operator() (image_rgba8 & data)
void operator() (image_rgba8 & data) const
{
using pixel_type = image_rgba8::pixel_type;
for (unsigned y = 0; y < data.height(); ++y)
@ -971,7 +952,7 @@ struct visitor_set_color_to_alpha
}
template <typename T>
void operator() (T & data)
void operator() (T & data) const
{
throw std::runtime_error("Error: set_color_to_alpha with " + std::string(typeid(data).name()) + " is not supported");
}
@ -1029,7 +1010,7 @@ struct visitor_fill
: val_(val) {}
template <typename T2>
void operator() (T2 & data)
void operator() (T2 & data) const
{
using pixel_type = typename T2::pixel_type;
pixel_type val;
@ -1058,7 +1039,7 @@ struct visitor_fill<color>
visitor_fill(color const& val)
: val_(val) {}
void operator() (image_rgba8 & data)
void operator() (image_rgba8 & data) const
{
using pixel_type = image_rgba8::pixel_type;
pixel_type val = static_cast<pixel_type>(val_.rgba());
@ -1067,7 +1048,7 @@ struct visitor_fill<color>
}
template <typename T2>
void operator() (T2 & data)
void operator() (T2 & data) const
{
using pixel_type = typename T2::pixel_type;
pixel_type val = static_cast<pixel_type>(val_.rgba());
@ -1314,7 +1295,7 @@ struct visitor_set_rectangle
visitor_set_rectangle(image_any const & src, int x0, int y0)
: src_(src), x0_(x0), y0_(y0) {}
void operator()(image_rgba8 & dst)
void operator()(image_rgba8 & dst) const
{
using pixel_type = image_rgba8::pixel_type;
image_rgba8 src = util::get<image_rgba8>(src_);
@ -1340,13 +1321,13 @@ struct visitor_set_rectangle
}
}
void operator() (image_null &)
void operator() (image_null &) const
{
throw std::runtime_error("Set rectangle not support for null images");
}
template <typename T>
void operator() (T & dst)
void operator() (T & dst) const
{
using pixel_type = typename T::pixel_type;
T src = util::get<T>(src_);
@ -1408,14 +1389,14 @@ struct visitor_composite_pixel
// Obviously c variable would only work for rgba8 currently, but didn't want to
// make this a template class until new rgba types exist.
visitor_composite_pixel(unsigned op, int x,int y, unsigned c, unsigned cover, double opacity)
: opacity_(opacity),
: opacity_(clamp(opacity, 0.0, 1.0)),
op_(op),
x_(x),
y_(y),
c_(c),
cover_(cover) {}
void operator() (image_rgba8 & data)
void operator() (image_rgba8 & data) const
{
using color_type = agg::rgba8;
using value_type = color_type::value_type;
@ -1424,29 +1405,29 @@ struct visitor_composite_pixel
if (mapnik::check_bounds(data, x_, y_))
{
unsigned rgba = data(x_,y_);
unsigned ca = (unsigned)(((c_ >> 24) & 0xff) * opacity_);
unsigned cb = (c_ >> 16 ) & 0xff;
unsigned cg = (c_ >> 8) & 0xff;
unsigned cr = (c_ & 0xff);
blender_type::blend_pix(op_, (value_type*)&rgba, cr, cg, cb, ca, cover_);
image_rgba8::pixel_type rgba = data(x_,y_);
value_type ca = static_cast<unsigned>(((c_ >> 24) & 0xff) * opacity_);
value_type cb = (c_ >> 16 ) & 0xff;
value_type cg = (c_ >> 8) & 0xff;
value_type cr = (c_ & 0xff);
blender_type::blend_pix(op_, reinterpret_cast<value_type*>(&rgba), cr, cg, cb, ca, cover_);
data(x_,y_) = rgba;
}
}
template <typename T>
void operator() (T & data)
void operator() (T & data) const
{
throw std::runtime_error("Composite pixel is not supported for this data type");
}
private:
double opacity_;
double const opacity_;
unsigned op_;
int x_;
int y_;
int c_;
unsigned cover_;
int const x_;
int const y_;
int const c_;
unsigned const cover_;
};
@ -1485,7 +1466,7 @@ struct visitor_set_pixel
: val_(val), x_(x), y_(y) {}
template <typename T2>
void operator() (T2 & data)
void operator() (T2 & data) const
{
using pixel_type = typename T2::pixel_type;
pixel_type val;
@ -1509,8 +1490,8 @@ struct visitor_set_pixel
private:
T1 const& val_;
std::size_t x_;
std::size_t y_;
std::size_t const x_;
std::size_t const y_;
};
template<>
@ -1520,7 +1501,7 @@ struct visitor_set_pixel<color>
: val_(val), x_(x), y_(y) {}
template <typename T2>
void operator() (T2 & data)
void operator() (T2 & data) const
{
using pixel_type = typename T2::pixel_type;
pixel_type val;
@ -1548,8 +1529,8 @@ struct visitor_set_pixel<color>
private:
color const& val_;
std::size_t x_;
std::size_t y_;
std::size_t const x_;
std::size_t const y_;
};
} // end detail ns
@ -1790,8 +1771,9 @@ struct visitor_get_pixel
: x_(x), y_(y) {}
template <typename T2>
T1 operator() (T2 const& data)
T1 operator() (T2 const& data) const
{
using pixel_type = T1;
if (check_bounds(data, x_, y_))
{
T1 val;
@ -1816,8 +1798,8 @@ struct visitor_get_pixel
}
private:
std::size_t x_;
std::size_t y_;
std::size_t const x_;
std::size_t const y_;
};
template<>
@ -1827,7 +1809,7 @@ struct visitor_get_pixel<color>
: x_(x), y_(y) {}
template <typename T2>
color operator() (T2 const& data)
color operator() (T2 const& data) const
{
if (check_bounds(data, x_, y_))
{
@ -1840,8 +1822,8 @@ struct visitor_get_pixel<color>
}
private:
std::size_t x_;
std::size_t y_;
std::size_t const x_;
std::size_t const y_;
};
} // end detail ns
@ -2338,22 +2320,22 @@ struct visitor_create_view
visitor_create_view(unsigned x,unsigned y, unsigned w, unsigned h)
: x_(x), y_(y), w_(w), h_(h) {}
image_view_any operator() (image_null const&)
image_view_any operator() (image_null const&) const
{
throw std::runtime_error("Can not make a view from a null image");
}
template <typename T>
image_view_any operator() (T const& data)
image_view_any operator() (T const& data) const
{
image_view<T> view(x_,y_,w_,h_,data);
return image_view_any(view);
}
private:
unsigned x_;
unsigned y_;
unsigned w_;
unsigned h_;
unsigned const x_;
unsigned const y_;
unsigned const w_;
unsigned const h_;
};
} // end detail ns
@ -2428,8 +2410,8 @@ MAPNIK_DECL unsigned compare<image_rgba8>(image_rgba8 const& im1, image_rgba8 co
{
for (unsigned int y = 0; y < im1.height(); ++y)
{
const std::uint32_t * row_from = im1.get_row(y);
const std::uint32_t * row_from2 = im2.get_row(y);
const pixel_type * row_from = im1.get_row(y);
const pixel_type * row_from2 = im2.get_row(y);
int x = 0;
for (; x < ROUND_DOWN(im1.width(),4); x +=4 )
{
@ -2462,8 +2444,8 @@ MAPNIK_DECL unsigned compare<image_rgba8>(image_rgba8 const& im1, image_rgba8 co
__m128i m_thres = _mm_set1_epi8(thres);
for (unsigned int y = 0; y < im1.height(); ++y)
{
const std::uint32_t * row_from = im1.get_row(y);
const std::uint32_t * row_from2 = im2.get_row(y);
const pixel_type * row_from = im1.get_row(y);
const pixel_type * row_from2 = im2.get_row(y);
int x = 0;
for (; x < ROUND_DOWN(im1.width(),4); x +=4 )
{
@ -2512,8 +2494,8 @@ MAPNIK_DECL unsigned compare<image_rgba8>(image_rgba8 const& im1, image_rgba8 co
#else
for (unsigned int y = 0; y < im1.height(); ++y)
{
const std::uint32_t * row_from = im1.get_row(y);
const std::uint32_t * row_from2 = im2.get_row(y);
const pixel_type * row_from = im1.get_row(y);
const pixel_type * row_from2 = im2.get_row(y);
for (unsigned int x = 0; x < im1.width(); ++x)
{
unsigned rgba = row_from[x];
@ -2550,10 +2532,12 @@ namespace detail
struct visitor_compare
{
visitor_compare(image_any const& im2, double threshold, bool alpha)
: im2_(im2), threshold_(threshold), alpha_(alpha) {}
: im2_(im2),
threshold_(threshold),
alpha_(alpha) {}
template <typename T>
unsigned operator() (T const & im1)
unsigned operator() (T const & im1) const
{
if (!im2_.is<T>())
{
@ -2564,8 +2548,8 @@ struct visitor_compare
private:
image_any const& im2_;
double threshold_;
bool alpha_;
double const threshold_;
bool const alpha_;
};
} // end detail ns

View file

@ -29,11 +29,9 @@
#include <mapnik/image_util_jpeg.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_view.hpp>
#include <mapnik/image_options.hpp>
#include <mapnik/util/conversions.hpp>
// boost
#include <boost/tokenizer.hpp>
// stl
#include <string>
@ -48,25 +46,22 @@ void process_rgba8_jpeg(T const& image, std::string const& type, std::ostream &
{
#if defined(HAVE_JPEG)
int quality = 85;
//std::string val = type.substr(4);
if (type != "jpeg")
{
boost::char_separator<char> sep(":");
boost::tokenizer< boost::char_separator<char> > tokens(type, sep);
for (auto const& t : tokens)
for (auto const& kv : parse_image_options(type))
{
if (t == "jpeg")
auto const& key = kv.first;
auto const& val = kv.second;
if ( key == "jpeg" ) continue;
if ( key == "quality")
{
continue;
}
else if (boost::algorithm::starts_with(t, "quality="))
{
std::string val = t.substr(8);
if (!val.empty())
if (val && ! (*val).empty())
{
if (!mapnik::util::string2int(val,quality) || quality < 0 || quality > 100)
if (!mapnik::util::string2int(*val, quality) || quality < 0 || quality > 100)
{
throw ImageWriterException("invalid jpeg quality: '" + val + "'");
throw image_writer_exception("invalid jpeg quality: '" + *val + "'");
}
}
}
@ -74,7 +69,7 @@ void process_rgba8_jpeg(T const& image, std::string const& type, std::ostream &
}
save_as_jpeg(stream, quality, image);
#else
throw ImageWriterException("jpeg output is not enabled in your build of Mapnik");
throw image_writer_exception("jpeg output is not enabled in your build of Mapnik");
#endif
}
@ -93,19 +88,19 @@ void jpeg_saver::operator()<image_view_rgba8> (image_view_rgba8 const& image) co
template<>
void jpeg_saver::operator()<image_null> (image_null const& image) const
{
throw ImageWriterException("Can not save a null image to jpeg");
throw image_writer_exception("Can not save a null image to jpeg");
}
template<>
void jpeg_saver::operator()<image_view_null> (image_view_null const& image) const
{
throw ImageWriterException("Can not save a null image to jpeg");
throw image_writer_exception("Can not save a null image to jpeg");
}
template <typename T>
void jpeg_saver::operator() (T const& image) const
{
throw ImageWriterException("Mapnik does not support jpeg grayscale images");
throw image_writer_exception("Mapnik does not support jpeg grayscale images");
}
template void jpeg_saver::operator()<image_rgba8> (image_rgba8 const& image) const;

View file

@ -37,11 +37,9 @@ extern "C"
#include <mapnik/image.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/image_view.hpp>
#include <mapnik/image_options.hpp>
#include <mapnik/util/conversions.hpp>
// boost
#include <boost/tokenizer.hpp>
// stl
#include <string>
#include <iostream>
@ -64,75 +62,70 @@ void handle_png_options(std::string const& type,
opts.paletted = true;
return;
}
boost::char_separator<char> sep(":");
boost::tokenizer< boost::char_separator<char> > tokens(type, sep);
bool set_colors = false;
bool set_gamma = false;
for (std::string const& t : tokens)
for (auto const& kv : parse_image_options(type))
{
if (t == "png8" || t == "png256")
auto const& key = kv.first;
auto const& val = kv.second;
if (key == "png8" || key == "png256")
{
opts.paletted = true;
}
else if (t == "png" || t == "png24" || t == "png32")
else if (key == "png" || key == "png24" || key == "png32")
{
opts.paletted = false;
}
else if (t == "m=o")
else if (key == "m" && val)
{
opts.quantization = png_options::OCTTREE;
if (*val == "o") opts.quantization = png_options::OCTTREE;
else if (*val == "h") opts.quantization = png_options::HEXTREE;
else if (*val == "iq") opts.quantization = png_options::IMGQUANT;
}
else if (t == "m=h")
else if (key == "iqs")
{
opts.quantization = png_options::HEXTREE;
}
else if (t == "m=iq")
{
opts.quantization = png_options::IMGQUANT;
}
else if (boost::algorithm::starts_with(t, "iqs="))
{
if (!mapnik::util::string2int(t.substr(4), opts.iq_speed) || opts.iq_speed < 1 || opts.iq_speed > 10)
if (!val || !mapnik::util::string2int(*val, opts.iq_speed) || opts.iq_speed < 1 || opts.iq_speed > 10)
{
throw ImageWriterException("invalid iq speed parameter: " + t.substr(4));
throw ImageWriterException("invalid iq speed parameter: " + to_string(val));
}
}
else if (boost::algorithm::starts_with(t, "iqd="))
else if (key == "iqd")
{
if (!mapnik::util::string2double(t.substr(4), opts.iq_dither) || opts.iq_dither < 0 || opts.iq_dither > 1)
if (!val || !mapnik::util::string2double(*val, opts.iq_dither) || opts.iq_dither < 0 || opts.iq_dither > 1)
{
throw ImageWriterException("invalid iq dithering parameter: " + t.substr(4));
throw ImageWriterException("invalid iq dithering parameter: " + to_string(val));
}
}
else if (t == "e=miniz")
else if (key == "e" && val && *val == "miniz")
{
opts.use_miniz = true;
}
else if (boost::algorithm::starts_with(t, "c="))
else if (key == "c")
{
set_colors = true;
if (!mapnik::util::string2int(t.substr(2),opts.colors) || opts.colors < 1 || opts.colors > 256)
if (!val || !mapnik::util::string2int(*val, opts.colors) || opts.colors < 1 || opts.colors > 256)
{
throw ImageWriterException("invalid color parameter: " + t.substr(2));
throw image_writer_exception("invalid color parameter: " + to_string(val));
}
}
else if (boost::algorithm::starts_with(t, "t="))
else if (key == "t")
{
if (!mapnik::util::string2int(t.substr(2),opts.trans_mode) || opts.trans_mode < 0 || opts.trans_mode > 2)
if (!val || !mapnik::util::string2int(*val,opts.trans_mode) || opts.trans_mode < 0 || opts.trans_mode > 2)
{
throw ImageWriterException("invalid trans_mode parameter: " + t.substr(2));
throw image_writer_exception("invalid trans_mode parameter: " + to_string(val));
}
}
else if (boost::algorithm::starts_with(t, "g="))
else if (key == "g")
{
set_gamma = true;
if (!mapnik::util::string2double(t.substr(2),opts.gamma) || opts.gamma < 0)
if (!val || !mapnik::util::string2double(*val, opts.gamma) || opts.gamma < 0)
{
throw ImageWriterException("invalid gamma parameter: " + t.substr(2));
throw image_writer_exception("invalid gamma parameter: " + to_string(val));
}
}
else if (boost::algorithm::starts_with(t, "z="))
else if (key == "z")
{
/*
#define Z_NO_COMPRESSION 0
@ -140,58 +133,59 @@ void handle_png_options(std::string const& type,
#define Z_BEST_COMPRESSION 9
#define Z_DEFAULT_COMPRESSION (-1)
*/
if (!mapnik::util::string2int(t.substr(2),opts.compression)
if (!val || !mapnik::util::string2int(*val, opts.compression)
|| opts.compression < Z_DEFAULT_COMPRESSION
|| opts.compression > 10) // use 10 here rather than Z_BEST_COMPRESSION (9) to allow for MZ_UBER_COMPRESSION
{
throw ImageWriterException("invalid compression parameter: " + t.substr(2) + " (only -1 through 10 are valid)");
throw image_writer_exception("invalid compression parameter: " + to_string(val) + " (only -1 through 10 are valid)");
}
}
else if (boost::algorithm::starts_with(t, "s="))
else if (key == "s")
{
std::string s = t.substr(2);
if (s == "default")
if (!val) throw image_writer_exception("invalid compression parameter: <uninitialised>");
if (*val == "default")
{
opts.strategy = Z_DEFAULT_STRATEGY;
}
else if (s == "filtered")
else if (*val == "filtered")
{
opts.strategy = Z_FILTERED;
}
else if (s == "huff")
else if (*val == "huff")
{
opts.strategy = Z_HUFFMAN_ONLY;
}
else if (s == "rle")
else if (*val == "rle")
{
opts.strategy = Z_RLE;
}
else if (s == "fixed")
else if (*val == "fixed")
{
opts.strategy = Z_FIXED;
}
else
{
throw ImageWriterException("invalid compression strategy parameter: " + s);
throw image_writer_exception("invalid compression strategy parameter: " + *val);
}
}
else
{
throw ImageWriterException("unhandled png option: " + t);
throw image_writer_exception("unhandled png option: " + key);
}
}
// validation
if (!opts.paletted && set_colors)
{
throw ImageWriterException("invalid color parameter: unavailable for true color (non-paletted) images");
throw image_writer_exception("invalid color parameter: unavailable for true color (non-paletted) images");
}
if (!opts.paletted && set_gamma)
{
throw ImageWriterException("invalid gamma parameter: unavailable for true color (non-paletted) images");
throw image_writer_exception("invalid gamma parameter: unavailable for true color (non-paletted) images");
}
if ((opts.use_miniz == false) && opts.compression > Z_BEST_COMPRESSION)
{
throw ImageWriterException("invalid compression value: (only -1 through 9 are valid)");
throw image_writer_exception("invalid compression value: (only -1 through 9 are valid)");
}
}
#endif
@ -205,29 +199,29 @@ png_saver_pal::png_saver_pal(std::ostream & stream, std::string const& t, rgba_p
template<>
void png_saver::operator()<image_null> (image_null const& image) const
{
throw ImageWriterException("null images not supported for png");
throw image_writer_exception("null images not supported for png");
}
template<>
void png_saver_pal::operator()<image_null> (image_null const& image) const
{
throw ImageWriterException("null images not supported for png");
throw image_writer_exception("null images not supported for png");
}
template<>
void png_saver::operator()<image_view_null> (image_view_null const& image) const
{
throw ImageWriterException("null image views not supported for png");
throw image_writer_exception("null image views not supported for png");
}
template<>
void png_saver_pal::operator()<image_view_null> (image_view_null const& image) const
{
throw ImageWriterException("null image views not supported for png");
throw image_writer_exception("null image views not supported for png");
}
template <typename T>
void process_rgba8_png_pal(T const& image,
void process_rgba8_png_pal(T const& image,
std::string const& t,
std::ostream & stream,
rgba_palette const& pal)
@ -261,12 +255,12 @@ void process_rgba8_png_pal(T const& image,
save_as_png(stream, image, opts);
}
#else
throw ImageWriterException("png output is not enabled in your build of Mapnik");
throw image_writer_exception("png output is not enabled in your build of Mapnik");
#endif
}
template <typename T>
void process_rgba8_png(T const& image,
void process_rgba8_png(T const& image,
std::string const& t,
std::ostream & stream)
{
@ -293,7 +287,7 @@ void process_rgba8_png(T const& image,
save_as_png(stream, image, opts);
}
#else
throw ImageWriterException("png output is not enabled in your build of Mapnik");
throw image_writer_exception("png output is not enabled in your build of Mapnik");
#endif
}
@ -325,12 +319,12 @@ template <typename T>
void png_saver::operator() (T const& image) const
{
#if defined(HAVE_PNG)
throw ImageWriterException("Mapnik does not support grayscale images for png");
throw image_writer_exception("Mapnik does not support grayscale images for png");
//png_options opts;
//handle_png_options(t_, opts);
//save_as_png(stream_, image, opts);
#else
throw ImageWriterException("png output is not enabled in your build of Mapnik");
throw image_writer_exception("png output is not enabled in your build of Mapnik");
#endif
}
@ -338,12 +332,12 @@ template <typename T>
void png_saver_pal::operator() (T const& image) const
{
#if defined(HAVE_PNG)
throw ImageWriterException("Mapnik does not support grayscale images for png");
throw image_writer_exception("Mapnik does not support grayscale images for png");
//png_options opts;
//handle_png_options(t_, opts);
//save_as_png(stream_, image, opts);
#else
throw ImageWriterException("png output is not enabled in your build of Mapnik");
throw image_writer_exception("png output is not enabled in your build of Mapnik");
#endif
}

View file

@ -29,11 +29,9 @@
#include <mapnik/image_util_tiff.hpp>
#include <mapnik/image.hpp>
#include <mapnik/image_view.hpp>
#include <mapnik/image_options.hpp>
#include <mapnik/util/conversions.hpp>
// boost
#include <boost/tokenizer.hpp>
// stl
#include <string>
@ -50,111 +48,103 @@ void handle_tiff_options(std::string const& type,
}
if (type.length() > 4)
{
boost::char_separator<char> sep(":");
boost::tokenizer< boost::char_separator<char> > tokens(type, sep);
for (auto const& t : tokens)
for (auto const& kv : parse_image_options(type))
{
if (t == "tiff")
auto const& key = kv.first;
auto const& val = kv.second;
if (key == "tiff") continue;
if (key == "compression")
{
continue;
}
else if (boost::algorithm::starts_with(t, "compression="))
{
std::string val = t.substr(12);
if (!val.empty())
if (val && !(*val).empty())
{
if (val == "deflate")
if (*val == "deflate")
{
config.compression = COMPRESSION_DEFLATE;
}
else if (val == "adobedeflate")
else if (*val == "adobedeflate")
{
config.compression = COMPRESSION_ADOBE_DEFLATE;
}
else if (val == "lzw")
else if (*val == "lzw")
{
config.compression = COMPRESSION_LZW;
}
else if (val == "none")
{
else if (*val == "none")
{
config.compression = COMPRESSION_NONE;
}
else
{
throw ImageWriterException("invalid tiff compression: '" + val + "'");
throw image_writer_exception("invalid tiff compression: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "method="))
else if (key == "method")
{
std::string val = t.substr(7);
if (!val.empty())
if (val && !(*val).empty())
{
if (val == "scanline")
if (*val == "scanline")
{
config.method = TIFF_WRITE_SCANLINE;
}
else if (val == "strip" || val == "stripped")
else if (*val == "strip" || *val == "stripped")
{
config.method = TIFF_WRITE_STRIPPED;
}
else if (val == "tiled")
else if (*val == "tiled")
{
config.method = TIFF_WRITE_TILED;
}
else
{
throw ImageWriterException("invalid tiff method: '" + val + "'");
throw image_writer_exception("invalid tiff method: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "zlevel="))
else if (key == "zlevel")
{
std::string val = t.substr(7);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.zlevel) || config.zlevel < 0 || config.zlevel > 9)
if (!mapnik::util::string2int(*val,config.zlevel) || config.zlevel < 0 || config.zlevel > 9)
{
throw ImageWriterException("invalid tiff zlevel: '" + val + "'");
throw image_writer_exception("invalid tiff zlevel: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "tile_height="))
else if (key == "tile_height")
{
std::string val = t.substr(12);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.tile_height) || config.tile_height < 0 )
if (!mapnik::util::string2int(*val,config.tile_height) || config.tile_height < 0 )
{
throw ImageWriterException("invalid tiff tile_height: '" + val + "'");
throw image_writer_exception("invalid tiff tile_height: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "tile_width="))
else if (key == "tile_width")
{
std::string val = t.substr(11);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.tile_width) || config.tile_width < 0 )
if (!mapnik::util::string2int(*val,config.tile_width) || config.tile_width < 0 )
{
throw ImageWriterException("invalid tiff tile_width: '" + val + "'");
throw image_writer_exception("invalid tiff tile_width: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "rows_per_strip="))
else if (key == "rows_per_strip")
{
std::string val = t.substr(15);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.rows_per_strip) || config.rows_per_strip < 0 )
if (!mapnik::util::string2int(*val,config.rows_per_strip) || config.rows_per_strip < 0 )
{
throw ImageWriterException("invalid tiff rows_per_strip: '" + val + "'");
throw image_writer_exception("invalid tiff rows_per_strip: '" + *val + "'");
}
}
}
else
{
throw ImageWriterException("unhandled tiff option: " + t);
throw image_writer_exception("unhandled tiff option: " + key);
}
}
}
@ -167,13 +157,13 @@ tiff_saver::tiff_saver(std::ostream & stream, std::string const& t):
template<>
void tiff_saver::operator()<image_null> (image_null const& image) const
{
throw ImageWriterException("null images not supported");
throw image_writer_exception("null images not supported");
}
template<>
void tiff_saver::operator()<image_view_null> (image_view_null const& image) const
{
throw ImageWriterException("null image views not supported");
throw image_writer_exception("null image views not supported");
}
template <typename T>
@ -184,7 +174,7 @@ void tiff_saver::operator() (T const& image) const
handle_tiff_options(t_, opts);
save_as_tiff(stream_, image, opts);
#else
throw ImageWriterException("tiff output is not enabled in your build of Mapnik");
throw image_writer_exception("tiff output is not enabled in your build of Mapnik");
#endif
}

View file

@ -30,11 +30,9 @@
#include <mapnik/image.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/image_view.hpp>
#include <mapnik/image_options.hpp>
#include <mapnik/util/conversions.hpp>
// boost
#include <boost/tokenizer.hpp>
// stl
#include <string>
#include <iostream>
@ -51,48 +49,45 @@ void handle_webp_options(std::string const& type,
{
return;
}
if (type.length() > 4){
boost::char_separator<char> sep(":");
boost::tokenizer< boost::char_separator<char> > tokens(type, sep);
for (auto const& t : tokens)
if (type.length() > 4)
{
for (auto const& kv : parse_image_options(type))
{
if (t == "webp")
auto const& key = kv.first;
auto const& val = kv.second;
if (key == "webp") continue;
if (key == "quality")
{
continue;
}
else if (boost::algorithm::starts_with(t, "quality="))
{
std::string val = t.substr(8);
if (!val.empty())
if (val && !(*val).empty())
{
double quality = 90;
if (!mapnik::util::string2double(val,quality) || quality < 0.0 || quality > 100.0)
if (!mapnik::util::string2double(*val,quality) || quality < 0.0 || quality > 100.0)
{
throw ImageWriterException("invalid webp quality: '" + val + "'");
throw image_writer_exception("invalid webp quality: '" + *val + "'");
}
config.quality = static_cast<float>(quality);
}
}
else if (boost::algorithm::starts_with(t, "method="))
else if (key == "method")
{
std::string val = t.substr(7);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.method) || config.method < 0 || config.method > 6)
if (!mapnik::util::string2int(*val,config.method) || config.method < 0 || config.method > 6)
{
throw ImageWriterException("invalid webp method: '" + val + "'");
throw image_writer_exception("invalid webp method: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "lossless="))
else if (key == "lossless")
{
std::string val = t.substr(9);
if (!val.empty())
if (val && !(*val).empty())
{
#if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100
if (!mapnik::util::string2int(val,config.lossless) || config.lossless < 0 || config.lossless > 1)
if (!mapnik::util::string2int(*val,config.lossless) || config.lossless < 0 || config.lossless > 1)
{
throw ImageWriterException("invalid webp lossless: '" + val + "'");
throw image_writer_exception("invalid webp lossless: '" + *val + "'");
}
#else
#ifdef _MSC_VER
@ -100,20 +95,19 @@ void handle_webp_options(std::string const& type,
#else
#warning "compiling against webp that does not support the lossless flag"
#endif
throw ImageWriterException("your webp version does not support the lossless option");
throw image_writer_exception("your webp version does not support the lossless option");
#endif
}
}
else if (boost::algorithm::starts_with(t, "image_hint="))
else if (key == "image_hint")
{
std::string val = t.substr(11);
if (!val.empty())
if (val && !(*val).empty())
{
#if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100
int image_hint = 0;
if (!mapnik::util::string2int(val,image_hint) || image_hint < 0 || image_hint > 3)
if (!mapnik::util::string2int(*val,image_hint) || image_hint < 0 || image_hint > 3)
{
throw ImageWriterException("invalid webp image_hint: '" + val + "'");
throw image_writer_exception("invalid webp image_hint: '" + *val + "'");
}
config.image_hint = static_cast<WebPImageHint>(image_hint);
#else
@ -122,131 +116,120 @@ void handle_webp_options(std::string const& type,
#else
#warning "compiling against webp that does not support the image_hint flag"
#endif
throw ImageWriterException("your webp version does not support the image_hint option");
throw image_writer_exception("your webp version does not support the image_hint option");
#endif
}
}
else if (boost::algorithm::starts_with(t, "alpha="))
else if (key == "alpha")
{
std::string val = t.substr(6);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2bool(val,alpha))
if (!mapnik::util::string2bool(*val,alpha))
{
throw ImageWriterException("invalid webp alpha: '" + val + "'");
throw image_writer_exception("invalid webp alpha: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "target_size="))
else if (key == "target_size")
{
std::string val = t.substr(12);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.target_size))
if (!mapnik::util::string2int(*val,config.target_size))
{
throw ImageWriterException("invalid webp target_size: '" + val + "'");
throw image_writer_exception("invalid webp target_size: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "target_psnr="))
else if (key == "target_psnr")
{
std::string val = t.substr(12);
if (!val.empty())
if (val && !(*val).empty())
{
double psnr = 0;
if (!mapnik::util::string2double(val,psnr))
if (!mapnik::util::string2double(*val,psnr))
{
throw ImageWriterException("invalid webp target_psnr: '" + val + "'");
throw image_writer_exception("invalid webp target_psnr: '" + *val + "'");
}
config.target_PSNR = psnr;
}
}
else if (boost::algorithm::starts_with(t, "segments="))
else if (key == "segments")
{
std::string val = t.substr(9);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.segments))
if (!mapnik::util::string2int(*val,config.segments))
{
throw ImageWriterException("invalid webp segments: '" + val + "'");
throw image_writer_exception("invalid webp segments: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "sns_strength="))
else if (key == "sns_strength")
{
std::string val = t.substr(13);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.sns_strength))
if (!mapnik::util::string2int(*val,config.sns_strength))
{
throw ImageWriterException("invalid webp sns_strength: '" + val + "'");
throw image_writer_exception("invalid webp sns_strength: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "filter_strength="))
else if (key == "filter_strength")
{
std::string val = t.substr(16);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.filter_strength))
if (!mapnik::util::string2int(*val,config.filter_strength))
{
throw ImageWriterException("invalid webp filter_strength: '" + val + "'");
throw image_writer_exception("invalid webp filter_strength: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "filter_sharpness="))
else if (key == "filter_sharpness")
{
std::string val = t.substr(17);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.filter_sharpness))
if (!mapnik::util::string2int(*val,config.filter_sharpness))
{
throw ImageWriterException("invalid webp filter_sharpness: '" + val + "'");
throw image_writer_exception("invalid webp filter_sharpness: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "filter_type="))
else if (key == "filter_type")
{
std::string val = t.substr(12);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.filter_type))
if (!mapnik::util::string2int(*val,config.filter_type))
{
throw ImageWriterException("invalid webp filter_type: '" + val + "'");
throw image_writer_exception("invalid webp filter_type: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "autofilter="))
else if (key == "autofilter")
{
std::string val = t.substr(11);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.autofilter))
if (!mapnik::util::string2int(*val,config.autofilter))
{
throw ImageWriterException("invalid webp autofilter: '" + val + "'");
throw image_writer_exception("invalid webp autofilter: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "alpha_compression="))
else if (key == "alpha_compression")
{
std::string val = t.substr(18);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.alpha_compression))
if (!mapnik::util::string2int(*val,config.alpha_compression))
{
throw ImageWriterException("invalid webp alpha_compression: '" + val + "'");
throw image_writer_exception("invalid webp alpha_compression: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "alpha_filtering="))
else if (key == "alpha_filtering")
{
std::string val = t.substr(16);
if (!val.empty())
if (val && !(*val).empty())
{
#if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100
if (!mapnik::util::string2int(val,config.alpha_filtering))
if (!mapnik::util::string2int(*val,config.alpha_filtering))
{
throw ImageWriterException("invalid webp alpha_filtering: '" + val + "'");
throw image_writer_exception("invalid webp alpha_filtering: '" + *val + "'");
}
#else
#ifdef _MSC_VER
@ -254,19 +237,18 @@ void handle_webp_options(std::string const& type,
#else
#warning "compiling against webp that does not support the alpha_filtering flag"
#endif
throw ImageWriterException("your webp version does not support the alpha_filtering option");
throw image_writer_exception("your webp version does not support the alpha_filtering option");
#endif
}
}
else if (boost::algorithm::starts_with(t, "alpha_quality="))
else if (key == "alpha_quality")
{
std::string val = t.substr(14);
if (!val.empty())
if (val && !(*val).empty())
{
#if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100
if (!mapnik::util::string2int(val,config.alpha_quality))
if (!mapnik::util::string2int(*val,config.alpha_quality))
{
throw ImageWriterException("invalid webp alpha_quality: '" + val + "'");
throw image_writer_exception("invalid webp alpha_quality: '" + *val + "'");
}
#else
#ifdef _MSC_VER
@ -274,57 +256,53 @@ void handle_webp_options(std::string const& type,
#else
#warning "compiling against webp that does not support the alpha_quality flag"
#endif
throw ImageWriterException("your webp version does not support the alpha_quality option");
throw image_writer_exception("your webp version does not support the alpha_quality option");
#endif
}
}
else if (boost::algorithm::starts_with(t, "pass="))
else if (key == "pass")
{
std::string val = t.substr(5);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.pass))
if (!mapnik::util::string2int(*val,config.pass))
{
throw ImageWriterException("invalid webp pass: '" + val + "'");
throw image_writer_exception("invalid webp pass: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "preprocessing="))
else if (key == "preprocessing")
{
std::string val = t.substr(14);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.preprocessing))
if (!mapnik::util::string2int(*val,config.preprocessing))
{
throw ImageWriterException("invalid webp preprocessing: '" + val + "'");
throw image_writer_exception("invalid webp preprocessing: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "partitions="))
else if (key == "partitions")
{
std::string val = t.substr(11);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.partitions))
if (!mapnik::util::string2int(*val,config.partitions))
{
throw ImageWriterException("invalid webp partitions: '" + val + "'");
throw image_writer_exception("invalid webp partitions: '" + *val + "'");
}
}
}
else if (boost::algorithm::starts_with(t, "partition_limit="))
else if (key == "partition_limit")
{
std::string val = t.substr(16);
if (!val.empty())
if (val && !(*val).empty())
{
if (!mapnik::util::string2int(val,config.partition_limit))
if (!mapnik::util::string2int(*val,config.partition_limit))
{
throw ImageWriterException("invalid webp partition_limit: '" + val + "'");
throw image_writer_exception("invalid webp partition_limit: '" + *val + "'");
}
}
}
else
{
throw ImageWriterException("unhandled webp option: " + t);
throw image_writer_exception("unhandled webp option: " + key);
}
}
}
@ -337,13 +315,13 @@ webp_saver::webp_saver(std::ostream & stream, std::string const& t):
template<>
void webp_saver::operator()<image_null> (image_null const& image) const
{
throw ImageWriterException("null images not supported");
throw image_writer_exception("null images not supported");
}
template<>
void webp_saver::operator()<image_view_null> (image_view_null const& image) const
{
throw ImageWriterException("null image views not supported");
throw image_writer_exception("null image views not supported");
}
template <typename T>
@ -361,7 +339,7 @@ void process_rgba8_webp(T const& image, std::string const& t, std::ostream & str
handle_webp_options(t,config,alpha);
save_as_webp(stream,image,config,alpha);
#else
throw ImageWriterException("webp output is not enabled in your build of Mapnik");
throw image_writer_exception("webp output is not enabled in your build of Mapnik");
#endif
}
@ -380,7 +358,7 @@ void webp_saver::operator()<image_view_rgba8> (image_view_rgba8 const& image) co
template <typename T>
void webp_saver::operator() (T const& image) const
{
throw ImageWriterException("Mapnik does not support webp grayscale images");
throw image_writer_exception("Mapnik does not support webp grayscale images");
}
template void webp_saver::operator()<image_rgba8> (image_rgba8 const& image) const;

View file

@ -34,8 +34,8 @@ namespace mapnik
layer::layer(std::string const& name, std::string const& srs)
: name_(name),
srs_(srs),
min_zoom_(0),
max_zoom_(std::numeric_limits<double>::max()),
minimum_scale_denom_(0),
maximum_scale_denom_(std::numeric_limits<double>::max()),
active_(true),
queryable_(false),
clear_label_cache_(false),
@ -49,8 +49,8 @@ layer::layer(std::string const& name, std::string const& srs)
layer::layer(layer const& rhs)
: name_(rhs.name_),
srs_(rhs.srs_),
min_zoom_(rhs.min_zoom_),
max_zoom_(rhs.max_zoom_),
minimum_scale_denom_(rhs.minimum_scale_denom_),
maximum_scale_denom_(rhs.maximum_scale_denom_),
active_(rhs.active_),
queryable_(rhs.queryable_),
clear_label_cache_(rhs.clear_label_cache_),
@ -64,8 +64,8 @@ layer::layer(layer const& rhs)
layer::layer(layer && rhs)
: name_(std::move(rhs.name_)),
srs_(std::move(rhs.srs_)),
min_zoom_(std::move(rhs.min_zoom_)),
max_zoom_(std::move(rhs.max_zoom_)),
minimum_scale_denom_(std::move(rhs.minimum_scale_denom_)),
maximum_scale_denom_(std::move(rhs.maximum_scale_denom_)),
active_(std::move(rhs.active_)),
queryable_(std::move(rhs.queryable_)),
clear_label_cache_(std::move(rhs.clear_label_cache_)),
@ -81,8 +81,8 @@ layer& layer::operator=(layer rhs)
using std::swap;
std::swap(this->name_,rhs.name_);
std::swap(this->srs_, rhs.srs_);
std::swap(this->min_zoom_, rhs.min_zoom_);
std::swap(this->max_zoom_,rhs.max_zoom_);
std::swap(this->minimum_scale_denom_, rhs.minimum_scale_denom_);
std::swap(this->maximum_scale_denom_,rhs.maximum_scale_denom_);
std::swap(this->active_, rhs.active_);
std::swap(this->queryable_, rhs.queryable_);
std::swap(this->clear_label_cache_, rhs.clear_label_cache_);
@ -99,8 +99,8 @@ bool layer::operator==(layer const& rhs) const
{
return (name_ == rhs.name_) &&
(srs_ == rhs.srs_) &&
(min_zoom_ == rhs.min_zoom_) &&
(max_zoom_ == rhs.max_zoom_) &&
(minimum_scale_denom_ == rhs.minimum_scale_denom_) &&
(maximum_scale_denom_ == rhs.maximum_scale_denom_) &&
(active_ == rhs.active_) &&
(queryable_ == rhs.queryable_) &&
(clear_label_cache_ == rhs.clear_label_cache_) &&
@ -149,24 +149,24 @@ std::vector<std::string> & layer::styles()
return styles_;
}
void layer::set_min_zoom(double min_zoom)
void layer::set_minimum_scale_denominator(double minimum_scale_denom)
{
min_zoom_=min_zoom;
minimum_scale_denom_=minimum_scale_denom;
}
void layer::set_max_zoom(double max_zoom)
void layer::set_maximum_scale_denominator(double maximum_scale_denom)
{
max_zoom_=max_zoom;
maximum_scale_denom_=maximum_scale_denom;
}
double layer::min_zoom() const
double layer::minimum_scale_denominator() const
{
return min_zoom_;
return minimum_scale_denom_;
}
double layer::max_zoom() const
double layer::maximum_scale_denominator() const
{
return max_zoom_;
return maximum_scale_denom_;
}
void layer::set_active(bool active)
@ -179,9 +179,9 @@ bool layer::active() const
return active_;
}
bool layer::visible(double scale) const
bool layer::visible(double scale_denom) const
{
return active() && scale >= min_zoom_ - 1e-6 && scale < max_zoom_ + 1e-6;
return active() && scale_denom >= minimum_scale_denom_ - 1e-6 && scale_denom < maximum_scale_denom_ + 1e-6;
}
void layer::set_queryable(bool queryable)

View file

@ -587,17 +587,34 @@ void map_parser::parse_layer(Map & map, xml_node const& node)
lyr.set_active(* status);
}
optional<double> min_zoom = node.get_opt_attr<double>("minzoom");
if (min_zoom)
optional<double> minimum_scale_denom = node.get_opt_attr<double>("minimum-scale-denominator");
if (minimum_scale_denom)
{
lyr.set_min_zoom(* min_zoom);
lyr.set_minimum_scale_denominator(* minimum_scale_denom);
}
else // back compatibility: remove at Mapnik 4.x
{
optional<double> min_zoom = node.get_opt_attr<double>("minzoom");
if (min_zoom)
{
MAPNIK_LOG_ERROR(markers_symbolizer) << "'minzoom' is deprecated and will be removed in Mapnik 4.x, use 'minimum-scale-denominator' instead (encountered in layer " << name << ")";
lyr.set_minimum_scale_denominator(* min_zoom);
}
}
optional<double> max_zoom = node.get_opt_attr<double>("maxzoom");
if (max_zoom)
optional<double> maximum_scale_denom = node.get_opt_attr<double>("maximum-scale-denominator");
if (maximum_scale_denom)
{
lyr.set_max_zoom(* max_zoom);
lyr.set_maximum_scale_denominator(* maximum_scale_denom);
}
else // back compatibility: remove at Mapnik 4.x
{
optional<double> max_zoom = node.get_opt_attr<double>("maxzoom");
if (max_zoom)
{
MAPNIK_LOG_ERROR(markers_symbolizer) << "'maxzoom' is deprecated and will be removed in Mapnik 4.x, use 'maximum-scale-denominator' instead (encountered in layer " << name << ")";
lyr.set_maximum_scale_denominator(* max_zoom);
}
}
optional<mapnik::boolean_type> queryable = node.get_opt_attr<mapnik::boolean_type>("queryable");

View file

@ -264,16 +264,32 @@ bool proj_transform::forward (box2d<double> & box) const
if (is_source_equal_dest_)
return true;
double minx = box.minx();
double miny = box.miny();
double maxx = box.maxx();
double maxy = box.maxy();
double llx = box.minx();
double ulx = box.minx();
double lly = box.miny();
double lry = box.miny();
double lrx = box.maxx();
double urx = box.maxx();
double uly = box.maxy();
double ury = box.maxy();
double z = 0.0;
if (!forward(minx,miny,z))
if (!forward(llx,lly,z))
return false;
if (!forward(maxx,maxy,z))
if (!forward(lrx,lry,z))
return false;
box.init(minx,miny,maxx,maxy);
if (!forward(ulx,uly,z))
return false;
if (!forward(urx,ury,z))
return false;
double minx = std::min(ulx, llx);
double miny = std::min(lly, lry);
double maxx = std::max(urx, lrx);
double maxy = std::max(ury, uly);
box.init(minx,
miny,
maxx,
maxy);
return true;
}
@ -282,16 +298,31 @@ bool proj_transform::backward (box2d<double> & box) const
if (is_source_equal_dest_)
return true;
double minx = box.minx();
double miny = box.miny();
double maxx = box.maxx();
double maxy = box.maxy();
double llx = box.minx();
double ulx = box.minx();
double lly = box.miny();
double lry = box.miny();
double lrx = box.maxx();
double urx = box.maxx();
double uly = box.maxy();
double ury = box.maxy();
double z = 0.0;
if (!backward(minx,miny,z))
if (!backward(llx,lly,z))
return false;
if (!backward(maxx,maxy,z))
if (!backward(lrx,lry,z))
return false;
box.init(minx,miny,maxx,maxy);
if (!backward(ulx,uly,z))
return false;
if (!backward(urx,ury,z))
return false;
double minx = std::min(ulx, llx);
double miny = std::min(lly, lry);
double maxx = std::max(urx, lrx);
double maxy = std::max(ury, uly);
box.init(minx,
miny,
maxx,
maxy);
return true;
}

View file

@ -531,14 +531,14 @@ void serialize_layer( ptree & map_node, const layer & layer, bool explicit_defau
set_attr/*<bool>*/( layer_node, "clear-label-cache", layer.clear_label_cache() );
}
if ( layer.min_zoom() )
if ( layer.minimum_scale_denominator() )
{
set_attr( layer_node, "minzoom", layer.min_zoom() );
set_attr( layer_node, "minimum_scale_denominator", layer.minimum_scale_denominator() );
}
if ( layer.max_zoom() != std::numeric_limits<double>::max() )
if ( layer.maximum_scale_denominator() != std::numeric_limits<double>::max() )
{
set_attr( layer_node, "maxzoom", layer.max_zoom() );
set_attr( layer_node, "maximum_scale_denominator", layer.maximum_scale_denominator() );
}
if ( layer.queryable() || explicit_defaults )

View file

@ -88,7 +88,6 @@ bool placement_finder::next_position()
horizontal_alignment_ = layout->horizontal_alignment();
return true;
}
MAPNIK_LOG_WARN(placement_finder) << "next_position() called while last call already returned false!\n";
return false;
}
@ -239,10 +238,9 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or
double last_cluster_angle = 999;
int current_cluster = -1;
pixel_position cluster_offset;
double angle;
double angle = 0;
rotation rot;
double last_glyph_spacing = 0.;
double last_glyph_spacing = 0.0;
for (auto const& glyph : line)
{
if (current_cluster != static_cast<int>(glyph.char_index))
@ -250,13 +248,17 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or
if (adjust)
{
if (!off_pp.move(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing)))
{
return false;
}
last_glyph_spacing = adjust_character_spacing;
}
else
{
if (!off_pp.move_to_distance(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing)))
{
return false;
}
last_glyph_spacing = glyph.format->character_spacing * scale_factor_;
}
current_cluster = glyph.char_index;
@ -274,7 +276,10 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or
last_cluster_angle = angle;
}
if (std::abs(angle) > M_PI/2) ++upside_down_glyph_count;
if (std::abs(angle) > M_PI/2)
{
++upside_down_glyph_count;
}
pixel_position pos = off_pp.current_position() + cluster_offset;
// Center the text on the line

View file

@ -318,6 +318,40 @@ placements_list const& text_symbolizer_helper::get() const
return finder_.placements();
}
class apply_line_placement_visitor
{
public:
apply_line_placement_visitor(vertex_converter_type & converter,
placement_finder_adapter<placement_finder> const & adapter)
: converter_(converter), adapter_(adapter)
{
}
bool operator()(geometry::line_string<double> const & geo) const
{
geometry::line_string_vertex_adapter<double> va(geo);
converter_.apply(va, adapter_);
return adapter_.status();
}
bool operator()(geometry::polygon<double> const & geo) const
{
geometry::polygon_vertex_adapter<double> va(geo);
converter_.apply(va, adapter_);
return adapter_.status();
}
template <typename T>
bool operator()(T const & geo) const
{
return false;
}
private:
vertex_converter_type & converter_;
placement_finder_adapter<placement_finder> const & adapter_;
};
bool text_symbolizer_helper::next_line_placement() const
{
while (!geometries_to_process_.empty())
@ -331,17 +365,11 @@ bool text_symbolizer_helper::next_line_placement() const
continue; //Reexecute size check
}
if (geo_itr_->is<base_symbolizer_helper::line_string_cref>()) // line_string
if (mapnik::util::apply_visitor(apply_line_placement_visitor(converter_, adapter_), *geo_itr_))
{
auto const& line = util::get<geometry::line_string<double> const>(*geo_itr_);
geometry::line_string_vertex_adapter<double> va(line);
converter_.apply(va, adapter_);
if (adapter_.status())
{
//Found a placement
geo_itr_ = geometries_to_process_.erase(geo_itr_);
return true;
}
//Found a placement
geo_itr_ = geometries_to_process_.erase(geo_itr_);
return true;
}
// No placement for this geometry. Keep it in geometries_to_process_ for next try.

View file

@ -224,7 +224,9 @@ void text_layout::break_line_icu(std::pair<unsigned, unsigned> && line_limits)
double wrap_at;
double string_width = line.width();
double string_height = line.line_height();
for (double i = 1.0; ((wrap_at = string_width/i)/(string_height*i)) > text_ratio_ && (string_width/i) > scaled_wrap_width; i += 1.0) ;
for (double i = 1.0;
((wrap_at = string_width/i)/(string_height*i)) > text_ratio_ && (string_width/i) > scaled_wrap_width;
i += 1.0) ;
scaled_wrap_width = wrap_at;
}
@ -243,10 +245,9 @@ void text_layout::break_line_icu(std::pair<unsigned, unsigned> && line_limits)
}
breakitr->setText(text);
double current_line_length = 0;
int last_break_position = static_cast<int>(line.first_char());
for (unsigned i=line.first_char(); i < line.last_char(); ++i)
for (unsigned i = line.first_char(); i < line.last_char(); ++i)
{
// TODO: character_spacing
std::map<unsigned, double>::const_iterator width_itr = width_map_.find(i);
@ -256,7 +257,7 @@ void text_layout::break_line_icu(std::pair<unsigned, unsigned> && line_limits)
}
if (current_line_length <= scaled_wrap_width) continue;
int break_position = wrap_before_ ? breakitr->preceding(i) : breakitr->following(i);
int break_position = wrap_before_ ? breakitr->preceding(i + 1) : breakitr->following(i);
// following() returns a break position after the last word. So DONE should only be returned
// when calling preceding.
if (break_position <= last_break_position || break_position == static_cast<int>(BreakIterator::DONE))
@ -280,15 +281,18 @@ void text_layout::break_line_icu(std::pair<unsigned, unsigned> && line_limits)
{
break_position = line.last_char();
}
bool adjust_for_space_character = break_position > 0 && text[break_position - 1] == 0x0020;
text_line new_line(last_break_position, break_position);
clear_cluster_widths(last_break_position, break_position);
text_line new_line(last_break_position, adjust_for_space_character ? break_position - 1 : break_position);
clear_cluster_widths(last_break_position, adjust_for_space_character ? break_position - 1 : break_position);
shape_text(new_line);
add_line(std::move(new_line));
last_break_position = break_position;
i = break_position - 1;
current_line_length = 0;
}
if (last_break_position == static_cast<int>(line.first_char()))
{
// No line breaks => no reshaping required
@ -365,7 +369,7 @@ void text_layout::break_line(std::pair<unsigned, unsigned> && line_limits)
}
if (current_line_length <= scaled_wrap_width) continue;
int break_position = wrap_before_ ? breaker.preceding(i) : breaker.following(i);
int break_position = wrap_before_ ? breaker.preceding(i + 1) : breaker.following(i);
if (break_position <= last_break_position || break_position == static_cast<int>(BreakIterator::DONE))
{
break_position = breaker.following(i);

@ -1 +1 @@
Subproject commit d51e1cffaf450148397dd68886edaf4936abb37d
Subproject commit 6802b27950218d7f620ffb7e73c5213aa003ea3c

@ -1 +1 @@
Subproject commit 7fd9b1954e87105c69bb0670db486147e2284ff5
Subproject commit 03407519069c6510da49b130ea03fba4fc22161c

View file

@ -11,16 +11,6 @@ function run_substep { >&2 echo -e "\033[1m\033[36m* $1\033[0m"; }
function run_success { >&2 echo -e "\033[1m\033[32m* $1\033[0m"; }
run_step "Starting Mapnik tests"
# mapnik-settings.env is an optional file to store
# environment variables that should be used before
# running tests like PROJ_LIB, GDAL_DATA, and ICU_DATA
# These do not normally need to be set except when
# building against binary versions of dependencies like
# done via bootstrap.sh
if [[ -f mapnik-settings.env ]]; then
run_substep "Inheriting from mapnik-settings.env"
source mapnik-settings.env
fi
run_substep "Running C++ Unit tests..."
./test/unit/run

View file

@ -3,9 +3,14 @@
// boost
#include <type_traits>
#include <iterator>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/zip_iterator.hpp>
#include <boost/range/iterator_range.hpp>
#pragma GCC diagnostic pop
// helper namespace to ensure correct functionality
namespace aux{

292
test/unit/imaging/image.cpp Normal file
View file

@ -0,0 +1,292 @@
#include "catch.hpp"
// mapnik
#include <mapnik/image_any.hpp>
#include <mapnik/color.hpp>
#include <mapnik/image_view_any.hpp>
#include <mapnik/image_util.hpp>
TEST_CASE("image class") {
SECTION("test gray16") {
const mapnik::image_gray16 im(4,4);
mapnik::image_gray16 im2(im);
mapnik::image_gray16 im3(5,5);
CHECK(im == im);
CHECK_FALSE(im == im2);
CHECK_FALSE(im2 == im3);
CHECK(im < im3);
CHECK_FALSE(im < im2);
// Check that width is correct
CHECK(im.width() == 4);
CHECK(im2.width() == 4);
// Check that height is correct
CHECK(im.height() == 4);
CHECK(im2.height() == 4);
CHECK(im(0,0) == 0);
CHECK(im2(0,0) == 0);
im2(0,0) = 1;
CHECK(im2(0,0) == 1);
im2.set(514);
CHECK(im2(0,0) == 514);
CHECK(im2(1,1) == 514);
// Check that size is correct
CHECK(im.size() == 32);
CHECK(im2.size() == 32);
// Check that row_size is correct
CHECK(im.row_size() == 8);
CHECK(im2.row_size() == 8);
// Check that get_premultiplied is correct
CHECK_FALSE(im.get_premultiplied());
CHECK_FALSE(im2.get_premultiplied());
// Check that set premultiplied works
im2.set_premultiplied(true);
CHECK(im2.get_premultiplied());
// Check that painted is correct
CHECK_FALSE(im.painted());
CHECK_FALSE(im2.painted());
// Check that set premultiplied works
im2.painted(true);
CHECK(im2.painted());
// Check that offset is correct
CHECK(im.get_offset() == 0.0);
CHECK(im2.get_offset() == 0.0);
// Check that set offset works
im2.set_offset(2.3);
CHECK(im2.get_offset() == 2.3);
// Check that scaling is correct
CHECK(im.get_scaling() == 1.0);
CHECK(im2.get_scaling() == 1.0);
// Check that set scaling works
im2.set_scaling(1.1);
CHECK(im2.get_scaling() == 1.1);
// CHECK that image dtype is correct
CHECK(im.get_dtype() == mapnik::image_dtype_gray16);
CHECK(im2.get_dtype() == mapnik::image_dtype_gray16);
using pixel_type = mapnik::image_view_gray16::pixel_type;
pixel_type expected_val;
// Check that all data in the view is correct
// IM
expected_val = 0;
pixel_type const* data_im = im.data();
CHECK(*data_im == expected_val);
unsigned char const* data_b = im.bytes();
CHECK(*data_b == 0);
for (std::size_t y = 0; y < im.height(); ++y)
{
std::size_t width = im.width();
pixel_type const* data_1 = im.get_row(y);
pixel_type const* data_2 = im.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// IM2
expected_val = 514;
pixel_type * data_im2 = im2.data();
CHECK(*data_im2 == expected_val);
unsigned char * data_b2 = im2.bytes();
CHECK(*data_b2 == 2);
++data_b;
CHECK(*data_b2 == 2);
for (std::size_t y = 0; y < im2.height(); ++y)
{
std::size_t width = im2.width();
pixel_type const* data_1 = im2.get_row(y);
pixel_type const* data_2 = im2.get_row(y, 1);
for (std::size_t x = 0; x < width; ++x)
{
CHECK(*data_1 == expected_val);
++data_1;
}
for (std::size_t x = 1; x < width; ++x)
{
CHECK(*data_2 == expected_val);
++data_2;
}
}
// Test set row
std::vector<pixel_type> v1(im2.width(), 30);
std::vector<pixel_type> v2(im2.width()-1, 50);
im2.set_row(0, v1.data(), v1.size());
im2.set_row(1, 1, v2.size(), v2.data());
CHECK(im2(0,0) == 30);
CHECK(im2(0,1) == 514);
CHECK(im2(1,1) == 50);
} // END SECTION
SECTION("image_null")
{
mapnik::image_null im_null;
const mapnik::image_null im_null2(2,2); // Actually doesn't really set any size
mapnik::image_null im_null3(im_null2);
mapnik::image_null im_null4(std::move(im_null3));
// All nulls are equal
CHECK(im_null == im_null4);
CHECK(im_null == im_null2);
// No null is greater
CHECK_FALSE(im_null < im_null4);
CHECK_FALSE(im_null < im_null2);
// Check defaults
CHECK(im_null.width() == 0);
CHECK(im_null.height() == 0);
CHECK(im_null.size() == 0);
CHECK(im_null.row_size() == 0);
// Setting offset does nothing
im_null.set_offset(10000000.0);
CHECK(im_null.get_offset() == 0.0);
// Setting scaling does nothing
im_null.set_scaling(123123123.0);
CHECK(im_null.get_scaling() == 1.0);
CHECK(im_null.get_dtype() == mapnik::image_dtype_null);
// Setting premultiplied does nothing
im_null.set_premultiplied(true);
CHECK_FALSE(im_null.get_premultiplied());
// Setting painted does nothing
im_null.painted(true);
CHECK_FALSE(im_null.painted());
// Should throw if we try to access or setdata.
REQUIRE_THROWS(im_null(0,0));
REQUIRE_THROWS(im_null2(0,0));
REQUIRE_THROWS(im_null(0,0) = 1);
unsigned char const* e1 = im_null.bytes();
unsigned char * e2 = im_null.bytes();
CHECK(e1 == nullptr);
CHECK(e2 == nullptr);
} // END SECTION
SECTION("image any")
{
mapnik::image_null null_im;
const mapnik::image_any im_any_null(null_im);
CHECK(im_any_null.get_dtype() == mapnik::image_dtype_null);
CHECK(im_any_null.bytes() == nullptr);
mapnik::image_gray16 im(4,4);
mapnik::fill(im, 514);
mapnik::image_any im_any(im);
CHECK(im_any.get_dtype() == mapnik::image_dtype_gray16);
unsigned char * foo = im_any.bytes();
CHECK(*foo == 2);
++foo;
CHECK(*foo == 2);
CHECK(im_any.width() == 4);
CHECK(im_any.height() == 4);
CHECK(im_any.size() == 32);
CHECK(im_any.row_size() == 8);
CHECK_FALSE(im_any.get_premultiplied());
im_any.set_offset(10.0);
CHECK(im_any.get_offset() == 10.0);
im_any.set_scaling(2.1);
CHECK(im_any.get_scaling() == 2.1);
CHECK_FALSE(im_any.painted());
} // END SECTION
SECTION("test image_any initialization")
{
{
mapnik::image_any im(4,4);
CHECK(im.get_dtype() == mapnik::image_dtype_rgba8);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_null);
CHECK(im.get_dtype() == mapnik::image_dtype_null);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray8);
CHECK(im.get_dtype() == mapnik::image_dtype_gray8);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray8s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray8s);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray16);
CHECK(im.get_dtype() == mapnik::image_dtype_gray16);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray16s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray16s);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray32);
CHECK(im.get_dtype() == mapnik::image_dtype_gray32);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray32s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray32s);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray32f);
CHECK(im.get_dtype() == mapnik::image_dtype_gray32f);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray64);
CHECK(im.get_dtype() == mapnik::image_dtype_gray64);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray64s);
CHECK(im.get_dtype() == mapnik::image_dtype_gray64s);
}
{
mapnik::image_any im(4, 4, mapnik::image_dtype_gray64f);
CHECK(im.get_dtype() == mapnik::image_dtype_gray64f);
}
} // END SECTION
SECTION("Image Buffer")
{
mapnik::detail::buffer buf_zero(0);
CHECK(buf_zero.size() == 0);
CHECK(!buf_zero);
mapnik::detail::buffer buf(10);
CHECK(buf.size() == 10);
CHECK_FALSE(!buf);
unsigned char * d = buf.data();
*d = 9;
const mapnik::detail::buffer buf2 = buf;
CHECK(buf2.size() == 10);
unsigned char const* d2 = buf2.data();
CHECK(*d2 == 9);
} // END SECTION
} // END TEST CASE

View file

@ -13,7 +13,7 @@ SECTION("test rgba8") {
mapnik::image_rgba8 im2(4,4,true,true); // Initialize as already premultiplied
mapnik::image_any im_any(mapnik::image_rgba8(4,4));
mapnik::image_any im2_any(mapnik::image_rgba8(4,4,true,true));
// Fill the images with meaningfull values
mapnik::color c1(57,70,128,128); // This color is not premultiplied
mapnik::color c2(57,70,128,128, true); // This color is premultiplied
@ -21,12 +21,12 @@ SECTION("test rgba8") {
mapnik::fill(im_any, c1); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::fill(im2, c2); // Because c1 is premultiplied it will make the image premultiplied
mapnik::fill(im2_any, c2); // Because c1 is premultiplied it will make the image premultiplied
mapnik::multiply_alpha(im, 0.75);
mapnik::multiply_alpha(im_any, 0.75);
mapnik::multiply_alpha(im2, 0.75);
mapnik::multiply_alpha(im2_any, 0.75);
mapnik::color out;
// This should have only changed the alpha, as it was not premultipleid
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
@ -54,30 +54,35 @@ SECTION("test rgba8") {
} // END SECTION
SECTION("test rgba8 overflow") {
mapnik::image_rgba8 im(4,4);
mapnik::color c(128,128,128,128); // This color is premultiplied
mapnik::fill(im, c); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::multiply_alpha(im, 2.5);
mapnik::color out;
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 128);
CHECK(static_cast<int>(out.green()) == 128);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 255);
CHECK(static_cast<int>(out.alpha()) == 128);
mapnik::multiply_alpha(im, 2.5);
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 128);
CHECK(static_cast<int>(out.green()) == 128);
CHECK(static_cast<int>(out.blue()) == 128);
CHECK(static_cast<int>(out.alpha()) == 128);
} // END SECTION
SECTION("test rgba8 underflow") {
mapnik::image_rgba8 im(4,4);
mapnik::color c(128,128,128,128); // This color is premultiplied
mapnik::fill(im, c); // Because c1 is not premultiplied it will make the image not premultiplied
mapnik::multiply_alpha(im, -2.5);
mapnik::color out;
out = mapnik::get_pixel<mapnik::color>(im, 0, 0);
CHECK(static_cast<int>(out.red()) == 128);
@ -88,13 +93,12 @@ SECTION("test rgba8 underflow") {
} // END SECTION
SECTION("test gray8") {
mapnik::image_gray8 im(4,4);
mapnik::image_any im_any(mapnik::image_gray8(4,4));
CHECK_THROWS(mapnik::multiply_alpha(im, 0.25));
CHECK_THROWS(mapnik::multiply_alpha(im_any, 0.25));
} // END SECTION
} // END TEST_CASE

View file

@ -50,6 +50,8 @@ SECTION("test rgba8") {
CHECK(view_all == view_yellow);
CHECK(view_all == view_red);
CHECK(view_all.data() == im);
// Check that view_all and view_all_2 are not the same underlying data
CHECK_FALSE(view_all == view_all_2);
CHECK(view_all < view_all_2);

View file

@ -0,0 +1,89 @@
#include "catch.hpp"
#include <mapnik/palette.hpp>
#include <fstream>
#include <sstream>
#include <string>
#include <cerrno>
std::string get_file_contents(std::string const& filename)
{
std::ifstream in(filename.c_str(), std::ios::in | std::ios::binary);
if (in)
{
std::ostringstream contents;
contents << in.rdbuf();
in.close();
return(contents.str());
}
throw(errno);
}
TEST_CASE("palette")
{
SECTION("rgb")
{
mapnik::rgb a(1,2,3);
mapnik::rgba b_(1,2,3,4);
mapnik::rgb b(b_);
mapnik::rgb c(3,4,5);
CHECK(a == b);
CHECK_FALSE(a == c);
} // END SECTION
SECTION("rgba")
{
mapnik::rgba a(1,2,3,4);
mapnik::rgba a_copy(1,2,3,4);
mapnik::rgba b(255,255,255,255);
mapnik::rgba c(4,3,2,1);
mapnik::rgb d_(1,2,3);
mapnik::rgba d(d_);
mapnik::rgba e(16909060);
CHECK(e.r == 4);
CHECK(e.g == 3);
CHECK(e.b == 2);
CHECK(e.a == 1);
CHECK(a == a_copy);
CHECK_FALSE(a == c);
CHECK(c == e);
mapnik::rgba::mean_sort_cmp msc;
CHECK_FALSE(msc(a,a_copy));
CHECK(msc(a,b));
CHECK_FALSE(msc(a,c));
CHECK(msc(a,d));
} // END SECTION
SECTION("rgba palette - exceptions and bad palettes")
{
REQUIRE_THROWS(mapnik::rgba_palette("foo"));
REQUIRE_THROWS(mapnik::rgba_palette("fooo", mapnik::rgba_palette::PALETTE_RGB));
REQUIRE_THROWS(mapnik::rgba_palette("foo", mapnik::rgba_palette::PALETTE_ACT));
} // END SECTION
SECTION("rgba palette - act pal_64")
{
std::string pal_64 = get_file_contents("./test/data/palettes/palette64.act");
mapnik::rgba_palette rgba_pal(pal_64, mapnik::rgba_palette::PALETTE_ACT);
CHECK(rgba_pal.to_string() == "[Palette 64 colors #494746 #c37631 #89827c #d1955c #7397b9 #fc9237 #a09f9c #fbc147 #9bb3ce #b7c9a1 #b5d29c #c4b9aa #cdc4a5 #d5c8a3 #c1d7aa #ccc4b6 #dbd19c #b2c4d5 #eae487 #c9c8c6 #e4db99 #c9dcb5 #dfd3ac #cbd2c2 #d6cdbc #dbd2b6 #c0ceda #ece597 #f7ef86 #d7d3c3 #dfcbc3 #d1d0cd #d1e2bf #d3dec1 #dbd3c4 #e6d8b6 #f4ef91 #d3d3cf #cad5de #ded7c9 #dfdbce #fcf993 #ffff8a #dbd9d7 #dbe7cd #d4dce2 #e4ded3 #ebe3c9 #e0e2e2 #f4edc3 #fdfcae #e9e5dc #f4edda #eeebe4 #fefdc5 #e7edf2 #edf4e5 #f2efe9 #f6ede7 #fefedd #f6f4f0 #f1f5f8 #fbfaf8 #ffffff]");
} // END SECTION
SECTION("rgba palette - act pal_256")
{
std::string pal_ = get_file_contents("./test/data/palettes/palette256.act");
mapnik::rgba_palette rgba_pal(pal_, mapnik::rgba_palette::PALETTE_ACT);
CHECK(rgba_pal.to_string() == "[Palette 256 colors #272727 #3c3c3c #484847 #564b41 #605243 #6a523e #555555 #785941 #5d5d5d #746856 #676767 #956740 #ba712e #787777 #cb752a #c27c3d #b68049 #dc8030 #df9e10 #878685 #e1a214 #928b82 #a88a70 #ea8834 #e7a81d #cb8d55 #909090 #94938c #e18f48 #f68d36 #6f94b7 #e1ab2e #8e959b #c79666 #999897 #ff9238 #ef9447 #a99a88 #f1b32c #919ca6 #a1a09f #f0b04b #8aa4bf #f8bc39 #b3ac8f #d1a67a #e3b857 #a8a8a7 #ffc345 #a2adb9 #afaeab #f9ab69 #afbba4 #c4c48a #b4b2af #dec177 #9ab2cf #a3bebb #d7b491 #b6cd9e #b5d29c #b9c8a2 #f1c969 #c5c79e #bbbab9 #cabdaa #a6bcd1 #cec4a7 #e7cc89 #dad98a #d5c9a3 #fabd8a #c1d7aa #cec5b4 #d1d1a5 #d9cf9f #c5c4c3 #d3c7b5 #ddd59d #b4c6d6 #d1cbb4 #d1c7ba #d7d1aa #e1c6ab #cbc7c2 #dbd0a9 #e8e58a #fee178 #d3cbba #dfd7a3 #d2cfb9 #c9ddb5 #d2cbbe #c3cbce #d7cbba #dcceb2 #dfd3aa #e5dd9a #dbd3b1 #ceccc6 #d7cbbe #d7cfba #dfc3be #dfd3ae #cbcbcb #cbd3c3 #d3cfc0 #e0d8aa #d7cfbe #dbd3b8 #ebe596 #dfd8b0 #c0ceda #f1ee89 #decfbc #d7cfc4 #d7d3c3 #d1d0cd #d2dfc0 #dbd3c3 #e7c7c3 #e7d7b3 #f2ed92 #d1e2bf #dad7c3 #fef383 #d3d3cf #dbd3c7 #e0d3c2 #dfd7c0 #ebe4a8 #dbd7c7 #dfd3c7 #f7f38f #c9d4de #dcdcc5 #dfd7c7 #e7d5c2 #d6d5d4 #faf78e #d7dfca #fbfb8a #fffb86 #dfd7cb #e5ddc0 #dad7d2 #ecd6c1 #cfd7de #e8d0cc #fbfb8e #fffb8a #eae3b8 #e3d7cd #dfdbce #fffb8e #ffff8a #f5efa6 #dae6cc #e3dbcf #edddc3 #dddbd6 #d5dbdf #ffff91 #e3dbd3 #fefc99 #e7dbd2 #eaddcd #e3dfd3 #ebd7d3 #dddddd #d4dee6 #e2dfd7 #fcdcc0 #e7dbd7 #e7dfd3 #ebe4cb #f4eeb8 #e3dfdb #e7dfd7 #ebded5 #e7e3d7 #fefea6 #e1ecd6 #ece5d3 #e7e3db #dee3e5 #ebe3db #efdfdb #efe3d8 #f4efc9 #e6ecdb #ebe3df #ebe7db #f0ecd3 #e5e6e5 #efe7da #ebe7df #efe3df #fefeb8 #dfe7ef #ebe7e3 #edebde #efe7e0 #e8efe0 #e7f3df #ebebe3 #e7ebe8 #f5edd9 #efebe3 #e3ebf1 #e9efe7 #ebebea #efebe7 #f0efe2 #ecf3e5 #fefdc9 #efefe7 #f3efe7 #f5f3e1 #f2efe9 #e9eef4 #ffeddf #efefef #f3efeb #f3f3eb #f0f7eb #fbf7e1 #fefed8 #f3f3ef #f7f3eb #eef3f7 #f7f7ea #f3f3f3 #f3f7ef #f7f3ef #f3f3f7 #f7f3f3 #f7f7ef #fffee3 #f3f7f7 #f7f7f3 #fcf7ee #f7f7f7 #f7fbf4 #f5f7fb #fbf7f6 #fffeef #f7fbfb #fbfbf7 #fbfbfb #fbfbff #fbfffb #fffbfb #fbffff #fffffb #ffffff]");
} // END SECTION
} // END TEST CASE

View file

@ -0,0 +1,38 @@
#include "catch.hpp"
#include <mapnik/projection.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/box2d.hpp>
TEST_CASE("projection transform")
{
SECTION("Test bounding box transforms - 4326 to 3857")
{
mapnik::projection proj_4326("+init=epsg:4326");
mapnik::projection proj_3857("+init=epsg:3857");
mapnik::proj_transform prj_trans(proj_4326, proj_3857);
double minx = -45.0;
double miny = 55.0;
double maxx = -40.0;
double maxy = 75.0;
mapnik::box2d<double> bbox(minx, miny, maxx, maxy);
prj_trans.forward(bbox);
INFO(bbox.to_string());
CHECK(bbox.minx() == Approx(-5009377.085697311));
CHECK(bbox.miny() == Approx(7361866.1130511891));
CHECK(bbox.maxx() == Approx(-4452779.631730943));
CHECK(bbox.maxy() == Approx(12932243.1119920239));
prj_trans.backward(bbox);
CHECK(bbox.minx() == Approx(minx));
CHECK(bbox.miny() == Approx(miny));
CHECK(bbox.maxx() == Approx(maxx));
CHECK(bbox.maxy() == Approx(maxy));
} // END SECTION
} // END TEST CASE

View file

@ -31,6 +31,7 @@
// mapnik
#include <mapnik/map.hpp>
#include <mapnik/util/fs.hpp>
#include <mapnik/agg_renderer.hpp>
#if defined(HAVE_CAIRO)
#include <mapnik/cairo/cairo_renderer.hpp>
@ -117,15 +118,16 @@ public:
{
typename Renderer::image_type image(ren.render(map, scale_factor));
boost::filesystem::path reference = reference_dir / image_file_name(name, map.width(), map.height(), scale_factor, true);
bool reference_exists = mapnik::util::exists(reference.string());
result res;
res.state = STATE_OK;
res.state = reference_exists ? STATE_OK : STATE_OVERWRITE;
res.name = name;
res.renderer_name = Renderer::name;
res.scale_factor = scale_factor;
res.size = map_size(map.width(), map.height());
res.reference_image_path = reference;
res.diff = ren.compare(image, reference);
res.diff = reference_exists ? ren.compare(image, reference) : 0;
if (res.diff)
{
@ -134,12 +136,12 @@ public:
res.actual_image_path = path;
res.state = STATE_FAIL;
ren.save(image, path);
}
if (overwrite)
{
ren.save(image, reference);
res.state = STATE_OVERWRITE;
}
if ((res.diff && overwrite) || !reference_exists)
{
ren.save(image, reference);
res.state = STATE_OVERWRITE;
}
return res;

View file

@ -11,7 +11,6 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#pragma GCC diagnostic pop
@ -135,7 +134,7 @@ int main (int argc,char** argv)
vars[name] = tr.transcode(param.second.get<std::string>().c_str());
}
}
}
}
}
mapnik::agg_renderer<mapnik::image_rgba8> ren(map,req,vars,im,scale_factor,0,0);
ren.apply();

View file

@ -25,7 +25,6 @@
#include <vector>
#include <string>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>

View file

@ -32,7 +32,6 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-local-typedef"
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#pragma GCC diagnostic pop