diff --git a/src/gfx/generated_image.cpp b/src/gfx/generated_image.cpp index b7a33528..1efbac25 100644 --- a/src/gfx/generated_image.cpp +++ b/src/gfx/generated_image.cpp @@ -228,9 +228,6 @@ Image EnlargeImage::generate(const Options& opt) const { // done return larger; } -ImageCombine EnlargeImage::combine() const { - return image->combine(); -} bool EnlargeImage::operator == (const GeneratedImage& that) const { const EnlargeImage* that2 = dynamic_cast(&that); return that2 && *image == *that2->image @@ -242,9 +239,6 @@ bool EnlargeImage::operator == (const GeneratedImage& that) const { Image CropImage::generate(const Options& opt) const { return image->generate(opt).Size(wxSize((int)width, (int)height), wxPoint(-(int)offset_x, -(int)offset_y)); } -ImageCombine CropImage::combine() const { - return image->combine(); -} bool CropImage::operator == (const GeneratedImage& that) const { const CropImage* that2 = dynamic_cast(&that); return that2 && *image == *that2->image @@ -340,9 +334,6 @@ Image DropShadowImage::generate(const Options& opt) const { delete[] shadow; return img; } -ImageCombine DropShadowImage::combine() const { - return image->combine(); -} bool DropShadowImage::operator == (const GeneratedImage& that) const { const DropShadowImage* that2 = dynamic_cast(&that); return that2 && *image == *that2->image diff --git a/src/gfx/generated_image.hpp b/src/gfx/generated_image.hpp index 18ad3b51..c2f9aa8b 100644 --- a/src/gfx/generated_image.hpp +++ b/src/gfx/generated_image.hpp @@ -199,41 +199,34 @@ class SaturateImage : public SimpleFilterImage { virtual Image generate(const Options& opt) const; virtual bool operator == (const GeneratedImage& that) const; private: - GeneratedImageP image; double amount; }; // ----------------------------------------------------------------------------- : EnlargeImage /// Enlarge an image by adding a border around it -class EnlargeImage : public GeneratedImage { +class EnlargeImage : public SimpleFilterImage { public: inline EnlargeImage(const GeneratedImageP& image, double border_size) - : image(image), border_size(fabs(border_size)) + : SimpleFilterImage(image), border_size(fabs(border_size)) {} virtual Image generate(const Options& opt) const; - virtual ImageCombine combine() const; virtual bool operator == (const GeneratedImage& that) const; - virtual bool local() const { return image->local(); } private: - GeneratedImageP image; double border_size; }; // ----------------------------------------------------------------------------- : CropImage /// Crop an image at a certain point, to a certain size -class CropImage : public GeneratedImage { +class CropImage : public SimpleFilterImage { public: inline CropImage(const GeneratedImageP& image, double width, double height, double offset_x, double offset_y) - : image(image), width(width), height(height), offset_x(offset_x), offset_y(offset_y) + : SimpleFilterImage(image), width(width), height(height), offset_x(offset_x), offset_y(offset_y) {} virtual Image generate(const Options& opt) const; - virtual ImageCombine combine() const; virtual bool operator == (const GeneratedImage& that) const; - virtual bool local() const { return image->local(); } private: - GeneratedImageP image; double width, height; double offset_x, offset_y; }; @@ -241,18 +234,15 @@ class CropImage : public GeneratedImage { // ----------------------------------------------------------------------------- : DropShadowImage /// Add a drop shadow to an image -class DropShadowImage : public GeneratedImage { +class DropShadowImage : public SimpleFilterImage { public: inline DropShadowImage(const GeneratedImageP& image, double offset_x, double offset_y, double shadow_alpha, double shadow_blur_radius, Color shadow_color) - : image(image), offset_x(offset_x), offset_y(offset_y) + : SimpleFilterImage(image), offset_x(offset_x), offset_y(offset_y) , shadow_alpha(shadow_alpha), shadow_blur_radius(shadow_blur_radius), shadow_color(shadow_color) {} virtual Image generate(const Options& opt) const; - virtual ImageCombine combine() const; virtual bool operator == (const GeneratedImage& that) const; - virtual bool local() const { return image->local(); } private: - GeneratedImageP image; double offset_x, offset_y; double shadow_alpha; double shadow_blur_radius; diff --git a/src/gfx/image_effects.cpp b/src/gfx/image_effects.cpp index 276e6c01..eebdf94d 100644 --- a/src/gfx/image_effects.cpp +++ b/src/gfx/image_effects.cpp @@ -13,13 +13,32 @@ // ----------------------------------------------------------------------------- : Saturation void saturate(Image& image, double amount) { - if (amount == 0) return; // nothing to do Byte* pix = image.GetData(); Byte* end = pix + image.GetWidth() * image.GetHeight() * 3; - if (amount > 0) { - amount = min(amount,0.99); - int factor = int(256 * amount); - int div = 768 - 3 * factor; + // the formula for saturation is + // rgb' = (rgb - amount * avg) / (1 - amount) + // if amount >= 1 then this is some kind of inversion + // if amount > 0 then use formula directly + // if amount < 0 then de-saturate instead: + // rgb = rgb' + -amount*avg - -amount*rgb' + // = rgb' * (1 - -amount) + -amount*avg + // if amount < -1 then we are left with just the average + int factor = int(256 * amount); + if (factor == 0) { + return; // nothing to do + } else if (factor == 256) { + // super crazy saturation: division by zero + // if we take infty to be 255, then it is a >avg test + while (pix != end) { + int r = pix[0], g = pix[1], b = pix[2]; + pix[0] = r+r > g+b ? 255 : 0; + pix[1] = g+g > b+r ? 255 : 0; + pix[2] = b+b > r+g ? 255 : 0; + pix += 3; + } + } else if (factor > 0) { + int div = 768 - 3 * factor; + assert(div > 0); while (pix != end) { int r = pix[0], g = pix[1], b = pix[2]; int avg = factor*(r+g+b); @@ -28,14 +47,8 @@ void saturate(Image& image, double amount) { pix[2] = col((768*b - avg) / div); pix += 3; } - } else if (amount < -0.99) { - while (pix != end) { - int r = pix[0], g = pix[1], b = pix[2]; - pix[0] = pix[1] = pix[2] = (r+g+b)/3; - pix += 3; - } } else { - int factor1 = int(256 * -amount); + int factor1 = -factor; int factor2 = 768 - 3*factor1; while (pix != end) { int r = pix[0], g = pix[1], b = pix[2];