Implement wrapping of the resampling parameter texture.
[movit] / resample_effect.h
1 #ifndef _RESAMPLE_EFFECT_H
2 #define _RESAMPLE_EFFECT_H 1
3
4 // High-quality image resizing, either up or down.
5 //
6 // The default scaling offered by the GPU (and as used in ResizeEffect)
7 // is bilinear (optionally mipmapped), which is not the highest-quality
8 // choice, especially for upscaling. ResampleEffect offers the three-lobed
9 // Lanczos kernel, which is among the most popular choices in image
10 // processing. While it does have its weaknesses, in particular a certain
11 // ringing/sharpening effect with artifacts that accumulate over several
12 // consecutive resizings, it is generally regarded as the best tradeoff.
13 //
14 // Works in two passes; first horizontal, then vertical (ResampleEffect,
15 // which is what the user is intended to use, instantiates two copies of
16 // SingleResamplePassEffect behind the scenes).
17
18 #include "effect.h"
19
20 class SingleResamplePassEffect;
21
22 class ResampleEffect : public Effect {
23 public:
24         ResampleEffect();
25
26         virtual std::string effect_type_id() const { return "ResampleEffect"; }
27
28         // We want this for the same reason as ResizeEffect; we could end up scaling
29         // down quite a lot.
30         virtual bool needs_texture_bounce() const { return true; }
31         virtual bool needs_srgb_primaries() const { return false; }
32
33         virtual void inform_input_size(unsigned input_num, unsigned width, unsigned height);
34
35         virtual std::string output_fragment_shader() {
36                 assert(false);
37         }
38         virtual void set_gl_state(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num) {
39                 assert(false);
40         }
41
42         virtual void rewrite_graph(EffectChain *graph, Node *self);
43         virtual bool set_float(const std::string &key, float value);
44         
45 private:
46         void update_size();
47         
48         SingleResamplePassEffect *hpass, *vpass;
49         int input_width, input_height, output_width, output_height;
50 };
51
52 class SingleResamplePassEffect : public Effect {
53 public:
54         // If parent is non-NULL, calls to inform_input_size will be forwarded,
55         // so that it can inform both passes about the right input and output
56         // resolutions.
57         SingleResamplePassEffect(ResampleEffect *parent);
58         ~SingleResamplePassEffect();
59         virtual std::string effect_type_id() const { return "SingleResamplePassEffect"; }
60
61         std::string output_fragment_shader();
62
63         virtual bool needs_texture_bounce() const { return true; }
64         virtual bool needs_srgb_primaries() const { return false; }
65
66         virtual void inform_input_size(unsigned input_num, unsigned width, unsigned height) {
67                 if (parent != NULL) {
68                         parent->inform_input_size(input_num, width, height);
69                 }
70         }
71         virtual bool changes_output_size() const { return true; }
72
73         virtual void get_output_size(unsigned *width, unsigned *height) const {
74                 *width = this->output_width;
75                 *height = this->output_height;
76         }
77
78         void set_gl_state(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num);
79         
80         enum Direction { HORIZONTAL = 0, VERTICAL = 1 };
81
82 private:
83         void update_texture(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num);
84
85         ResampleEffect *parent;
86         Direction direction;
87         GLuint texnum;
88         int input_width, input_height, output_width, output_height;
89         int last_input_width, last_input_height, last_output_width, last_output_height;
90         int src_samples, num_loops;
91         float slice_height;
92 };
93
94 #endif // !defined(_RESAMPLE_EFFECT_H)