@@ -569,23 +569,28 @@ class lookup_distortion
569569{
570570public:
571571 lookup_distortion (const double *mesh, int in_width, int in_height,
572- int out_width, int out_height) :
572+ int out_width, int out_height, bool edge_aligned_subpixels ) :
573573 m_mesh (mesh),
574574 m_in_width (in_width),
575575 m_in_height (in_height),
576576 m_out_width (out_width),
577- m_out_height (out_height)
577+ m_out_height (out_height),
578+ m_edge_aligned_subpixels (edge_aligned_subpixels)
578579 {}
579580
580581 void calculate (int * x, int * y) {
581582 if (m_mesh) {
583+ // Nearest-neighbor interpolation needs edge-aligned subpixels
584+ // All other interpolation approaches need center-aligned subpixels
585+ double offset = m_edge_aligned_subpixels ? 0 : 0.5 ;
586+
582587 double dx = double (*x) / agg::image_subpixel_scale;
583588 double dy = double (*y) / agg::image_subpixel_scale;
584589 if (dx >= 0 && dx < m_out_width &&
585590 dy >= 0 && dy < m_out_height) {
586591 const double *coord = m_mesh + (int (dy) * m_out_width + int (dx)) * 2 ;
587- *x = int (coord[0 ] * agg::image_subpixel_scale + 0.5 ); // round
588- *y = int (coord[1 ] * agg::image_subpixel_scale + 0.5 ); // round
592+ *x = int (coord[0 ] * agg::image_subpixel_scale + offset);
593+ *y = int (coord[1 ] * agg::image_subpixel_scale + offset);
589594 }
590595 }
591596 }
@@ -596,6 +601,7 @@ class lookup_distortion
596601 int m_in_height;
597602 int m_out_width;
598603 int m_out_height;
604+ bool m_edge_aligned_subpixels;
599605};
600606
601607
@@ -781,7 +787,7 @@ void resample(
781787 using span_conv_t = agg::span_converter<span_gen_t , span_conv_alpha_t >;
782788 using nn_renderer_t = agg::renderer_scanline_aa<renderer_t , span_alloc_t , span_conv_t >;
783789 lookup_distortion dist (
784- params.transform_mesh , in_width, in_height, out_width, out_height);
790+ params.transform_mesh , in_width, in_height, out_width, out_height, true );
785791 arbitrary_interpolator_t interpolator (inverted, dist);
786792 span_gen_t span_gen (input_accessor, interpolator);
787793 span_conv_t span_conv (span_gen, conv_alpha);
@@ -806,7 +812,7 @@ void resample(
806812 using span_conv_t = agg::span_converter<span_gen_t , span_conv_alpha_t >;
807813 using int_renderer_t = agg::renderer_scanline_aa<renderer_t , span_alloc_t , span_conv_t >;
808814 lookup_distortion dist (
809- params.transform_mesh , in_width, in_height, out_width, out_height);
815+ params.transform_mesh , in_width, in_height, out_width, out_height, false );
810816 arbitrary_interpolator_t interpolator (inverted, dist);
811817 span_gen_t span_gen (input_accessor, interpolator, filter);
812818 span_conv_t span_conv (span_gen, conv_alpha);
0 commit comments