featureset_ptr gdal_datasource::features(query const& q) const { if (! is_bound_) bind(); gdal_query gq = q; // TODO - move to boost::make_shared, but must reduce # of args to <= 9 return featureset_ptr(new gdal_featureset(*open_dataset(), band_, gq, extent_, width_, height_, nbands_, dx_, dy_, filter_factor_)); }
/* * Opens a GDALDataset and returns a pointer to it. * Caller is responsible for calling GDALClose on it */ inline GDALDataset *gdal_datasource::open_dataset() const { #ifdef MAPNIK_DEBUG std::clog << "GDAL Plugin: opening: " << dataset_name_ << std::endl; #endif GDALDataset *dataset; #if GDAL_VERSION_NUM >= 1600 if (shared_dataset_) dataset = reinterpret_cast<GDALDataset*>(GDALOpenShared((dataset_name_).c_str(),GA_ReadOnly)); else #endif dataset = reinterpret_cast<GDALDataset*>(GDALOpen((dataset_name_).c_str(),GA_ReadOnly)); if (! dataset) throw datasource_exception(CPLGetLastErrorMsg()); return dataset; }
feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt) { if (band_ > 0) { unsigned raster_xsize = dataset_.GetRasterXSize(); unsigned raster_ysize = dataset_.GetRasterYSize(); double gt[6]; dataset_.GetGeoTransform(gt); double det = gt[1] * gt[5] - gt[2] * gt[4]; // subtract half a pixel width & height because gdal coord reference // is the top-left corner of a pixel, not the center. double X = pt.x - gt[0] - gt[1]/2; double Y = pt.y - gt[3] - gt[5]/2; double det1 = gt[1]*Y + gt[4]*X; double det2 = gt[2]*Y + gt[5]*X; unsigned x = det2/det, y = det1/det; if (x < raster_xsize && y < raster_ysize) { MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: pt.x=" << pt.x << " pt.y=" << pt.y; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: x=" << x << " y=" << y; GDALRasterBand* band = dataset_.GetRasterBand(band_); int hasNoData; double nodata = band->GetNoDataValue(&hasNoData); double value; band->RasterIO(GF_Read, x, y, 1, 1, &value, 1, 1, GDT_Float64, 0, 0); if (! hasNoData || value != nodata) { // construct feature feature_ptr feature = feature_factory::create(ctx_,1); geometry_type * point = new geometry_type(mapnik::Point); point->move_to(pt.x, pt.y); feature->add_geometry(point); feature->put("value",value); return feature; } } } return feature_ptr(); }
feature_ptr rasterlite_featureset::next() { if (first_) { first_ = false; query *q = boost::get<query>(&gquery_); if(q) { return get_feature(*q); } else { coord2d *p = boost::get<coord2d>(&gquery_); if(p) { return get_feature_at_point(*p); } } // should never reach here } return feature_ptr(); }
featureset_ptr geos_datasource::features_at_point(coord2d const& pt) const { if (!is_bound_) bind(); std::ostringstream s; s << "POINT(" << pt.x << " " << pt.y << ")"; #ifdef MAPNIK_DEBUG clog << "GEOS Plugin: using point: " << s.str() << endl; #endif return featureset_ptr(new geos_featureset (*geometry_, GEOSGeomFromWKT(s.str().c_str()), geometry_id_, geometry_data_, geometry_data_name_, desc_.get_encoding(), multiple_geometries_)); }
kismet_datasource::kismet_datasource(parameters const& params, bool bind) : datasource(params), extent_(), extent_initialized_(false), type_(datasource::Vector), srs_("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"), desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8")) { boost::optional<std::string> host = params_.get<std::string>("host"); if (host) { host_ = *host; } else { throw datasource_exception("Kismet Plugin: missing <host> parameter"); } boost::optional<unsigned int> port = params_.get<unsigned int>("port", 2501); if (port) { port_ = *port; } boost::optional<std::string> srs = params_.get<std::string>("srs"); if (srs) { srs_ = *srs; } boost::optional<std::string> ext = params_.get<std::string>("extent"); if (ext) { extent_initialized_ = extent_.from_string(*ext); } kismet_thread.reset(new boost::thread(boost::bind(&kismet_datasource::run, this, host_, port_))); if (bind) { this->bind(); } }
sqlite_datasource::sqlite_datasource(parameters const& params, bool bind) : datasource(params), extent_(), extent_initialized_(false), type_(datasource::Vector), table_(*params.get<std::string>("table","")), fields_(*params.get<std::string>("fields","*")), metadata_(*params.get<std::string>("metadata","")), geometry_field_(*params.get<std::string>("geometry_field","the_geom")), key_field_(*params.get<std::string>("key_field","OGC_FID")), row_offset_(*params_.get<int>("row_offset",0)), row_limit_(*params_.get<int>("row_limit",0)), desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8")), format_(mapnik::wkbGeneric) { boost::optional<std::string> file = params.get<std::string>("file"); if (!file) throw datasource_exception("Sqlite Plugin: missing <file> parameter"); boost::optional<std::string> wkb = params.get<std::string>("wkb_format"); if (wkb) { if (*wkb == "spatialite") format_ = mapnik::wkbSpatiaLite; } multiple_geometries_ = *params_.get<mapnik::boolean>("multiple_geometries",false); use_spatial_index_ = *params_.get<mapnik::boolean>("use_spatial_index",true); boost::optional<std::string> ext = params_.get<std::string>("extent"); if (ext) extent_initialized_ = extent_.from_string(*ext); boost::optional<std::string> base = params.get<std::string>("base"); if (base) dataset_name_ = *base + "/" + *file; else dataset_name_ = *file; if (bind) { this->bind(); } }
featureset_ptr gdal_datasource::features_at_point(coord2d const& pt, double tol) const { #ifdef MAPNIK_STATS mapnik::progress_timer __stats__(std::clog, "gdal_datasource::features_at_point"); #endif gdal_query gq = pt; // TODO - move to std::make_shared, but must reduce # of args to <= 9 return featureset_ptr(new gdal_featureset(*open_dataset(), band_, gq, extent_, width_, height_, nbands_, dx_, dy_, nodata_value_, nodata_tolerance_)); }
feature_ptr gdal_featureset::next() { if (first_) { first_ = false; #ifdef MAPNIK_DEBUG std::clog << "GDAL Plugin: featureset, dataset = " << &dataset_ << std::endl; #endif query *q = boost::get<query>(&gquery_); if(q) { return get_feature(*q); } else { coord2d *p = boost::get<coord2d>(&gquery_); if(p) { return get_feature_at_point(*p); } } // should never reach here } return feature_ptr(); }
ogr_datasource::ogr_datasource(parameters const& params, bool bind) : datasource(params), extent_(), type_(datasource::Vector), desc_(*params_.get<std::string>("type"), *params_.get<std::string>("encoding", "utf-8")), indexed_(false) { boost::optional<std::string> file = params.get<std::string>("file"); boost::optional<std::string> string = params.get<std::string>("string"); if (! file && ! string) { throw datasource_exception("missing <file> or <string> parameter"); } multiple_geometries_ = *params.get<mapnik::boolean>("multiple_geometries", false); if (string) { dataset_name_ = *string; } else { boost::optional<std::string> base = params.get<std::string>("base"); if (base) { dataset_name_ = *base + "/" + *file; } else { dataset_name_ = *file; } } if (bind) { this->bind(); } }
shape_datasource::shape_datasource(const parameters ¶ms, bool bind) : datasource (params), type_(datasource::Vector), file_length_(0), indexed_(false), desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8")) { boost::optional<std::string> file = params.get<std::string>("file"); if (!file) throw datasource_exception("Shape Plugin: missing <file> parameter"); boost::optional<std::string> base = params.get<std::string>("base"); if (base) shape_name_ = *base + "/" + *file; else shape_name_ = *file; boost::algorithm::ireplace_last(shape_name_,".shp",""); if (bind) { this->bind(); } }
/* * Opens a GDALDataset and returns a pointer to it. * Caller is responsible for calling GDALClose on it */ inline GDALDataset* gdal_datasource::open_dataset() const { MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource: Opening " << dataset_name_; GDALDataset *dataset; #if GDAL_VERSION_NUM >= 1600 if (shared_dataset_) { dataset = reinterpret_cast<GDALDataset*>(GDALOpenShared((dataset_name_).c_str(), GA_ReadOnly)); } else #endif { dataset = reinterpret_cast<GDALDataset*>(GDALOpen((dataset_name_).c_str(), GA_ReadOnly)); } if (! dataset) { throw datasource_exception(CPLGetLastErrorMsg()); } return dataset; }
feature_ptr kismet_featureset::next() { if (knd_list_it != knd_list_.end ()) { const kismet_network_data& knd = *knd_list_it; const std::string key = "internet_access"; std::string value; if (knd.crypt_ == crypt_none) { value = "wlan_uncrypted"; } else if (knd.crypt_ == crypt_wep) { value = "wlan_wep"; } else { value = "wlan_crypted"; } feature_ptr feature(feature_factory::create(feature_id_)); ++feature_id_; geometry_type* pt = new geometry_type(mapnik::Point); pt->move_to(knd.bestlon_, knd.bestlat_); feature->add_geometry(pt); boost::put(*feature, key, tr_->transcode(value.c_str())); ++knd_list_it; return feature; } return feature_ptr(); }
void sqlite_datasource::bind() const { if (is_bound_) return; if (!boost::filesystem::exists(dataset_name_)) throw datasource_exception("Sqlite Plugin: " + dataset_name_ + " does not exist"); dataset_ = new sqlite_connection (dataset_name_); if(geometry_table_.empty()) { geometry_table_ = mapnik::table_from_sql(table_); } // should we deduce column names and types using PRAGMA? bool use_pragma_table_info = true; if (table_ != geometry_table_) { // if 'table_' is a subquery then we try to deduce names // and types from the first row returned from that query use_pragma_table_info = false; } if (!use_pragma_table_info) { std::ostringstream s; s << "SELECT " << fields_ << " FROM (" << table_ << ") LIMIT 1"; boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str())); if (rs->is_valid () && rs->step_next()) { for (int i = 0; i < rs->column_count (); ++i) { const int type_oid = rs->column_type (i); const char* fld_name = rs->column_name (i); switch (type_oid) { case SQLITE_INTEGER: desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer)); break; case SQLITE_FLOAT: desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double)); break; case SQLITE_TEXT: desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String)); break; case SQLITE_NULL: // sqlite reports based on value, not actual column type unless // PRAGMA table_info is used so here we assume the column is a string // which is a lesser evil than altogether dropping the column desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String)); case SQLITE_BLOB: if (geometry_field_.empty() && (boost::algorithm::icontains(fld_name,"geom") || boost::algorithm::icontains(fld_name,"point") || boost::algorithm::icontains(fld_name,"linestring") || boost::algorithm::icontains(fld_name,"polygon")) ) geometry_field_ = std::string(fld_name); break; default: #ifdef MAPNIK_DEBUG std::clog << "Sqlite Plugin: unknown type_oid=" << type_oid << std::endl; #endif break; } } } else { // if we do not have at least a row and // we cannot determine the right columns types and names // as all column_type are SQLITE_NULL // so we fallback to using PRAGMA table_info use_pragma_table_info = true; } } // TODO - ensure that the supplied key_field is a valid "integer primary key" desc_.add_descriptor(attribute_descriptor("rowid",mapnik::Integer)); if (use_pragma_table_info) { std::ostringstream s; s << "PRAGMA table_info(" << geometry_table_ << ")"; boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str())); bool found_table = false; while (rs->is_valid () && rs->step_next()) { found_table = true; const char* fld_name = rs->column_text(1); std::string fld_type(rs->column_text(2)); boost::algorithm::to_lower(fld_type); // see 2.1 "Column Affinity" at http://www.sqlite.org/datatype3.html if (geometry_field_.empty() && ( (boost::algorithm::icontains(fld_name,"geom") || boost::algorithm::icontains(fld_name,"point") || boost::algorithm::icontains(fld_name,"linestring") || boost::algorithm::icontains(fld_name,"polygon")) || (boost::algorithm::contains(fld_type,"geom") || boost::algorithm::contains(fld_type,"point") || boost::algorithm::contains(fld_type,"linestring") || boost::algorithm::contains(fld_type,"polygon")) ) ) geometry_field_ = std::string(fld_name); else if (boost::algorithm::contains(fld_type,"int")) { desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer)); } else if (boost::algorithm::contains(fld_type,"text") || boost::algorithm::contains(fld_type,"char") || boost::algorithm::contains(fld_type,"clob")) { desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String)); } else if (boost::algorithm::contains(fld_type,"real") || boost::algorithm::contains(fld_type,"float") || boost::algorithm::contains(fld_type,"double")) { desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double)); } else if (boost::algorithm::contains(fld_type,"blob") && !geometry_field_.empty()) desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String)); #ifdef MAPNIK_DEBUG else { // "Column Affinity" says default to "Numeric" but for now we pass.. //desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double)); std::clog << "Sqlite Plugin: column '" << std::string(fld_name) << "' unhandled due to unknown type: " << fld_type << std::endl; } #endif } if (!found_table) { throw datasource_exception("Sqlite Plugin: could not query table '" + geometry_table_ + "' using pragma table_info(" + geometry_table_ + ");"); } } if (geometry_field_.empty()) { throw datasource_exception("Sqlite Plugin: cannot detect geometry_field, please supply the name of the geometry_field to use."); } if (use_spatial_index_) { std::ostringstream s; s << "SELECT COUNT (*) FROM sqlite_master"; s << " WHERE LOWER(name) = LOWER('idx_" << geometry_table_ << "_" << geometry_field_ << "')"; boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str())); if (rs->is_valid () && rs->step_next()) { use_spatial_index_ = rs->column_integer (0) == 1; } if (!use_spatial_index_) std::clog << "Sqlite Plugin: spatial index not found for table '" << geometry_table_ << "'" << std::endl; } if (metadata_ != "" && !extent_initialized_) { std::ostringstream s; s << "SELECT xmin, ymin, xmax, ymax FROM " << metadata_; s << " WHERE LOWER(f_table_name) = LOWER('" << geometry_table_ << "')"; boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str())); if (rs->is_valid () && rs->step_next()) { double xmin = rs->column_double (0); double ymin = rs->column_double (1); double xmax = rs->column_double (2); double ymax = rs->column_double (3); extent_.init (xmin,ymin,xmax,ymax); extent_initialized_ = true; } } if (!extent_initialized_ && use_spatial_index_) { std::ostringstream s; s << "SELECT MIN(xmin), MIN(ymin), MAX(xmax), MAX(ymax) FROM " << "idx_" << geometry_table_ << "_" << geometry_field_; boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str())); if (rs->is_valid () && rs->step_next()) { double xmin = rs->column_double (0); double ymin = rs->column_double (1); double xmax = rs->column_double (2); double ymax = rs->column_double (3); extent_.init (xmin,ymin,xmax,ymax); extent_initialized_ = true; } } if (!extent_initialized_) { std::ostringstream s; s << "Sqlite Plugin: extent could not be determined for table|geometry '" << geometry_table_ << "|" << geometry_field_ << "'" << " because an rtree spatial index is missing." << " - either set the table 'extent' or create an rtree spatial index"; throw datasource_exception(s.str()); } is_bound_ = true; }
raster_datasource::raster_datasource(parameters const& params) : datasource(params), desc_(*params.get<std::string>("type"), "utf-8"), extent_initialized_(false) { MAPNIK_LOG_DEBUG(raster) << "raster_datasource: Initializing..."; boost::optional<std::string> file = params.get<std::string>("file"); if (! file) throw datasource_exception("Raster Plugin: missing <file> parameter "); boost::optional<std::string> base = params.get<std::string>("base"); if (base) filename_ = *base + "/" + *file; else filename_ = *file; multi_tiles_ = *params.get<mapnik::boolean>("multi", false); tile_size_ = *params.get<int>("tile_size", 256); tile_stride_ = *params.get<int>("tile_stride", 1); boost::optional<std::string> format_from_filename = mapnik::type_from_filename(*file); format_ = *params.get<std::string>("format",format_from_filename?(*format_from_filename) : "tiff"); boost::optional<double> lox = params.get<double>("lox"); boost::optional<double> loy = params.get<double>("loy"); boost::optional<double> hix = params.get<double>("hix"); boost::optional<double> hiy = params.get<double>("hiy"); boost::optional<std::string> ext = params.get<std::string>("extent"); if (lox && loy && hix && hiy) { extent_.init(*lox, *loy, *hix, *hiy); extent_initialized_ = true; } else if (ext) { extent_initialized_ = extent_.from_string(*ext); } if (! extent_initialized_) { throw datasource_exception("Raster Plugin: valid <extent> or <lox> <loy> <hix> <hiy> are required"); } if (multi_tiles_) { boost::optional<int> x_width = params.get<int>("x_width"); boost::optional<int> y_width = params.get<int>("y_width"); if (! x_width) { throw datasource_exception("Raster Plugin: x-width parameter not supplied for multi-tiled data source."); } if (! y_width) { throw datasource_exception("Raster Plugin: y-width parameter not supplied for multi-tiled data source."); } width_ = x_width.get() * tile_size_; height_ = y_width.get() * tile_size_; } else { if (!mapnik::util::exists(filename_)) { throw datasource_exception("Raster Plugin: " + filename_ + " does not exist"); } try { std::auto_ptr<image_reader> reader(mapnik::get_image_reader(filename_, format_)); if (reader.get()) { width_ = reader->width(); height_ = reader->height(); } } catch (mapnik::image_reader_exception const& ex) { throw datasource_exception("Raster Plugin: image reader exception: " + std::string(ex.what())); } catch (std::exception const& ex) { throw datasource_exception("Raster Plugin: " + std::string(ex.what())); } catch (...) { throw datasource_exception("Raster Plugin: image reader unknown exception caught"); } } MAPNIK_LOG_DEBUG(raster) << "raster_datasource: Raster size=" << width_ << "," << height_; }
featureset_ptr raster_datasource::features_at_point(coord2d const&, double tol) const { MAPNIK_LOG_WARN(raster) << "raster_datasource: feature_at_point not supported"; return featureset_ptr(); }
void gdal_datasource::bind() const { if (is_bound_) return; shared_dataset_ = *params_.get<mapnik::boolean>("shared", false); band_ = *params_.get<int>("band", -1); GDALDataset *dataset = open_dataset(); nbands_ = dataset->GetRasterCount(); width_ = dataset->GetRasterXSize(); height_ = dataset->GetRasterYSize(); double tr[6]; bool bbox_override = false; boost::optional<std::string> bbox_s = params_.get<std::string>("bbox"); if (bbox_s) { #ifdef MAPNIK_DEBUG std::clog << "GDAL Plugin: bbox parameter=" << *bbox_s << std::endl; #endif bbox_override = extent_.from_string(*bbox_s); if (! bbox_override) { throw datasource_exception("GDAL Plugin: bbox parameter '" + *bbox_s + "' invalid"); } } if (bbox_override) { tr[0] = extent_.minx(); tr[1] = extent_.width() / (double)width_; tr[2] = 0; tr[3] = extent_.maxy(); tr[4] = 0; tr[5] = -extent_.height() / (double)height_; } else { dataset->GetGeoTransform(tr); } #ifdef MAPNIK_DEBUG std::clog << "GDAL Plugin: geotransform=" << tr[0] << "," << tr[1] << "," << tr[2] << "," << tr[3] << "," << tr[4] << "," << tr[5] << std::endl; #endif // TODO - We should throw for true non-north up images, but the check // below is clearly too restrictive. // https://github.com/mapnik/mapnik/issues/970 /* if (tr[2] != 0 || tr[4] != 0) { throw datasource_exception("GDAL Plugin: only 'north up' images are supported"); } */ dx_ = tr[1]; dy_ = tr[5]; if (! bbox_override) { double x0 = tr[0]; double y0 = tr[3]; double x1 = tr[0] + width_ * dx_ + height_ *tr[2]; double y1 = tr[3] + width_ *tr[4] + height_ * dy_; /* double x0 = tr[0] + (height_) * tr[2]; // minx double y0 = tr[3] + (height_) * tr[5]; // miny double x1 = tr[0] + (width_) * tr[1]; // maxx double y1 = tr[3] + (width_) * tr[4]; // maxy */ extent_.init(x0, y0, x1, y1); } GDALClose(dataset); #ifdef MAPNIK_DEBUG std::clog << "GDAL Plugin: Raster Size=" << width_ << "," << height_ << std::endl; std::clog << "GDAL Plugin: Raster Extent=" << extent_ << std::endl; #endif is_bound_ = true; }
feature_ptr sqlite_featureset::next() { while (rs_->is_valid () && rs_->step_next ()) { int size; const char* data = (const char*) rs_->column_blob(0, size); if (data == 0) { return feature_ptr(); } // null feature id is not acceptable if (rs_->column_type(1) == SQLITE_NULL) { MAPNIK_LOG_ERROR(postgis) << "sqlite_featureset: null value encountered for key_field"; continue; } feature_ptr feature = feature_factory::create(ctx_,rs_->column_integer64(1)); if (!geometry_utils::from_wkb(feature->paths(), data, size, format_)) continue; if (!spatial_index_) { // we are not using r-tree index, check if feature intersects bounding box if (!bbox_.intersects(feature->envelope())) continue; } for (int i = 2; i < rs_->column_count(); ++i) { const int type_oid = rs_->column_type(i); const char* fld_name = rs_->column_name(i); if (! fld_name) continue; std::string fld_name_str(fld_name); // subqueries in sqlite lead to field double quoting which we need to strip if (using_subquery_) { sqlite_utils::dequote(fld_name_str); } switch (type_oid) { case SQLITE_INTEGER: { feature->put<mapnik::value_integer>(fld_name_str, rs_->column_integer64(i)); break; } case SQLITE_FLOAT: { feature->put(fld_name_str, rs_->column_double(i)); break; } case SQLITE_TEXT: { int text_col_size; const char * text_data = rs_->column_text(i, text_col_size); feature->put(fld_name_str, tr_->transcode(text_data, text_col_size)); break; } case SQLITE_NULL: { // NOTE: we intentionally do not store null here // since it is equivalent to the attribute not existing break; } case SQLITE_BLOB: break; default: MAPNIK_LOG_WARN(sqlite) << "sqlite_featureset: Field=" << fld_name_str << " unhandled type_oid=" << type_oid; break; } } return feature; } return feature_ptr(); }
feature_ptr osm_featureset<filterT>::next() { feature_ptr feature; osm_item* cur_item = dataset_->next_item(); if (!cur_item) return feature_ptr(); if (dataset_->current_item_is_node()) { feature = feature_factory::create(ctx_, cur_item->id); double lat = static_cast<osm_node*>(cur_item)->lat; double lon = static_cast<osm_node*>(cur_item)->lon; geometry_type* point = new geometry_type(mapnik::Point); point->move_to(lon, lat); feature->add_geometry(point); } else if (dataset_->current_item_is_way()) { // Loop until we find a feature which passes the filter while (cur_item) { bounds b = static_cast<osm_way*>(cur_item)->get_bounds(); if (filter_.pass(box2d<double>(b.w, b.s, b.e, b.n)) && static_cast<osm_way*>(cur_item)->nodes.size()) break; cur_item = dataset_->next_item(); } if (!cur_item) return feature_ptr(); feature = feature_factory::create(ctx_, cur_item->id); geometry_type* geom; if (static_cast<osm_way*>(cur_item)->is_polygon()) { geom = new geometry_type(mapnik::Polygon); } else { geom = new geometry_type(mapnik::LineString); } geom->move_to(static_cast<osm_way*>(cur_item)->nodes[0]->lon, static_cast<osm_way*>(cur_item)->nodes[0]->lat); for (unsigned int count = 1; count < static_cast<osm_way*>(cur_item)->nodes.size(); count++) { geom->line_to(static_cast<osm_way*>(cur_item)->nodes[count]->lon, static_cast<osm_way*>(cur_item)->nodes[count]->lat); } feature->add_geometry(geom); } else { MAPNIK_LOG_ERROR(osm_featureset) << "Current item is neither node nor way.\n"; } std::set<std::string>::const_iterator itr = attribute_names_.begin(); std::set<std::string>::const_iterator end = attribute_names_.end(); std::map<std::string,std::string>::iterator end_keyvals = cur_item->keyvals.end(); for (; itr != end; itr++) { std::map<std::string,std::string>::iterator i = cur_item->keyvals.find(*itr); if (i != end_keyvals) { feature->put_new(i->first, tr_->transcode(i->second.c_str())); } } return feature; }
feature_ptr rasterlite_featureset::get_feature_at_point(mapnik::coord2d const& pt) { return feature_ptr(); }
void save_to_file3(mapnik::image_32 const& im, std::string const& filename, std::string const& type, mapnik::rgba_palette const& pal) { save_to_file(im,filename,type,pal); }
feature_ptr raster_featureset<LookupPolicy>::next() { if (curIter_ != endIter_) { feature_ptr feature(feature_factory::create(ctx_,feature_id_++)); try { std::auto_ptr<image_reader> reader(mapnik::get_image_reader(curIter_->file(),curIter_->format())); MAPNIK_LOG_DEBUG(raster) << "raster_featureset: Reader=" << curIter_->format() << "," << curIter_->file() << ",size(" << curIter_->width() << "," << curIter_->height() << ")"; if (reader.get()) { int image_width = policy_.img_width(reader->width()); int image_height = policy_.img_height(reader->height()); if (image_width > 0 && image_height > 0) { mapnik::CoordTransform t(image_width, image_height, extent_, 0, 0); box2d<double> intersect = bbox_.intersect(curIter_->envelope()); box2d<double> ext = t.forward(intersect); box2d<double> rem = policy_.transform(ext); if (ext.width() > 0.5 && ext.height() > 0.5 ) { // select minimum raster containing whole ext int x_off = static_cast<int>(std::floor(ext.minx())); int y_off = static_cast<int>(std::floor(ext.miny())); int end_x = static_cast<int>(std::ceil(ext.maxx())); int end_y = static_cast<int>(std::ceil(ext.maxy())); // clip to available data if (x_off < 0) x_off = 0; if (y_off < 0) y_off = 0; if (end_x > image_width) end_x = image_width; if (end_y > image_height) end_y = image_height; int width = end_x - x_off; int height = end_y - y_off; // calculate actual box2d of returned raster box2d<double> feature_raster_extent(rem.minx() + x_off, rem.miny() + y_off, rem.maxx() + x_off + width, rem.maxy() + y_off + height); intersect = t.backward(feature_raster_extent); mapnik::raster_ptr raster = boost::make_shared<mapnik::raster>(intersect, width, height); reader->read(x_off, y_off, raster->data_); raster->premultiplied_alpha_ = reader->premultiplied_alpha(); feature->set_raster(raster); } } } } catch (mapnik::image_reader_exception const& ex) { MAPNIK_LOG_ERROR(raster) << "Raster Plugin: image reader exception caught: " << ex.what(); } catch (std::exception const& ex) { MAPNIK_LOG_ERROR(raster) << "Raster Plugin: " << ex.what(); } catch (...) { MAPNIK_LOG_ERROR(raster) << "Raster Plugin: exception caught"; } ++curIter_; return feature; } return feature_ptr(); }
shape_datasource::shape_datasource(parameters const& params) : datasource (params), type_(datasource::Vector), file_length_(0), indexed_(false), row_limit_(*params.get<mapnik::value_integer>("row_limit",0)), desc_(shape_datasource::name(), *params.get<std::string>("encoding","utf-8")) { #ifdef MAPNIK_STATS mapnik::progress_timer __stats__(std::clog, "shape_datasource::init"); #endif boost::optional<std::string> file = params.get<std::string>("file"); if (!file) throw datasource_exception("Shape Plugin: missing <file> parameter"); boost::optional<std::string> base = params.get<std::string>("base"); if (base) shape_name_ = *base + "/" + *file; else shape_name_ = *file; boost::algorithm::ireplace_last(shape_name_,".shp",""); if (!mapnik::util::exists(shape_name_ + ".shp")) { throw datasource_exception("Shape Plugin: shapefile '" + shape_name_ + ".shp' does not exist"); } if (mapnik::util::is_directory(shape_name_ + ".shp")) { throw datasource_exception("Shape Plugin: shapefile '" + shape_name_ + ".shp' appears to be a directory not a file"); } if (!mapnik::util::exists(shape_name_ + ".dbf")) { throw datasource_exception("Shape Plugin: shapefile '" + shape_name_ + ".dbf' does not exist"); } try { #ifdef MAPNIK_STATS mapnik::progress_timer __stats2__(std::clog, "shape_datasource::init(get_column_description)"); #endif std::unique_ptr<shape_io> shape_ref = std::make_unique<shape_io>(shape_name_); init(*shape_ref); for (int i=0;i<shape_ref->dbf().num_fields();++i) { field_descriptor const& fd=shape_ref->dbf().descriptor(i); std::string fld_name=fd.name_; switch (fd.type_) { case 'C': // character case 'D': // date desc_.add_descriptor(attribute_descriptor(fld_name, String)); break; case 'L': // logical desc_.add_descriptor(attribute_descriptor(fld_name, Boolean)); break; case 'N': // numeric case 'O': // double case 'F': // float { if (fd.dec_>0) { desc_.add_descriptor(attribute_descriptor(fld_name,Double,false,8)); } else { desc_.add_descriptor(attribute_descriptor(fld_name,Integer,false,4)); } break; } default: // I - long // G - ole // + - autoincrement // @ - timestamp // B - binary // l - long // M - memo MAPNIK_LOG_ERROR(shape) << "shape_datasource: Unknown type=" << fd.type_; break; } } } catch (datasource_exception const& ex) { MAPNIK_LOG_ERROR(shape) << "Shape Plugin: error processing field attributes, " << ex.what(); throw; } catch (const std::exception& ex) { MAPNIK_LOG_ERROR(shape) << "Shape Plugin: error processing field attributes, " << ex.what(); throw; } catch (...) // exception: pipe_select_interrupter: Too many open files { MAPNIK_LOG_ERROR(shape) << "Shape Plugin: error processing field attributes"; throw; } }
feature_ptr ogr_featureset::next() { if (count_ == 0) { // Reset the layer reading on the first feature read // this is a hack, but needed due to https://github.com/mapnik/mapnik/issues/2048 // Proper solution is to avoid storing layer state in featureset layer_.ResetReading(); } OGRFeature *poFeature; while ((poFeature = layer_.GetNextFeature()) != nullptr) { // ogr feature ids start at 0, so add one to stay // consistent with other mapnik datasources that start at 1 mapnik::value_integer feature_id = (poFeature->GetFID() + 1); feature_ptr feature(feature_factory::create(ctx_,feature_id)); OGRGeometry* geom = poFeature->GetGeometryRef(); if (geom && ! geom->IsEmpty()) { auto geom_corrected = ogr_converter::convert_geometry(geom); mapnik::geometry::correct(geom_corrected); feature->set_geometry(std::move(geom_corrected)); } else { MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: Feature with null geometry=" << poFeature->GetFID(); OGRFeature::DestroyFeature( poFeature ); continue; } ++count_; int fld_count = layerdef_->GetFieldCount(); for (int i = 0; i < fld_count; i++) { OGRFieldDefn* fld = layerdef_->GetFieldDefn(i); const OGRFieldType type_oid = fld->GetType(); const std::string fld_name = fld->GetNameRef(); switch (type_oid) { case OFTInteger: { feature->put<mapnik::value_integer>( fld_name, poFeature->GetFieldAsInteger(i)); break; } #if GDAL_VERSION_MAJOR >= 2 case OFTInteger64: { feature->put<mapnik::value_integer>( fld_name, poFeature->GetFieldAsInteger64(i)); break; } #endif case OFTReal: { feature->put( fld_name, poFeature->GetFieldAsDouble(i)); break; } case OFTString: case OFTWideString: // deprecated ! { feature->put( fld_name, tr_->transcode(poFeature->GetFieldAsString(i))); break; } case OFTIntegerList: #if GDAL_VERSION_MAJOR >= 2 case OFTInteger64List: #endif case OFTRealList: case OFTStringList: case OFTWideStringList: // deprecated ! { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid; break; } case OFTBinary: { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid; //feature->put(name,feat->GetFieldAsBinary (i, size)); break; } case OFTDate: case OFTTime: case OFTDateTime: // unhandled ! { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid; break; } default: // unknown { MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unknown type_oid=" << type_oid; break; } } } OGRFeature::DestroyFeature( poFeature ); return feature; } MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: " << count_ << " features"; return feature_ptr(); }
gdal_datasource::gdal_datasource(parameters const& params) : datasource(params), desc_(gdal_datasource::name(), "utf-8"), nodata_value_(params.get<double>("nodata")), nodata_tolerance_(*params.get<double>("nodata_tolerance",1e-12)) { MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource: Initializing..."; #ifdef MAPNIK_STATS mapnik::progress_timer __stats__(std::clog, "gdal_datasource::init"); #endif GDALAllRegister(); boost::optional<std::string> file = params.get<std::string>("file"); if (! file) throw datasource_exception("missing <file> parameter"); boost::optional<std::string> base = params.get<std::string>("base"); if (base) { dataset_name_ = *base + "/" + *file; } else { dataset_name_ = *file; } shared_dataset_ = *params.get<mapnik::boolean_type>("shared", false); band_ = *params.get<mapnik::value_integer>("band", -1); GDALDataset *dataset = open_dataset(); nbands_ = dataset->GetRasterCount(); width_ = dataset->GetRasterXSize(); height_ = dataset->GetRasterYSize(); desc_.add_descriptor(mapnik::attribute_descriptor("nodata", mapnik::Double)); double tr[6]; bool bbox_override = false; boost::optional<std::string> bbox_s = params.get<std::string>("extent"); if (bbox_s) { MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource: BBox Parameter=" << *bbox_s; bbox_override = extent_.from_string(*bbox_s); if (! bbox_override) { throw datasource_exception("GDAL Plugin: bbox parameter '" + *bbox_s + "' invalid"); } } if (bbox_override) { tr[0] = extent_.minx(); tr[1] = extent_.width() / (double)width_; tr[2] = 0; tr[3] = extent_.maxy(); tr[4] = 0; tr[5] = -extent_.height() / (double)height_; MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource extent override gives Geotransform=" << tr[0] << "," << tr[1] << "," << tr[2] << "," << tr[3] << "," << tr[4] << "," << tr[5]; } else { if (dataset->GetGeoTransform(tr) != CPLE_None) { MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource GetGeotransform failure gives=" << tr[0] << "," << tr[1] << "," << tr[2] << "," << tr[3] << "," << tr[4] << "," << tr[5]; } else { MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource Geotransform=" << tr[0] << "," << tr[1] << "," << tr[2] << "," << tr[3] << "," << tr[4] << "," << tr[5]; } } // TODO - We should throw for true non-north up images, but the check // below is clearly too restrictive. // https://github.com/mapnik/mapnik/issues/970 /* if (tr[2] != 0 || tr[4] != 0) { throw datasource_exception("GDAL Plugin: only 'north up' images are supported"); } */ dx_ = tr[1]; dy_ = tr[5]; if (! bbox_override) { double x0 = tr[0]; double y0 = tr[3]; double x1 = tr[0] + width_ * dx_ + height_ *tr[2]; double y1 = tr[3] + width_ *tr[4] + height_ * dy_; /* double x0 = tr[0] + (height_) * tr[2]; // minx double y0 = tr[3] + (height_) * tr[5]; // miny double x1 = tr[0] + (width_) * tr[1]; // maxx double y1 = tr[3] + (width_) * tr[4]; // maxy */ extent_.init(x0, y0, x1, y1); } GDALClose(dataset); MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource: Raster Size=" << width_ << "," << height_; MAPNIK_LOG_DEBUG(gdal) << "gdal_datasource: Raster Extent=" << extent_; }
featureset_ptr sqlite_datasource::features(query const& q) const { if (!is_bound_) bind(); if (dataset_) { mapnik::box2d<double> const& e = q.get_bbox(); std::ostringstream s; s << "SELECT " << geometry_field_ << "," << key_field_; std::set<std::string> const& props = q.property_names(); std::set<std::string>::const_iterator pos = props.begin(); std::set<std::string>::const_iterator end = props.end(); while (pos != end) { s << ",\"" << *pos << "\""; ++pos; } s << " FROM "; std::string query (table_); if (use_spatial_index_) { std::ostringstream spatial_sql; spatial_sql << std::setprecision(16); spatial_sql << " WHERE " << key_field_ << " IN (SELECT pkid FROM idx_" << geometry_table_ << "_" << geometry_field_; spatial_sql << " WHERE xmax>=" << e.minx() << " AND xmin<=" << e.maxx() ; spatial_sql << " AND ymax>=" << e.miny() << " AND ymin<=" << e.maxy() << ")"; if (boost::algorithm::ifind_first(query, "WHERE")) { boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND "); } else if (boost::algorithm::ifind_first(query, geometry_table_)) { boost::algorithm::ireplace_first(query, table_, table_ + " " + spatial_sql.str()); } } s << query ; if (row_limit_ > 0) { s << " LIMIT " << row_limit_; } if (row_offset_ > 0) { s << " OFFSET " << row_offset_; } #ifdef MAPNIK_DEBUG std::clog << "Sqlite Plugin: " << s.str() << std::endl; #endif boost::shared_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str())); return boost::make_shared<sqlite_featureset>(rs, desc_.get_encoding(), format_, multiple_geometries_); } return featureset_ptr(); }
void save_to_file2(mapnik::image_32 const& im, std::string const& filename, std::string const& type) { save_to_file(im,filename,type); }
featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const { if (!is_bound_) bind(); if (dataset_) { // TODO - need tolerance mapnik::box2d<double> const e(pt.x,pt.y,pt.x,pt.y); std::ostringstream s; s << "SELECT " << geometry_field_ << "," << key_field_; std::vector<attribute_descriptor>::const_iterator itr = desc_.get_descriptors().begin(); std::vector<attribute_descriptor>::const_iterator end = desc_.get_descriptors().end(); while (itr != end) { std::string fld_name = itr->get_name(); if (fld_name != key_field_) s << ",\"" << itr->get_name() << "\""; ++itr; } s << " FROM "; std::string query (table_); if (use_spatial_index_) { std::ostringstream spatial_sql; spatial_sql << std::setprecision(16); spatial_sql << " WHERE " << key_field_ << " IN (SELECT pkid FROM idx_" << geometry_table_ << "_" << geometry_field_; spatial_sql << " WHERE xmax>=" << e.minx() << " AND xmin<=" << e.maxx() ; spatial_sql << " AND ymax>=" << e.miny() << " AND ymin<=" << e.maxy() << ")"; if (boost::algorithm::ifind_first(query, "WHERE")) { boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND "); } else if (boost::algorithm::ifind_first(query, geometry_table_)) { boost::algorithm::ireplace_first(query, table_, table_ + " " + spatial_sql.str()); } } s << query ; if (row_limit_ > 0) { s << " LIMIT " << row_limit_; } if (row_offset_ > 0) { s << " OFFSET " << row_offset_; } #ifdef MAPNIK_DEBUG std::clog << "Sqlite Plugin: " << s.str() << std::endl; #endif boost::shared_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str())); return boost::make_shared<sqlite_featureset>(rs, desc_.get_encoding(), format_, multiple_geometries_); } return featureset_ptr(); }
feature_ptr ogr_index_featureset<filterT>::next() { if (itr_ != ids_.end()) { int pos = *itr_++; layer_.SetNextByIndex (pos); ogr_feature_ptr feat (layer_.GetNextFeature()); if ((*feat) != NULL) { // ogr feature ids start at 0, so add one to stay // consistent with other mapnik datasources that start at 1 int feature_id = ((*feat)->GetFID() + 1); feature_ptr feature(feature_factory::create(feature_id)); OGRGeometry* geom=(*feat)->GetGeometryRef(); if (geom && !geom->IsEmpty()) { ogr_converter::convert_geometry (geom, feature, multiple_geometries_); } #ifdef MAPNIK_DEBUG else { std::clog << "### Warning: feature with null geometry: " << (*feat)->GetFID() << "\n"; } #endif int fld_count = layerdef_->GetFieldCount(); for (int i = 0; i < fld_count; i++) { OGRFieldDefn* fld = layerdef_->GetFieldDefn (i); OGRFieldType type_oid = fld->GetType (); std::string fld_name = fld->GetNameRef (); switch (type_oid) { case OFTInteger: { boost::put(*feature,fld_name,(*feat)->GetFieldAsInteger (i)); break; } case OFTReal: { boost::put(*feature,fld_name,(*feat)->GetFieldAsDouble (i)); break; } case OFTString: case OFTWideString: // deprecated ! { UnicodeString ustr = tr_->transcode((*feat)->GetFieldAsString (i)); boost::put(*feature,fld_name,ustr); break; } case OFTIntegerList: case OFTRealList: case OFTStringList: case OFTWideStringList: // deprecated ! { #ifdef MAPNIK_DEBUG std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl; #endif break; } case OFTBinary: { #ifdef MAPNIK_DEBUG std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl; #endif //boost::put(*feature,name,feat->GetFieldAsBinary (i, size)); break; } case OFTDate: case OFTTime: case OFTDateTime: // unhandled ! { #ifdef MAPNIK_DEBUG std::clog << "OGR Plugin: unhandled type_oid=" << type_oid << std::endl; #endif break; } default: // unknown { #ifdef MAPNIK_DEBUG std::clog << "OGR Plugin: unknown type_oid=" << type_oid << std::endl; #endif break; } } } return feature; } } return feature_ptr(); }
feature_ptr gdal_featureset::get_feature(mapnik::query const& q) { feature_ptr feature = feature_factory::create(ctx_,1); GDALRasterBand * red = 0; GDALRasterBand * green = 0; GDALRasterBand * blue = 0; GDALRasterBand * alpha = 0; GDALRasterBand * grey = 0; /* #ifdef MAPNIK_LOG double tr[6]; dataset_.GetGeoTransform(tr); const double dx = tr[1]; const double dy = tr[5]; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: dx_=" << dx_ << " dx=" << dx << " dy_=" << dy_ << "dy=" << dy; #endif */ CoordTransform t(raster_width_, raster_height_, raster_extent_, 0, 0); box2d<double> intersect = raster_extent_.intersect(q.get_bbox()); box2d<double> box = t.forward(intersect); //size of resized output pixel in source image domain double margin_x = 1.0 / (fabs(dx_) * boost::get<0>(q.resolution())); double margin_y = 1.0 / (fabs(dy_) * boost::get<1>(q.resolution())); if (margin_x < 1) { margin_x = 1.0; } if (margin_y < 1) { margin_y = 1.0; } //select minimum raster containing whole box int x_off = rint(box.minx() - margin_x); int y_off = rint(box.miny() - margin_y); int end_x = rint(box.maxx() + margin_x); int end_y = rint(box.maxy() + margin_y); //clip to available data if (x_off < 0) { x_off = 0; } if (y_off < 0) { y_off = 0; } if (end_x > (int)raster_width_) { end_x = raster_width_; } if (end_y > (int)raster_height_) { end_y = raster_height_; } int width = end_x - x_off; int height = end_y - y_off; // don't process almost invisible data if (box.width() < 0.5) { width = 0; } if (box.height() < 0.5) { height = 0; } //calculate actual box2d of returned raster box2d<double> feature_raster_extent(x_off, y_off, x_off + width, y_off + height); intersect = t.backward(feature_raster_extent); MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Raster extent=" << raster_extent_; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: View extent=" << intersect; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Query resolution=" << boost::get<0>(q.resolution()) << "," << boost::get<1>(q.resolution()); MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: StartX=" << x_off << " StartY=" << y_off << " Width=" << width << " Height=" << height; if (width > 0 && height > 0) { double width_res = boost::get<0>(q.resolution()); double height_res = boost::get<1>(q.resolution()); int im_width = int(width_res * intersect.width() + 0.5); int im_height = int(height_res * intersect.height() + 0.5); // if layer-level filter_factor is set, apply it if (filter_factor_) { im_width *= filter_factor_; im_height *= filter_factor_; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Applying layer filter_factor=" << filter_factor_; } // otherwise respect symbolizer level factor applied to query, default of 1.0 else { double sym_downsample_factor = q.get_filter_factor(); im_width *= sym_downsample_factor; im_height *= sym_downsample_factor; } // case where we need to avoid upsampling so that the // image can be later scaled within raster_symbolizer if (im_width >= width || im_height >= height) { im_width = width; im_height = height; } if (im_width > 0 && im_height > 0) { mapnik::raster_ptr raster = boost::make_shared<mapnik::raster>(intersect, im_width, im_height); feature->set_raster(raster); mapnik::image_data_32 & image = raster->data_; image.set(0xffffffff); MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Image Size=(" << im_width << "," << im_height << ")"; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Reading band=" << band_; if (band_ > 0) // we are querying a single band { if (band_ > nbands_) { throw datasource_exception((boost::format("GDAL Plugin: '%d' is an invalid band, dataset only has '%d' bands\n") % band_ % nbands_).str()); } float* imageData = (float*)image.getBytes(); GDALRasterBand * band = dataset_.GetRasterBand(band_); int hasNoData(0); double nodata(0); if (nodata_value_) { hasNoData = 1; nodata = *nodata_value_; } else { nodata = band->GetNoDataValue(&hasNoData); } band->RasterIO(GF_Read, x_off, y_off, width, height, imageData, image.width(), image.height(), GDT_Float32, 0, 0); if (hasNoData) { feature->put("NODATA",nodata); } } else // working with all bands { for (int i = 0; i < nbands_; ++i) { GDALRasterBand * band = dataset_.GetRasterBand(i + 1); #ifdef MAPNIK_LOG get_overview_meta(band); #endif GDALColorInterp color_interp = band->GetColorInterpretation(); switch (color_interp) { case GCI_RedBand: red = band; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found red band"; break; case GCI_GreenBand: green = band; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found green band"; break; case GCI_BlueBand: blue = band; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found blue band"; break; case GCI_AlphaBand: alpha = band; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found alpha band"; break; case GCI_GrayIndex: grey = band; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band"; break; case GCI_PaletteIndex: { grey = band; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found gray band, and colortable..."; GDALColorTable *color_table = band->GetColorTable(); if (color_table) { int count = color_table->GetColorEntryCount(); MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color Table count=" << count; for (int j = 0; j < count; j++) { const GDALColorEntry *ce = color_table->GetColorEntry (j); if (! ce) continue; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Color entry RGB=" << ce->c1 << "," <<ce->c2 << "," << ce->c3; } } break; } case GCI_Undefined: MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Found undefined band (assumming gray band)"; grey = band; break; default: MAPNIK_LOG_WARN(gdal) << "gdal_featureset: Band type unknown!"; break; } } if (red && green && blue) { MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing rgb bands..."; int hasNoData = 0; double nodata = 0.0; if (nodata_value_) { hasNoData = 1; nodata = *nodata_value_; } else { nodata = red->GetNoDataValue(&hasNoData); } if (hasNoData) { feature->put("NODATA",nodata); } GDALColorTable *color_table = red->GetColorTable(); if (! alpha && hasNoData && ! color_table) { // first read the data in and create an alpha channel from the nodata values float* imageData = (float*)image.getBytes(); red->RasterIO(GF_Read, x_off, y_off, width, height, imageData, image.width(), image.height(), GDT_Float32, 0, 0); int len = image.width() * image.height(); for (int i = 0; i < len; ++i) { if (nodata == imageData[i]) { *reinterpret_cast<unsigned *>(&imageData[i]) = 0; } else { *reinterpret_cast<unsigned *>(&imageData[i]) = 0xFFFFFFFF; } } } red->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0, image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); green->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 1, image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); blue->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 2, image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); } else if (grey) { MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Processing gray band..."; int hasNoData(0); double nodata(0); if (nodata_value_) { hasNoData = 1; nodata = *nodata_value_; } else { nodata = grey->GetNoDataValue(&hasNoData); } GDALColorTable* color_table = grey->GetColorTable(); if (hasNoData && ! color_table) { MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: No data value for layer=" << nodata; feature->put("NODATA",nodata); // first read the data in and create an alpha channel from the nodata values float* imageData = (float*)image.getBytes(); grey->RasterIO(GF_Read, x_off, y_off, width, height, imageData, image.width(), image.height(), GDT_Float32, 0, 0); int len = image.width() * image.height(); for (int i = 0; i < len; ++i) { if (nodata == imageData[i]) { *reinterpret_cast<unsigned *>(&imageData[i]) = 0; } else { *reinterpret_cast<unsigned *> (&imageData[i]) = 0xFFFFFFFF; } } } grey->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0, image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 1, image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 2, image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); if (color_table) { MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Loading colour table..."; unsigned nodata_value = static_cast<unsigned>(nodata); if (hasNoData) { feature->put("NODATA",static_cast<int>(nodata_value)); } for (unsigned y = 0; y < image.height(); ++y) { unsigned int* row = image.getRow(y); for (unsigned x = 0; x < image.width(); ++x) { unsigned value = row[x] & 0xff; if (hasNoData && (value == nodata_value)) { // make no data fully alpha row[x] = 0; } else { const GDALColorEntry *ce = color_table->GetColorEntry(value); if (ce) { // TODO - big endian support row[x] = (ce->c4 << 24)| (ce->c3 << 16) | (ce->c2 << 8) | (ce->c1) ; } else { // make lacking color entry fully alpha // note - gdal_translate makes black row[x] = 0; } } } } } } if (alpha) { MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: processing alpha band..."; alpha->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 3, image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); } } return feature; } } return feature_ptr(); }