88#include " agg_image_accessors.h"
99#include " agg_path_storage.h"
1010#include " agg_pixfmt_gray.h"
11+ #include " agg_pixfmt_rgb.h"
1112#include " agg_pixfmt_rgba.h"
1213#include " agg_renderer_base.h"
1314#include " agg_renderer_scanline.h"
1617#include " agg_span_allocator.h"
1718#include " agg_span_converter.h"
1819#include " agg_span_image_filter_gray.h"
20+ #include " agg_span_image_filter_rgb.h"
1921#include " agg_span_image_filter_rgba.h"
2022#include " agg_span_interpolator_adaptor.h"
2123#include " agg_span_interpolator_linear.h"
@@ -496,16 +498,38 @@ typedef enum {
496498} interpolation_e;
497499
498500
499- // T is rgba if and only if it has an T::r field.
501+ // T is rgb(a) if and only if it has an T::r field.
500502template <typename T, typename = void > struct is_grayscale : std::true_type {};
501503template <typename T> struct is_grayscale <T, std::void_t <decltype (T::r)>> : std::false_type {};
502504template <typename T> constexpr bool is_grayscale_v = is_grayscale<T>::value;
503505
504506
505- template <typename color_type>
507+ template <typename color_type, bool input_has_alpha >
506508struct type_mapping
507509{
508- using blender_type = std::conditional_t <
510+ using input_blender_type = std::conditional_t <
511+ is_grayscale_v<color_type>,
512+ agg::blender_gray<color_type>,
513+ std::conditional_t <
514+ input_has_alpha,
515+ std::conditional_t <
516+ std::is_same_v<color_type, agg::rgba8>,
517+ fixed_blender_rgba_plain<color_type, agg::order_rgba>,
518+ agg::blender_rgba_plain<color_type, agg::order_rgba>
519+ >,
520+ agg::blender_rgb<color_type, agg::order_rgb>
521+ >
522+ >;
523+ using input_pixfmt_type = std::conditional_t <
524+ is_grayscale_v<color_type>,
525+ agg::pixfmt_alpha_blend_gray<input_blender_type, agg::rendering_buffer>,
526+ std::conditional_t <
527+ input_has_alpha,
528+ agg::pixfmt_alpha_blend_rgba<input_blender_type, agg::rendering_buffer>,
529+ agg::pixfmt_alpha_blend_rgb<input_blender_type, agg::rendering_buffer, 3 >
530+ >
531+ >;
532+ using output_blender_type = std::conditional_t <
509533 is_grayscale_v<color_type>,
510534 agg::blender_gray<color_type>,
511535 std::conditional_t <
@@ -514,25 +538,37 @@ struct type_mapping
514538 agg::blender_rgba_plain<color_type, agg::order_rgba>
515539 >
516540 >;
517- using pixfmt_type = std::conditional_t <
541+ using output_pixfmt_type = std::conditional_t <
518542 is_grayscale_v<color_type>,
519- agg::pixfmt_alpha_blend_gray<blender_type , agg::rendering_buffer>,
520- agg::pixfmt_alpha_blend_rgba<blender_type , agg::rendering_buffer>
543+ agg::pixfmt_alpha_blend_gray<output_blender_type , agg::rendering_buffer>,
544+ agg::pixfmt_alpha_blend_rgba<output_blender_type , agg::rendering_buffer>
521545 >;
522546 template <typename A> using span_gen_affine_type = std::conditional_t <
523547 is_grayscale_v<color_type>,
524548 agg::span_image_resample_gray_affine<A>,
525- agg::span_image_resample_rgba_affine<A>
549+ std::conditional_t <
550+ input_has_alpha,
551+ agg::span_image_resample_rgba_affine<A>,
552+ agg::span_image_resample_rgb_affine<A>
553+ >
526554 >;
527555 template <typename A, typename B> using span_gen_filter_type = std::conditional_t <
528556 is_grayscale_v<color_type>,
529557 agg::span_image_filter_gray<A, B>,
530- agg::span_image_filter_rgba<A, B>
558+ std::conditional_t <
559+ input_has_alpha,
560+ agg::span_image_filter_rgba<A, B>,
561+ agg::span_image_filter_rgb<A, B>
562+ >
531563 >;
532564 template <typename A, typename B> using span_gen_nn_type = std::conditional_t <
533565 is_grayscale_v<color_type>,
534566 agg::span_image_filter_gray_nn<A, B>,
535- agg::span_image_filter_rgba_nn<A, B>
567+ std::conditional_t <
568+ input_has_alpha,
569+ agg::span_image_filter_rgba_nn<A, B>,
570+ agg::span_image_filter_rgb_nn<A, B>
571+ >
536572 >;
537573};
538574
@@ -686,16 +722,16 @@ static void get_filter(const resample_params_t ¶ms,
686722}
687723
688724
689- template <typename color_type>
725+ template <typename color_type, bool input_has_alpha = true >
690726void resample (
691727 const void *input, int in_width, int in_height,
692728 void *output, int out_width, int out_height,
693729 resample_params_t ¶ms)
694730{
695- using type_mapping_t = type_mapping<color_type>;
731+ using type_mapping_t = type_mapping<color_type, input_has_alpha >;
696732
697- using input_pixfmt_t = typename type_mapping_t ::pixfmt_type ;
698- using output_pixfmt_t = typename type_mapping_t ::pixfmt_type ;
733+ using input_pixfmt_t = typename type_mapping_t ::input_pixfmt_type ;
734+ using output_pixfmt_t = typename type_mapping_t ::output_pixfmt_type ;
699735
700736 using renderer_t = agg::renderer_base<output_pixfmt_t >;
701737 using rasterizer_t = agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl>;
@@ -711,9 +747,16 @@ void resample(
711747 using arbitrary_interpolator_t =
712748 agg::span_interpolator_adaptor<agg::span_interpolator_linear<>, lookup_distortion>;
713749
714- size_t itemsize = sizeof (color_type);
750+ size_t in_itemsize = sizeof (color_type);
751+ size_t out_itemsize = sizeof (color_type);
715752 if (is_grayscale<color_type>::value) {
716- itemsize /= 2 ; // agg::grayXX includes an alpha channel which we don't have.
753+ // agg::grayXX includes an alpha channel which we don't have.
754+ in_itemsize /= 2 ;
755+ out_itemsize /= 2 ;
756+ } else if (!input_has_alpha) {
757+ // color_type is the output type, but the input doesn't have an alpha channel,
758+ // so we remove one value's size off the input size.
759+ in_itemsize -= sizeof (typename color_type::value_type);
717760 }
718761
719762 if (params.interpolation != NEAREST &&
@@ -733,13 +776,13 @@ void resample(
733776
734777 agg::rendering_buffer input_buffer;
735778 input_buffer.attach (
736- (unsigned char *)input, in_width, in_height, in_width * itemsize );
779+ (unsigned char *)input, in_width, in_height, in_width * in_itemsize );
737780 input_pixfmt_t input_pixfmt (input_buffer);
738781 image_accessor_t input_accessor (input_pixfmt);
739782
740783 agg::rendering_buffer output_buffer;
741784 output_buffer.attach (
742- (unsigned char *)output, out_width, out_height, out_width * itemsize );
785+ (unsigned char *)output, out_width, out_height, out_width * out_itemsize );
743786 output_pixfmt_t output_pixfmt (output_buffer);
744787 renderer_t renderer (output_pixfmt);
745788
0 commit comments