Commit 27d93cc9 authored by twanvl's avatar twanvl

New image functions:

 * invert
 * flip_horizontal
 * flip_vertical
 * rotate
parent 3db9aecd
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(<img src="image_logo.png" alt='"image_logo.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />) == <img src="image_logo_hflip.png" alt='"image_logo_hflip.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />
--See also--
| [[fun:flip_vertical]] Flip an image vertically
| [[fun:rotate]] Rotate an image
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(<img src="image_logo.png" alt='"image_logo.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />) == <img src="image_logo_vflip.png" alt='"image_logo_vflip.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />
--See also--
| [[fun:flip_horizontal]] Flip an image horizontally
| [[fun:rotate]] Rotate an image
......@@ -83,8 +83,12 @@ These functions are built into the program, other [[type:function]]s can be defi
| [[fun:set_alpha]] Change the transparency of an image.
| [[fun:set_combine]] Change how the image should be combined with the background.
| [[fun:saturate]] Saturate/desaturate an image.
| [[fun:invert]] Invert the colors of an image.
| [[fun:enlarge]] Enlarge an image by putting a border around it.
| [[fun:crop]] Crop an image, giving only a small subset of it.
| [[fun:flip_horizontal]] Flip an image horizontally.
| [[fun:flip_vertical]] Flip an image vertically.
| [[fun:rotate]] Rotate an image.
| [[fun:drop_shadow]] Add a drop shadow to an image.
| [[fun:symbol_variation]] Render a variation of a [[type:symbol]].
| [[fun:built_in_image]] Return an image built into the program.
......
Function: invert
--Usage--
> 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(<img src="image_logo.png" alt='"image_logo.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />) == <img src="image_logo_invert.png" alt='"image_logo_invert.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />
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(<img src="image_logo.png" alt='"image_logo.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />, angle:30) == <img src="image_logo_rotate30.png" alt='"image_logo_rotate30.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />
--See also--
| [[fun:flip_horizontal]] Flip an image horizontally
| [[fun:flip_vertical]] Flip an image vertically
......@@ -19,3 +19,5 @@ To desaturate use an amount between @0@ (no desaturation) and @-1@ (convert to g
>>> saturate(<img src="image5.png" alt='"image5.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />, amount: 0.5) == <img src="image_saturate1.png" alt='"image_saturate1.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />
> saturate("image5.png", amount: -0.5) == [[Image]]
>>> saturate(<img src="image5.png" alt='"image5.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />, amount: -0.5) == <img src="image_saturate2.png" alt='"image_saturate2.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />
> saturate("image_logo.png", amount: -1) == [[Image]]
>>> saturate(<img src="image_logo.png" alt='"image_logo.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />, amount: -1) == <img src="image_logo_desaturate.png" alt='"image_logo_desaturate.png"' style="border:1px solid black;vertical-align:middle;margin:1px;" />
......@@ -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
......
......@@ -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);
......
......@@ -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<const InvertImage*>(&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<const FlipImageHorizontal*>(&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<const FlipImageVertical*>(&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<const RotateImage*>(&that);
return that2 && *image == *that2->image
&& angle == that2->angle;
}
// ----------------------------------------------------------------------------- : EnlargeImage
Image EnlargeImage::generate(const Options& opt) const {
......
......@@ -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
......
......@@ -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
......
......@@ -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];
}
}
......@@ -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<Rotate90> (image);
case 180: return rotate_image_impl<Rotate180>(image);
case 270: return rotate_image_impl<Rotate270>(image);
default:
if (!image.HasAlpha()) const_cast<Image&>(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<Rotate90> (image);
if (almost_equal(a,180)) return rotate_image_impl<Rotate180>(image);
if (almost_equal(a,270)) return rotate_image_impl<Rotate270>(image);
else {
if (!image.HasAlpha()) const_cast<Image&>(image).InitAlpha();
return image.Rotate(angle * M_PI / 180, wxPoint(0,0));
}
}
// ----------------------------------------------------------------------------- : 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;
}
}
/*Bitmap rotate_bitmap(const Bitmap& bitmap, int angle) {
switch (angle % 360) {
case 90:
case 180:
case 270:
default: return bitmap;
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;
}
*/
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment