void graphics<Canvas>::render(const Path& path, const Brush& brush) { static raster raster; raster.rasterize(path); for (int y = raster.bbox().top; y < raster.bbox().bottom; ++y) for (const raster::span& span : raster.fetch_scanline(y)) for (int x = span.x, end_x = span.x + int(span.length); x < end_x; ++x) canvas_.pixel(x, y, brush, span.coverage); }
/** * normalize [0, 1.0] in place */ inline raster normalize(raster& v) { auto minmax = std::minmax_element(v.begin(), v.end()); float min = *minmax.first; float max = *minmax.second; float diff = max - min; if (diff == 0) // max == min return v; // normalize in place for (auto& f : v) f = (f - min) / diff; return v; }
/** handy method to display a raster * * @param v vector of float * @returns vector of uint8_t (unisgned char) * * distribute as: * min(v) -> 0 * max(v) -> 255 */ inline bytes_t raster2bytes(const raster& v) { auto minmax = std::minmax_element(v.begin(), v.end()); float min = *minmax.first; float max = *minmax.second; float diff = max - min; bytes_t b(v.size()); if (diff == 0) // max == min (useless band) return b; float coef = 255.0 / diff; std::transform(v.begin(), v.end(), b.begin(), // C++11 lambda, capture local varibles by reference [&] [&](float f) -> uint8_t { return std::floor( coef * (f - min) ); }); return b; }
void reproject_and_scale_raster(raster & target, raster const& source, proj_transform const& prj_trans, double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method) { detail::warp_image_visitor warper(target, prj_trans, source.ext_, offset_x, offset_y, mesh_size, scaling_method, source.get_filter_factor()); util::apply_visitor(warper, source.data_); }
color internal_smooth_pixel (double x, double y) { return (color) r->internal_smooth_pixel (x, y); }
void reproject_and_scale_raster(raster & target, raster const& source, proj_transform const& prj_trans, double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method) { CoordTransform ts(source.data_.width(), source.data_.height(), source.ext_); CoordTransform tt(target.data_.width(), target.data_.height(), target.ext_, offset_x, offset_y); unsigned mesh_nx = std::ceil(source.data_.width()/double(mesh_size) + 1); unsigned mesh_ny = std::ceil(source.data_.height()/double(mesh_size) + 1); ImageData<double> xs(mesh_nx, mesh_ny); ImageData<double> ys(mesh_nx, mesh_ny); // Precalculate reprojected mesh for(unsigned j=0; j<mesh_ny; ++j) { for (unsigned i=0; i<mesh_nx; ++i) { xs(i,j) = std::min(i*mesh_size,source.data_.width()); ys(i,j) = std::min(j*mesh_size,source.data_.height()); ts.backward(&xs(i,j), &ys(i,j)); } } prj_trans.backward(xs.getData(), ys.getData(), nullptr, mesh_nx*mesh_ny); // Initialize AGG objects using pixfmt = agg::pixfmt_rgba32_pre; using color_type = pixfmt::color_type; using renderer_base = agg::renderer_base<pixfmt>; agg::rasterizer_scanline_aa<> rasterizer; agg::scanline_u8 scanline; agg::rendering_buffer buf((unsigned char*)target.data_.getData(), target.data_.width(), target.data_.height(), target.data_.width()*4); pixfmt pixf(buf); renderer_base rb(pixf); rasterizer.clip_box(0, 0, target.data_.width(), target.data_.height()); agg::rendering_buffer buf_tile( (unsigned char*)source.data_.getData(), source.data_.width(), source.data_.height(), source.data_.width() * 4); pixfmt pixf_tile(buf_tile); using img_accessor_type = agg::image_accessor_clone<pixfmt>; img_accessor_type ia(pixf_tile); agg::span_allocator<color_type> sa; // Initialize filter agg::image_filter_lut filter; switch(scaling_method) { case SCALING_NEAR: break; case SCALING_BILINEAR8: // TODO - impl this or remove? case SCALING_BILINEAR: filter.calculate(agg::image_filter_bilinear(), true); break; case SCALING_BICUBIC: filter.calculate(agg::image_filter_bicubic(), true); break; case SCALING_SPLINE16: filter.calculate(agg::image_filter_spline16(), true); break; case SCALING_SPLINE36: filter.calculate(agg::image_filter_spline36(), true); break; case SCALING_HANNING: filter.calculate(agg::image_filter_hanning(), true); break; case SCALING_HAMMING: filter.calculate(agg::image_filter_hamming(), true); break; case SCALING_HERMITE: filter.calculate(agg::image_filter_hermite(), true); break; case SCALING_KAISER: filter.calculate(agg::image_filter_kaiser(), true); break; case SCALING_QUADRIC: filter.calculate(agg::image_filter_quadric(), true); break; case SCALING_CATROM: filter.calculate(agg::image_filter_catrom(), true); break; case SCALING_GAUSSIAN: filter.calculate(agg::image_filter_gaussian(), true); break; case SCALING_BESSEL: filter.calculate(agg::image_filter_bessel(), true); break; case SCALING_MITCHELL: filter.calculate(agg::image_filter_mitchell(), true); break; case SCALING_SINC: filter.calculate(agg::image_filter_sinc(source.get_filter_factor()), true); break; case SCALING_LANCZOS: filter.calculate(agg::image_filter_lanczos(source.get_filter_factor()), true); break; case SCALING_BLACKMAN: filter.calculate(agg::image_filter_blackman(source.get_filter_factor()), true); break; } // Project mesh cells into target interpolating raster inside each one for(unsigned j=0; j<mesh_ny-1; ++j) { for (unsigned i=0; i<mesh_nx-1; ++i) { double polygon[8] = {xs(i,j), ys(i,j), xs(i+1,j), ys(i+1,j), xs(i+1,j+1), ys(i+1,j+1), xs(i,j+1), ys(i,j+1)}; tt.forward(polygon+0, polygon+1); tt.forward(polygon+2, polygon+3); tt.forward(polygon+4, polygon+5); tt.forward(polygon+6, polygon+7); rasterizer.reset(); rasterizer.move_to_d(std::floor(polygon[0]), std::floor(polygon[1])); rasterizer.line_to_d(std::floor(polygon[2]), std::floor(polygon[3])); rasterizer.line_to_d(std::floor(polygon[4]), std::floor(polygon[5])); rasterizer.line_to_d(std::floor(polygon[6]), std::floor(polygon[7])); unsigned x0 = i * mesh_size; unsigned y0 = j * mesh_size; unsigned x1 = (i+1) * mesh_size; unsigned y1 = (j+1) * mesh_size; x1 = std::min(x1, source.data_.width()); y1 = std::min(y1, source.data_.height()); agg::trans_affine tr(polygon, x0, y0, x1, y1); if (tr.is_valid()) { using interpolator_type = agg::span_interpolator_linear<agg::trans_affine>; interpolator_type interpolator(tr); if (scaling_method == SCALING_NEAR) { using span_gen_type = agg::span_image_filter_rgba_nn <img_accessor_type, interpolator_type>; span_gen_type sg(ia, interpolator); agg::render_scanlines_aa(rasterizer, scanline, rb, sa, sg); } else { using span_gen_type = agg::span_image_resample_rgba_affine <img_accessor_type>; span_gen_type sg(ia, interpolator, filter); agg::render_scanlines_aa(rasterizer, scanline, rb, sa, sg); } } } } }