]> git.sesse.net Git - movit/blobdiff - main.cpp
Move the Effect class out into its own file.
[movit] / main.cpp
index 974fe53998c5ad5198919cd26acd67fdba8b58da..84837395879a43f10f4a897f772846d3e757966a 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -5,11 +5,14 @@
 #define HEIGHT 720
 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
 
+#include <string.h>
 #include <math.h>
 #include <time.h>
+#include <assert.h>
 
 #include <string>
 #include <vector>
+#include <map>
 
 #include <SDL/SDL.h>
 #include <SDL/SDL_opengl.h>
@@ -18,6 +21,7 @@
 #include <GL/gl.h>
 #include <GL/glext.h>
 
+#include "effect.h"
 #include "util.h"
 #include "widgets.h"
 #include "texture_enum.h"
@@ -33,14 +37,26 @@ float lift_r = 0.0f, lift_g = 0.0f, lift_b = 0.0f;
 float gamma_r = 1.0f, gamma_g = 1.0f, gamma_b = 1.0f;
 float gain_r = 1.0f, gain_g = 1.0f, gain_b = 1.0f;
 
-struct ImageFormat {
-       enum { FORMAT_RGB, FORMAT_RGBA } format;
+enum PixelFormat { FORMAT_RGB, FORMAT_RGBA };
+
+enum ColorSpace {
+       COLORSPACE_sRGB = 0,
+       COLORSPACE_REC_709 = 0,  // Same as sRGB.
+       COLORSPACE_REC_601_525 = 1,
+       COLORSPACE_REC_601_625 = 2,
+};
 
-       // Note: sRGB and 709 use the same colorspace primaries.
-       enum { COLORSPACE_sRGB, COLORSPACE_REC_601_525, COLORSPACE_REC_601_625, COLORSPACE_REC_709 } color_space;
+enum GammaCurve {
+       GAMMA_LINEAR = 0,
+       GAMMA_sRGB = 1,
+       GAMMA_REC_601 = 2,
+       GAMMA_REC_709 = 2,  // Same as Rec. 601.
+};
 
-       // Note: Rec. 601 and 709 use the same gamma curve.
-       enum { LINEAR_LIGHT, GAMMA_sRGB, GAMMA_REC_601, GAMMA_REC_709 } gamma_curve;
+struct ImageFormat {
+       PixelFormat pixel_format;
+       ColorSpace color_space;
+       GammaCurve gamma_curve;
 };
 
 enum EffectId {
@@ -52,25 +68,69 @@ enum EffectId {
        LIFT_GAMMA_GAIN,
 };
 
-class Effect {
-public: 
-       virtual bool needs_linear_light() { return true; }
-       virtual bool needs_srgb_primaries() { return true; }
-       virtual bool needs_many_samples() { return false; }
-       virtual bool needs_mipmaps() { return false; }
-       bool set_float(const std::string& key, float value);
-       bool set_float_array(const std::string&, const float *values, size_t num_values);
+// Can alias on a float[3].
+struct RGBTriplet {
+       RGBTriplet(float r, float g, float b)
+               : r(r), g(g), b(b) {}
+
+       float r, g, b;
+};
+
+class GammaExpansionEffect : public Effect {
+public:
+       GammaExpansionEffect()
+               : source_curve(GAMMA_LINEAR)
+       {
+               register_int("source_curve", (int *)&source_curve);
+       }
+
+private:
+       GammaCurve source_curve;
+};
+
+class ColorSpaceConversionEffect : public Effect {
+public:
+       ColorSpaceConversionEffect()
+               : source_space(COLORSPACE_sRGB),
+                 destination_space(COLORSPACE_sRGB)
+       {
+               register_int("source_space", (int *)&source_space);
+               register_int("destination_space", (int *)&destination_space);
+       }
+
+private:
+       ColorSpace source_space, destination_space;
+};
+
+class ColorSpaceConversionEffect;
+
+class LiftGammaGainEffect : public Effect {
+public:
+       LiftGammaGainEffect()
+               : lift(0.0f, 0.0f, 0.0f),
+                 gamma(1.0f, 1.0f, 1.0f),
+                 gain(1.0f, 1.0f, 1.0f),
+                 saturation(1.0f)
+       {
+               register_vec3("lift", (float *)&lift);
+               register_vec3("gamma", (float *)&gamma);
+               register_vec3("gain", (float *)&gain);
+               register_float("saturation", &saturation);
+       }
 
 private:
-       bool register_float(const std::string& key, float value);
-       bool register_float_array(const std::string& key, float *values, size_t num_values);
-};      
+       RGBTriplet lift, gamma, gain;
+       float saturation;
+};
 
 class EffectChain {
 public:
-       void set_size(unsigned width, unsigned height);
+       EffectChain(unsigned width, unsigned height);
        void add_input(const ImageFormat &format);
+
+       // The pointer is owned by EffectChain.
        Effect *add_effect(EffectId effect);
+
        void add_output(const ImageFormat &format);
 
        void render(unsigned char *src, unsigned char *dst);
@@ -79,8 +139,63 @@ private:
        unsigned width, height;
        ImageFormat input_format, output_format;
        std::vector<Effect *> effects;
+
+       ColorSpace current_color_space;
+       GammaCurve current_gamma_curve; 
 };
 
+EffectChain::EffectChain(unsigned width, unsigned height)
+       : width(width), height(height) {}
+
+void EffectChain::add_input(const ImageFormat &format)
+{
+       input_format = format;
+       current_color_space = format.color_space;
+       current_gamma_curve = format.gamma_curve;
+}
+
+void EffectChain::add_output(const ImageFormat &format)
+{
+       output_format = format;
+}
+       
+Effect *instantiate_effect(EffectId effect)
+{
+       switch (effect) {
+       case GAMMA_CONVERSION:
+               return new GammaExpansionEffect();
+       case RGB_PRIMARIES_CONVERSION:
+               return new GammaExpansionEffect();
+       case LIFT_GAMMA_GAIN:
+               return new LiftGammaGainEffect();
+       }
+       assert(false);
+}
+
+Effect *EffectChain::add_effect(EffectId effect_id)
+{
+       Effect *effect = instantiate_effect(effect_id);
+
+       if (effect->needs_linear_light() && current_gamma_curve != GAMMA_LINEAR) {
+               GammaExpansionEffect *gamma_conversion = new GammaExpansionEffect();
+               gamma_conversion->set_int("source_curve", current_gamma_curve);
+               effects.push_back(gamma_conversion);
+               current_gamma_curve = GAMMA_LINEAR;
+       }
+
+       if (effect->needs_srgb_primaries() && current_color_space != COLORSPACE_sRGB) {
+               assert(current_gamma_curve == GAMMA_LINEAR);
+               ColorSpaceConversionEffect *colorspace_conversion = new ColorSpaceConversionEffect();
+               colorspace_conversion->set_int("source_space", current_color_space);
+               colorspace_conversion->set_int("destination_space", COLORSPACE_sRGB);
+               effects.push_back(colorspace_conversion);
+               current_color_space = COLORSPACE_sRGB;
+       }
+
+       effects.push_back(effect);
+       return effect;
+}
+
 GLhandleARB read_shader(const char* filename, GLenum type)
 {
        static char buf[131072];