From ca0e762b642674f631ef4275c29b1933d1cd30ef Mon Sep 17 00:00:00 2001 From: twanvl Date: Tue, 3 Aug 2010 14:56:45 +0000 Subject: [PATCH] New image functions: * invert * flip_horizontal * flip_vertical * rotate git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1472 0fc631ac-6414-0410-93d0-97cfa31319b6 --- doc/function/flip_horizontal.txt | 18 +++++++ doc/function/flip_vertical.txt | 18 +++++++ doc/function/image_logo.png | Bin 0 -> 4944 bytes doc/function/image_logo_desaturate.png | Bin 0 -> 4789 bytes doc/function/image_logo_hflip.png | Bin 0 -> 4894 bytes doc/function/image_logo_invert.png | Bin 0 -> 4959 bytes doc/function/image_logo_rotate30.png | Bin 0 -> 15198 bytes doc/function/image_logo_vflip.png | Bin 0 -> 4851 bytes doc/function/index.txt | 4 ++ doc/function/invert.txt | 14 ++++++ doc/function/rotate.txt | 19 +++++++ doc/function/saturate.txt | 2 + src/data/field/color.cpp | 9 +++- src/gfx/color.hpp | 22 +++++++++ src/gfx/generated_image.cpp | 42 ++++++++++++++++ src/gfx/generated_image.hpp | 46 +++++++++++++++++ src/gfx/gfx.hpp | 11 ++++- src/gfx/image_effects.cpp | 10 ++++ src/gfx/rotate_image.cpp | 66 +++++++++++++++++++------ src/script/functions/image.cpp | 25 ++++++++++ 20 files changed, 286 insertions(+), 20 deletions(-) create mode 100644 doc/function/flip_horizontal.txt create mode 100644 doc/function/flip_vertical.txt create mode 100644 doc/function/image_logo.png create mode 100644 doc/function/image_logo_desaturate.png create mode 100644 doc/function/image_logo_hflip.png create mode 100644 doc/function/image_logo_invert.png create mode 100644 doc/function/image_logo_rotate30.png create mode 100644 doc/function/image_logo_vflip.png create mode 100644 doc/function/invert.txt create mode 100644 doc/function/rotate.txt diff --git a/doc/function/flip_horizontal.txt b/doc/function/flip_horizontal.txt new file mode 100644 index 00000000..c3af2872 --- /dev/null +++ b/doc/function/flip_horizontal.txt @@ -0,0 +1,18 @@ +Function: flip_horizontal + +--Usage-- +> flip_horizontal(input: image) + +Flip an image horizontally. + +--Parameters-- +! Parameter Type Description +| @input@ [[type:image]] Image to flip. + +--Examples-- +> flip_horizontal("image_logo.png") == [[Image]] +>>> flip_horizontal("image_logo.png") == "image_logo_hflip.png" + +--See also-- +| [[fun:flip_vertical]] Flip an image vertically +| [[fun:rotate]] Rotate an image diff --git a/doc/function/flip_vertical.txt b/doc/function/flip_vertical.txt new file mode 100644 index 00000000..19c7b3d1 --- /dev/null +++ b/doc/function/flip_vertical.txt @@ -0,0 +1,18 @@ +Function: flip_vertical + +--Usage-- +> flip_vertical(input: image) + +Flip an image vertically. + +--Parameters-- +! Parameter Type Description +| @input@ [[type:image]] Image to flip. + +--Examples-- +> flip_vertical("image_logo.png") == [[Image]] +>>> flip_vertical("image_logo.png") == "image_logo_vflip.png" + +--See also-- +| [[fun:flip_horizontal]] Flip an image horizontally +| [[fun:rotate]] Rotate an image diff --git a/doc/function/image_logo.png b/doc/function/image_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c64c192b0b8b66c2ed771feedd236a666127ecd5 GIT binary patch literal 4944 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 P00000NkvXXu0mjf|C`FZ literal 0 HcmV?d00001 diff --git a/doc/function/image_logo_hflip.png b/doc/function/image_logo_hflip.png new file mode 100644 index 0000000000000000000000000000000000000000..4e0ded3dc0575f0ba527ed7dd8077ad40a7214b8 GIT binary patch literal 4894 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 Q#Q*>R07*qoM6N<$f>WOjS^xk5 literal 0 HcmV?d00001 diff --git a/doc/function/image_logo_invert.png b/doc/function/image_logo_invert.png new file mode 100644 index 0000000000000000000000000000000000000000..39e19dddfd978d1bfdf1e7f4ccc37ddd28fc453b GIT binary patch literal 4959 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 literal 0 HcmV?d00001 diff --git a/doc/function/image_logo_vflip.png b/doc/function/image_logo_vflip.png new file mode 100644 index 0000000000000000000000000000000000000000..6f459f641a5562e23ac7f2e32f1f86590615b034 GIT binary patch literal 4851 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 invert(input: image) + +Invert the colors in an image. + +--Parameters-- +! Parameter Type Description +| @input@ [[type:image]] Image to invert. + +--Examples-- +> invert("image_logo.png") == [[Image]] +>>> invert("image_logo.png") == "image_logo_invert.png" diff --git a/doc/function/rotate.txt b/doc/function/rotate.txt new file mode 100644 index 00000000..3519dce1 --- /dev/null +++ b/doc/function/rotate.txt @@ -0,0 +1,19 @@ +Function: flip_vertical + +--Usage-- +> rotate(input: image, angle: some_number) + +Rotate an image. The image can become larger to accomodate the rotated bounding box. + +--Parameters-- +! Parameter Type Description +| @input@ [[type:image]] Image to rotate. +| @angle@ [[type:double]] Angle to rotate by, in degrees counter clockwise. + +--Examples-- +> rotate("image_logo.png", angle:30) == [[Image]] +>>> rotate("image_logo.png", angle:30) == "image_logo_rotate30.png" + +--See also-- +| [[fun:flip_horizontal]] Flip an image horizontally +| [[fun:flip_vertical]] Flip an image vertically diff --git a/doc/function/saturate.txt b/doc/function/saturate.txt index f9f9f9cf..44b0d904 100644 --- a/doc/function/saturate.txt +++ b/doc/function/saturate.txt @@ -19,3 +19,5 @@ To desaturate use an amount between @0@ (no desaturation) and @-1@ (convert to g >>> saturate("image5.png", amount: 0.5) == "image_saturate1.png" > saturate("image5.png", amount: -0.5) == [[Image]] >>> saturate("image5.png", amount: -0.5) == "image_saturate2.png" +> saturate("image_logo.png", amount: -1) == [[Image]] +>>> saturate("image_logo.png", amount: -1) == "image_logo_desaturate.png" diff --git a/src/data/field/color.cpp b/src/data/field/color.cpp index 1c7d0708..82f33804 100644 --- a/src/data/field/color.cpp +++ b/src/data/field/color.cpp @@ -41,8 +41,13 @@ IMPLEMENT_REFLECTION(ColorField) { // ----------------------------------------------------------------------------- : ColorField::Choice IMPLEMENT_REFLECTION(ColorField::Choice) { - REFLECT(name); - REFLECT(color); + if (tag.reading() && !tag.isComplex()) { + REFLECT_NAMELESS(name); + color = parse_color(name); + } else { + REFLECT(name); + REFLECT(color); + } } // ----------------------------------------------------------------------------- : ColorStyle diff --git a/src/gfx/color.hpp b/src/gfx/color.hpp index 9c6a383f..aff7a1f7 100644 --- a/src/gfx/color.hpp +++ b/src/gfx/color.hpp @@ -60,9 +60,31 @@ Color hsl2rgb(double h, double s, double l); /// A darker version of a color Color darken(const Color& c); +/// A black or white color, that contrasts with c +Color contrasting_color(const Color& c); + /// A saturated version of a color Color saturate(const Color& c, double amount); +/// Recolor: +/** + * Maps + * black -> black + * red -> cr + * green -> cg + * blue -> cb + * white -> cw + * + * Allows for interpolation between the colors, so for example + * rgb(128,128,128) -> 0.5*cw + * rgb(128,128,0) -> 0.5*cr + 0.5*cg + * rgb(128,0,0) -> 0.5*cr + */ +Color recolor(Color const& c, Color const& cr, Color const& cg, Color const& cb, Color const& cw); +Image recolor(Image const& im, Color const& cr, Color const& cg, Color const& cb, Color const& cw); +/// Like recolor: map green to similar black/white and blue to complementary white/black +Image recolor(Image const& im, Color const& cr); + /// Fills an image with the specified color void fill_image(Image& image, const Color& color); diff --git a/src/gfx/generated_image.cpp b/src/gfx/generated_image.cpp index 1efbac25..76de5902 100644 --- a/src/gfx/generated_image.cpp +++ b/src/gfx/generated_image.cpp @@ -196,6 +196,48 @@ bool SaturateImage::operator == (const GeneratedImage& that) const { && amount == that2->amount; } +// ----------------------------------------------------------------------------- : InvertImage + +Image InvertImage::generate(const Options& opt) const { + Image img = image->generate(opt); + invert(img); + return img; +} +bool InvertImage::operator == (const GeneratedImage& that) const { + const InvertImage* that2 = dynamic_cast(&that); + return that2 && *image == *that2->image; +} + +// ----------------------------------------------------------------------------- : FlipImage + +Image FlipImageHorizontal::generate(const Options& opt) const { + Image img = image->generate(opt); + return flip_image_horizontal(img); +} +bool FlipImageHorizontal::operator == (const GeneratedImage& that) const { + const FlipImageHorizontal* that2 = dynamic_cast(&that); + return that2 && *image == *that2->image; +} + +Image FlipImageVertical::generate(const Options& opt) const { + Image img = image->generate(opt); + return flip_image_vertical(img); +} +bool FlipImageVertical::operator == (const GeneratedImage& that) const { + const FlipImageVertical* that2 = dynamic_cast(&that); + return that2 && *image == *that2->image; +} + +Image RotateImage::generate(const Options& opt) const { + Image img = image->generate(opt); + return rotate_image(img,angle); +} +bool RotateImage::operator == (const GeneratedImage& that) const { + const RotateImage* that2 = dynamic_cast(&that); + return that2 && *image == *that2->image + && angle == that2->angle; +} + // ----------------------------------------------------------------------------- : EnlargeImage Image EnlargeImage::generate(const Options& opt) const { diff --git a/src/gfx/generated_image.hpp b/src/gfx/generated_image.hpp index c2f9aa8b..a97645f0 100644 --- a/src/gfx/generated_image.hpp +++ b/src/gfx/generated_image.hpp @@ -202,6 +202,52 @@ class SaturateImage : public SimpleFilterImage { double amount; }; +// ----------------------------------------------------------------------------- : InvertImage + +/// Invert an image +class InvertImage : public SimpleFilterImage { + public: + inline InvertImage(const GeneratedImageP& image) + : SimpleFilterImage(image) + {} + virtual Image generate(const Options& opt) const; + virtual bool operator == (const GeneratedImage& that) const; +}; + +// ----------------------------------------------------------------------------- : FlipImage + +/// Flip an image horizontally +class FlipImageHorizontal : public SimpleFilterImage { + public: + inline FlipImageHorizontal(const GeneratedImageP& image) + : SimpleFilterImage(image) + {} + virtual Image generate(const Options& opt) const; + virtual bool operator == (const GeneratedImage& that) const; +}; + +/// Flip an image vertically +class FlipImageVertical : public SimpleFilterImage { + public: + inline FlipImageVertical(const GeneratedImageP& image) + : SimpleFilterImage(image) + {} + virtual Image generate(const Options& opt) const; + virtual bool operator == (const GeneratedImage& that) const; +}; + +/// Rotate an image +class RotateImage : public SimpleFilterImage { + public: + inline RotateImage(const GeneratedImageP& image, double angle) + : SimpleFilterImage(image), angle(angle) + {} + virtual Image generate(const Options& opt) const; + virtual bool operator == (const GeneratedImage& that) const; + private: + double angle; +}; + // ----------------------------------------------------------------------------- : EnlargeImage /// Enlarge an image by adding a border around it diff --git a/src/gfx/gfx.hpp b/src/gfx/gfx.hpp index 077f67e3..7ca61043 100644 --- a/src/gfx/gfx.hpp +++ b/src/gfx/gfx.hpp @@ -74,8 +74,12 @@ inline double rad_to_deg(double rad) { return rad * (180.0 / M_PI); } inline double deg_to_rad(double deg) { return deg * (M_PI / 180.0); } /// Rotates an image counter clockwise -/// angle must be a multiple of 90, i.e. {0,90,180,270} -Image rotate_image(const Image& image, int angle); +Image rotate_image(const Image& image, double angle); + +/// Flip an image horizontally +Image flip_image_horizontal(const Image& image); +/// Flip an image vertically +Image flip_image_vertical(const Image& image); // ----------------------------------------------------------------------------- : Blending @@ -98,6 +102,9 @@ void mask_blend(Image& img1, const Image& img2, const Image& mask); /// Saturate an image void saturate(Image& image, double amount); +/// Invert the colors in an image +void invert(Image& img); + // ----------------------------------------------------------------------------- : Combining /// Ways in which images can be combined, similair to what Photoshop supports diff --git a/src/gfx/image_effects.cpp b/src/gfx/image_effects.cpp index eebdf94d..0a6d4896 100644 --- a/src/gfx/image_effects.cpp +++ b/src/gfx/image_effects.cpp @@ -60,3 +60,13 @@ void saturate(Image& image, double amount) { } } } + +// ----------------------------------------------------------------------------- : Color inversion + +void invert(Image& img) { + Byte* data = img.GetData(); + int n = 3 * img.GetWidth() * img.GetHeight(); + for (int i = 0 ; i < n ; ++i) { + data[i] = 255 - data[i]; + } +} diff --git a/src/gfx/rotate_image.cpp b/src/gfx/rotate_image.cpp index e659bb37..76bfd590 100644 --- a/src/gfx/rotate_image.cpp +++ b/src/gfx/rotate_image.cpp @@ -83,24 +83,58 @@ struct Rotate270 { // ----------------------------------------------------------------------------- : Interface -Image rotate_image(const Image& image, int angle) { - switch (angle % 360) { - case 0: return image; - case 90: return rotate_image_impl (image); - case 180: return rotate_image_impl(image); - case 270: return rotate_image_impl(image); - default: - if (!image.HasAlpha()) const_cast(image).InitAlpha(); - return image.Rotate(angle * M_PI / 180, wxPoint(0,0)); +double almost_equal(double x, double y) { + return fabs(x-y) < 1e-6; +} + +Image rotate_image(const Image& image, double angle) { + double a = fmod(angle, 360); + if (almost_equal(a, 0)) return image; + if (almost_equal(a, 90)) return rotate_image_impl (image); + if (almost_equal(a,180)) return rotate_image_impl(image); + if (almost_equal(a,270)) return rotate_image_impl(image); + else { + if (!image.HasAlpha()) const_cast(image).InitAlpha(); + return image.Rotate(angle * M_PI / 180, wxPoint(0,0)); } } -/*Bitmap rotate_bitmap(const Bitmap& bitmap, int angle) { - switch (angle % 360) { - case 90: - case 180: - case 270: - default: return bitmap; + +// ----------------------------------------------------------------------------- : Flipping images + +// reverse a list of n chunks of size 'step' +void do_flip(Byte const* in, Byte* out, int step, int n) { + for (int i = 0, j = n-1 ; i < n ; ++i, --j) { + memcpy(&out[i*step], &in[j*step], step); } } -*/ +void do_flip(Byte const* in, Byte* out, int step1, int n1, int n2) { + int step2 = step1 * n1; + for (int i = 0 ; i < n2 ; ++i) { + do_flip(in,out,step1,n1); + in += step2; + out += step2; + } +} + +Image flip_image_horizontal(Image const& img) { + int w = img.GetWidth(), h= img.GetHeight(); + Image out(w,h,false); + do_flip(img.GetData(), out.GetData(), 3, w, h); + if (img.HasAlpha()) { + out.InitAlpha(); + do_flip(img.GetAlpha(), out.GetAlpha(), 1, w, h); + } + return out; +} + +Image flip_image_vertical(Image const& img) { + int w = img.GetWidth(), h= img.GetHeight(); + Image out(w,h,false); + do_flip(img.GetData(), out.GetData(), 3 * w, h); + if (img.HasAlpha()) { + out.InitAlpha(); + do_flip(img.GetAlpha(), out.GetAlpha(), 1 * w, h); + } + return out; +} diff --git a/src/script/functions/image.cpp b/src/script/functions/image.cpp index 09590ee0..bd93c26f 100644 --- a/src/script/functions/image.cpp +++ b/src/script/functions/image.cpp @@ -86,6 +86,11 @@ SCRIPT_FUNCTION(saturate) { return intrusive(new SaturateImage(input, amount)); } +SCRIPT_FUNCTION(invert_image) { + SCRIPT_PARAM_C(GeneratedImageP, input); + return intrusive(new InvertImage(input)); +} + SCRIPT_FUNCTION(enlarge) { SCRIPT_PARAM_C(GeneratedImageP, input); SCRIPT_PARAM_N(double, _("border size"), border_size); @@ -101,6 +106,22 @@ SCRIPT_FUNCTION(crop) { return intrusive(new CropImage(input, width, height, offset_x, offset_y)); } +SCRIPT_FUNCTION(flip_horizontal) { + SCRIPT_PARAM_C(GeneratedImageP, input); + return intrusive(new FlipImageHorizontal(input)); +} + +SCRIPT_FUNCTION(flip_vertical) { + SCRIPT_PARAM_C(GeneratedImageP, input); + return intrusive(new FlipImageVertical(input)); +} + +SCRIPT_FUNCTION(rotate) { + SCRIPT_PARAM_C(GeneratedImageP, input); + SCRIPT_PARAM_N(double, _("angle"), angle); + return intrusive(new RotateImage(input,angle)); +} + SCRIPT_FUNCTION(drop_shadow) { SCRIPT_PARAM_C(GeneratedImageP, input); SCRIPT_OPTIONAL_PARAM_N_(double, _("offset x"), offset_x); @@ -190,8 +211,12 @@ void init_script_image_functions(Context& ctx) { ctx.setVariable(_("set alpha"), script_set_alpha); ctx.setVariable(_("set combine"), script_set_combine); ctx.setVariable(_("saturate"), script_saturate); + ctx.setVariable(_("invert image"), script_invert_image); ctx.setVariable(_("enlarge"), script_enlarge); ctx.setVariable(_("crop"), script_crop); + ctx.setVariable(_("flip horizontal"), script_flip_horizontal); + ctx.setVariable(_("flip vertical"), script_flip_vertical); + ctx.setVariable(_("rotate"), script_rotate); ctx.setVariable(_("drop shadow"), script_drop_shadow); ctx.setVariable(_("symbol variation"), script_symbol_variation); ctx.setVariable(_("built in image"), script_built_in_image);