8
8
#include " agg_image_accessors.h"
9
9
#include " agg_path_storage.h"
10
10
#include " agg_pixfmt_gray.h"
11
+ #include " agg_pixfmt_rgb.h"
11
12
#include " agg_pixfmt_rgba.h"
12
13
#include " agg_renderer_base.h"
13
14
#include " agg_renderer_scanline.h"
16
17
#include " agg_span_allocator.h"
17
18
#include " agg_span_converter.h"
18
19
#include " agg_span_image_filter_gray.h"
20
+ #include " agg_span_image_filter_rgb.h"
19
21
#include " agg_span_image_filter_rgba.h"
20
22
#include " agg_span_interpolator_adaptor.h"
21
23
#include " agg_span_interpolator_linear.h"
@@ -496,16 +498,38 @@ typedef enum {
496
498
} interpolation_e;
497
499
498
500
499
- // T isrgba if and only if it has an T::r field.
501
+ // T isrgb(a) if and only if it has an T::r field.
500
502
template <typename T,typename =void >struct is_grayscale : std::true_type {};
501
503
template <typename T>struct is_grayscale <T, std::void_t <decltype(T::r)>> : std::false_type {};
502
504
template <typename T>constexpr bool is_grayscale_v = is_grayscale<T>::value;
503
505
504
506
505
- template <typename color_type>
507
+ template <typename color_type, bool input_has_alpha >
506
508
struct type_mapping
507
509
{
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 <
509
533
is_grayscale_v<color_type>,
510
534
agg::blender_gray<color_type>,
511
535
std::conditional_t <
@@ -514,25 +538,37 @@ struct type_mapping
514
538
agg::blender_rgba_plain<color_type, agg::order_rgba>
515
539
>
516
540
>;
517
- using pixfmt_type = std::conditional_t <
541
+ using output_pixfmt_type = std::conditional_t <
518
542
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>
521
545
>;
522
546
template <typename A>using span_gen_affine_type = std::conditional_t <
523
547
is_grayscale_v<color_type>,
524
548
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
+ >
526
554
>;
527
555
template <typename A,typename B>using span_gen_filter_type = std::conditional_t <
528
556
is_grayscale_v<color_type>,
529
557
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
+ >
531
563
>;
532
564
template <typename A,typename B>using span_gen_nn_type = std::conditional_t <
533
565
is_grayscale_v<color_type>,
534
566
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
+ >
536
572
>;
537
573
};
538
574
@@ -686,16 +722,16 @@ static void get_filter(const resample_params_t ¶ms,
686
722
}
687
723
688
724
689
- template <typename color_type>
725
+ template <typename color_type, bool input_has_alpha = true >
690
726
void resample (
691
727
const void *input,int in_width,int in_height,
692
728
void *output,int out_width,int out_height,
693
729
resample_params_t ¶ms)
694
730
{
695
- using type_mapping_t = type_mapping<color_type>;
731
+ using type_mapping_t = type_mapping<color_type, input_has_alpha >;
696
732
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 ;
699
735
700
736
using renderer_t = agg::renderer_base<output_pixfmt_t >;
701
737
using rasterizer_t = agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl>;
@@ -711,9 +747,16 @@ void resample(
711
747
using arbitrary_interpolator_t =
712
748
agg::span_interpolator_adaptor<agg::span_interpolator_linear<>, lookup_distortion>;
713
749
714
- size_t itemsize =sizeof (color_type);
750
+ size_t in_itemsize =sizeof (color_type);
751
+ size_t out_itemsize =sizeof (color_type);
715
752
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);
717
760
}
718
761
719
762
if (params.interpolation != NEAREST &&
@@ -733,13 +776,13 @@ void resample(
733
776
734
777
agg::rendering_buffer input_buffer;
735
778
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 );
737
780
input_pixfmt_t input_pixfmt (input_buffer);
738
781
image_accessor_t input_accessor (input_pixfmt);
739
782
740
783
agg::rendering_buffer output_buffer;
741
784
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 );
743
786
output_pixfmt_t output_pixfmt (output_buffer);
744
787
renderer_t renderer (output_pixfmt);
745
788