diff --git a/doc/function/add_drop_shadow.txt b/doc/function/add_drop_shadow.txt new file mode 100644 index 00000000..c90a9c2e --- /dev/null +++ b/doc/function/add_drop_shadow.txt @@ -0,0 +1,28 @@ +Function: add_drop_shadow + +--Usage-- +> add_drop_shadow(image, offset_x: offset, offset_y: offset) + +Add a drop shadow to an image. + +The shadow is based on the opacity of the image. + +To make sure the shadow doesn't fall outside the image, it can be a good idea to [[fun:enlarge]] the image first. + +--Parameters-- +! Parameter Type Default Description +| @input@ [[type:image]] Image to add drop shadow to +| @offset_x@ [[type:double]] 0 Relative position of the shadow, a positive number moves the shadow to the left.
+ Value is in the range 0 (no movement) to 1 (move by the width of the image) +| @offset_y@ [[type:double]] 0 Relative position of the shadow, a positive number moves the shadow down.
+ Value is in the range 0 (no movement) to 1 (move by the height of the image) +| @blur_radius@ [[type:double]] 0 Amount to blur the shadow. +| @alpha@ [[type:double]] 0 Opacity of the shadow, in the range 0 (fully transparent) to 1 (fully opaque) +| @color@ [[type:color]] black Color of the shadow. + +--Examples-- +> add_drop_shadow("image4.png", offset_x: 0.08, offset_y: 0.08, alpha: 0.5) == [[Image]] +>>> add_drop_shadow("image1.png", offset_x: 0.08, offset_y: 0.08, alpha: 0.5) == "image_drop_shadow_1.png" + +> add_drop_shadow("image4.png", offset_x: -0.1, offset_y: 0.1, alpha: 1, color: rgb(0,0,255), blur_radius: 0.05) == [[Image]] +>>> add_drop_shadow("image1.png", offset_x: -0.1, offset_y: 0.1, alpha: 1, color: rgb(0,0,255), blur_radius: 0.05) == "image_drop_shadow_1.png" diff --git a/doc/function/crop.txt b/doc/function/crop_image.txt similarity index 79% rename from doc/function/crop.txt rename to doc/function/crop_image.txt index c537cb0a..8f290c41 100644 --- a/doc/function/crop.txt +++ b/doc/function/crop_image.txt @@ -1,17 +1,17 @@ -Function: crop - ---Usage-- -> crop(input: image, height: height_of_new_image, width: width_of_new_image, offset_x: x_position_to_start_crop, offset_y: y_position_to_start_crop) - -Shrink an image by cutting off some of the image, starting at the position denoted by the offsets. The resulting image size is specified in the parameters. - -Resulting image can be bigger than the original, if offset_x or offset_y are negative, or if width or height are bigger than the original width and height. - ---Parameters-- -! Parameter Type Description -| @input@ [[type:image]] Image to enlarge -| @height@ [[type:double]] Height of the resulting image, in pixels -| @width@ [[type:double]] Width of the resulting image, in pixels -| @offset_x@ [[type:double]] Offset of crop, horizontally, in pixels -| @offset_y@ [[type:double]] Offset of crop, vertically, in pixels - +Function: crop_image + +--Usage-- +> crop_image(input: image, height: height_of_new_image, width: width_of_new_image, offset_x: x_position_to_start_crop, offset_y: y_position_to_start_crop) + +Shrink an image by cutting off some of the image, starting at the position denoted by the offsets. The resulting image size is specified in the parameters. + +Resulting image can be bigger than the original, if offset_x or offset_y are negative, or if width or height are bigger than the original width and height. + +--Parameters-- +! Parameter Type Description +| @input@ [[type:image]] Image to enlarge +| @height@ [[type:double]] Height of the resulting image, in pixels +| @width@ [[type:double]] Width of the resulting image, in pixels +| @offset_x@ [[type:double]] Offset of crop, horizontally, in pixels +| @offset_y@ [[type:double]] Offset of crop, vertically, in pixels + diff --git a/doc/function/drop_shadow.txt b/doc/function/drop_shadow.txt deleted file mode 100644 index 2d8c942a..00000000 --- a/doc/function/drop_shadow.txt +++ /dev/null @@ -1,28 +0,0 @@ -Function: drop_shadow - ---Usage-- -> drop_shadow(image, offset_x: offset, offset_y: offset) - -Add a drop shadow to an image. - -The shadow is based on the opacity of the image. - -To make sure the shadow doesn't fall outside the image, it can be a good idea to [[fun:enlarge]] the image first. - ---Parameters-- -! Parameter Type Default Description -| @input@ [[type:image]] Image to add drop shadow to -| @offset_x@ [[type:double]] 0 Relative position of the shadow, a positive number moves the shadow to the left.
- Value is in the range 0 (no movement) to 1 (move by the width of the image) -| @offset_y@ [[type:double]] 0 Relative position of the shadow, a positive number moves the shadow down.
- Value is in the range 0 (no movement) to 1 (move by the height of the image) -| @blur_radius@ [[type:double]] 0 Amount to blur the shadow. -| @alpha@ [[type:double]] 0 Opacity of the shadow, in the range 0 (fully transparent) to 1 (fully opaque) -| @color@ [[type:color]] black Color of the shadow. - ---Examples-- -> drop_shadow("image4.png", offset_x: 0.08, offset_y: 0.08, alpha: 0.5) == [[Image]] ->>> drop_shadow("image1.png", offset_x: 0.08, offset_y: 0.08, alpha: 0.5) == "image_drop_shadow_1.png" - -> drop_shadow("image4.png", offset_x: -0.1, offset_y: 0.1, alpha: 1, color: rgb(0,0,255), blur_radius: 0.05) == [[Image]] ->>> drop_shadow("image1.png", offset_x: -0.1, offset_y: 0.1, alpha: 1, color: rgb(0,0,255), blur_radius: 0.05) == "image_drop_shadow_1.png" diff --git a/doc/function/enlarge.txt b/doc/function/enlarge.txt deleted file mode 100644 index c9353636..00000000 --- a/doc/function/enlarge.txt +++ /dev/null @@ -1,16 +0,0 @@ -Function: enlarge - ---Usage-- -> enlarge(input: image, border_size: amount_to_enlarge) - -Enlarge an image by putting a transparent border around it. -The border size is given in percentages of the image size, so @border_size: 1@ makes the image three times as large by putting a border of 100% the size on all sides. - ---Parameters-- -! Parameter Type Description -| @input@ [[type:image]] Image to enlarge -| @border_size@ [[type:double]] Amount of border to add, in percentage of the image - ---Examples-- -> enlarge(input: "image1.png", border_size: 0.1) == [[Image]] ->>> enlarge(input: "image1.png", border_size: 0.1) == "image_enlarge.png" diff --git a/doc/function/enlarge_image.txt b/doc/function/enlarge_image.txt new file mode 100644 index 00000000..62835e37 --- /dev/null +++ b/doc/function/enlarge_image.txt @@ -0,0 +1,16 @@ +Function: enlarge_image + +--Usage-- +> enlarge_image(input: image, border_size: amount_to_enlarge) + +Enlarge an image by putting a transparent border around it. +The border size is given in percentages of the image size, so @border_size: 1@ makes the image three times as large by putting a border of 100% the size on all sides. + +--Parameters-- +! Parameter Type Description +| @input@ [[type:image]] Image to enlarge +| @border_size@ [[type:double]] Amount of border to add, in percentage of the image + +--Examples-- +> enlarge_image(input: "image1.png", border_size: 0.1) == [[Image]] +>>> enlarge_image(input: "image1.png", border_size: 0.1) == "image_enlarge.png" diff --git a/doc/function/flip_horizontal.txt b/doc/function/flip_horizontal.txt deleted file mode 100644 index 14bdc90c..00000000 --- a/doc/function/flip_horizontal.txt +++ /dev/null @@ -1,20 +0,0 @@ -Function: flip_horizontal - -DOC_MSE_VERSION: since 0.3.9 - ---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_image.txt b/doc/function/flip_image.txt new file mode 100644 index 00000000..624ceb58 --- /dev/null +++ b/doc/function/flip_image.txt @@ -0,0 +1,18 @@ +Function: flip_image + +--Usage-- +> flip_image(input: image, horizontal: true) + +Flip an image horizontally or vertically. + +--Parameters-- +! Parameter Type Description +| @input@ [[type:image]] Image to flip. +| @horizontal@ [[type:boolean]] Flip horizontally or vertically? + +--Examples-- +> flip_image("image_logo.png") == [[Image]] +>>> flip_image("image_logo.png") == "image_logo_vflip.png" + +--See also-- +| [[fun:rotate]] Rotate an image diff --git a/doc/function/flip_vertical.txt b/doc/function/flip_vertical.txt deleted file mode 100644 index 913f624e..00000000 --- a/doc/function/flip_vertical.txt +++ /dev/null @@ -1,20 +0,0 @@ -Function: flip_vertical - -DOC_MSE_VERSION: since 0.3.9 - ---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/index.txt b/doc/function/index.txt index 54cca5ae..629eff76 100644 --- a/doc/function/index.txt +++ b/doc/function/index.txt @@ -86,24 +86,23 @@ These functions are built into the program, other [[type:function]]s can be defi | [[fun:set_mask]] Set the transparancy mask of an image. | [[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:saturate_image]] Saturate/desaturate an image. | [[fun:invert_image]] Invert the colors of an image. | [[fun:recolor_image]] Change the colors of an image to match the font color. | [[fun:resize_image]] Stretch or squeeze an image to a given height and width. -| [[fun:enlarge]] Enlarge an image by putting a border around it. +| [[fun:enlarge_image]] Enlarge an image by putting a border around it. +| [[fun:crop_image]] Crop an image, giving only a small subset of it. +| [[fun:insert_image]] Insert an image inside another. +| [[fun:flip_image]] Flip an image horizontally or vertically. +| [[fun:rotate_image]] Rotate an image. | [[fun:add_stroke_effect]] Add a stroke effect around an image. | [[fun:add_bleed_edge]] Add a crude print bleed edge around an image. -| [[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_image]] Rotate an image. -| [[fun:drop_shadow]] Add a drop shadow to an image. -| [[fun:insert_image]] Insert an image inside another. +| [[fun:add_drop_shadow]] Add a drop shadow to an image. | [[fun:dimensions_of]] Get the width and height of an image. -| [[fun:symbol_variation]] Render a variation of a [[type:symbol]]. -| [[fun:import_image]] Load an image from outside the data folder. -| [[fun:download_image]] Download an image from a URL. -| [[fun:built_in_image]] Return an image built into the program. +| [[fun:symbol_variation]] Render a variation of a [[type:symbol]]. +| [[fun:import_image]] Load an image from outside the data folder. +| [[fun:download_image]] Download an image from a URL. +| [[fun:built_in_image]] Return an image built into the program. ! Cards <<< | [[fun:new_card]] Construct a new [[type:card]] object. diff --git a/doc/function/saturate.txt b/doc/function/saturate.txt deleted file mode 100644 index 1895bcc4..00000000 --- a/doc/function/saturate.txt +++ /dev/null @@ -1,25 +0,0 @@ -Function: saturate - -DOC_MSE_VERSION: since 0.3.9 - ---Usage-- -> saturate(input: image, amount: saturation amount) - -Saturate or desaturate an image. Saturation makes the colors brighter, desaturation makes the image more grey. - -To saturate use an amount between @0@ (no saturation) and @1@ (super crazy, too much saturation). - -To desaturate use an amount between @0@ (no desaturation) and @-1@ (convert to greyscale). - ---Parameters-- -! Parameter Type Description -| @input@ [[type:image]] Image to (de)saturate. -| @alpha@ [[type:double]] Saturation factor. - ---Examples-- -> saturate("image5.png", amount: 0.5) == [[Image]] ->>> 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/doc/function/saturate_image.txt b/doc/function/saturate_image.txt new file mode 100644 index 00000000..f86b7fd0 --- /dev/null +++ b/doc/function/saturate_image.txt @@ -0,0 +1,25 @@ +Function: saturate_image + +DOC_MSE_VERSION: since 0.3.9 + +--Usage-- +> saturate_image(input: image, amount: saturation amount) + +Saturate or desaturate an image. Saturation makes the colors brighter, desaturation makes the image more grey. + +To saturate use an amount between @0@ (no saturation) and @1@ (super crazy, too much saturation). + +To desaturate use an amount between @0@ (no desaturation) and @-1@ (convert to greyscale). + +--Parameters-- +! Parameter Type Description +| @input@ [[type:image]] Image to (de)saturate. +| @alpha@ [[type:double]] Saturation factor. + +--Examples-- +> saturate_image("image5.png", amount: 0.5) == [[Image]] +>>> saturate_image("image5.png", amount: 0.5) == "image_saturate1.png" +> saturate_image("image5.png", amount: -0.5) == [[Image]] +>>> saturate_image("image5.png", amount: -0.5) == "image_saturate2.png" +> saturate_image("image_logo.png", amount: -1) == [[Image]] +>>> saturate_image("image_logo.png", amount: -1) == "image_logo_desaturate.png" diff --git a/src/data/field.hpp b/src/data/field.hpp index d9f1927e..a89c275f 100644 --- a/src/data/field.hpp +++ b/src/data/field.hpp @@ -126,10 +126,10 @@ public: inline RealPoint getPos() const { return RealPoint(left, top); } inline RealSize getSize() const { return RealSize(width, height); } inline RealRect getExternalRect() const { return RealRect(left, top, width, height); } - inline std::string getExternalRectString(double scale, Radians angle, double bleed, int img_width, int img_height, int img_offset) { ///< update the style before calling this + inline std::string getExternalRectString(double scale, Radians angle, int offset_x, int offset_y, int img_width, int img_height) { ///< update the style before calling this RealRect rect(left, top, width, height); int degrees = lround(rad_to_deg(this->angle)); - return transformAndEncodeRectInString(rect, degrees, scale, angle, bleed, img_width, img_height, img_offset); + return transformAndEncodeRectInString(rect, degrees, scale, angle, offset_x, offset_y, img_width, img_height); } /// Does this style have a non-zero size (or is it scripted)? diff --git a/src/data/format/image.cpp b/src/data/format/image.cpp index fbbc8903..a151ff8c 100644 --- a/src/data/format/image.cpp +++ b/src/data/format/image.cpp @@ -151,7 +151,7 @@ Image export_image(const SetP& set, const CardP& card, const bool write_metadata } // store only crop coordinates else { - std::string rect = style->getExternalRectString(zoom, angle_radians, bleed_pixels, width, height, 0); + std::string rect = style->getExternalRectString(zoom, angle_radians, bleed_pixels, bleed_pixels, width, height); cardv_data[field->name.ToStdString()] = rect; } } @@ -243,7 +243,7 @@ Image export_image( const SetP& set, const vector& cards, } // store only crop coordinates else { - std::string rect = style->getExternalRectString(zooms[i], angles[i], bleeds[i], widths[i], heights[i], offsets[i]); + std::string rect = style->getExternalRectString(zooms[i], angles[i], bleeds[i] + offsets[i], bleeds[i], widths[i], heights[i]); cardv_data[field->name.ToStdString()] = rect; } } diff --git a/src/data/format/image_encoding.hpp b/src/data/format/image_encoding.hpp index e6a6beac..eaed453a 100644 --- a/src/data/format/image_encoding.hpp +++ b/src/data/format/image_encoding.hpp @@ -78,7 +78,7 @@ inline static bool decodeRectFromString(const String& rectString, wxRect& rect_o } /// Apply a transformation to a rect, return true if successful -inline static bool transformEncodedRect(wxRect& rect, int& degrees, double scale, Radians angle, double bleed, int img_width, int img_height, int img_offset) { +inline static bool transformEncodedRect(wxRect& rect, int& degrees, double scale, Radians angle, int offset_x, int offset_y, int img_width, int img_height) { if (degrees != 0 && degrees != 90 && degrees != 180 && degrees != 270) return false; rect = wxRect(rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale); if (is_rad0(angle)) { @@ -94,22 +94,22 @@ inline static bool transformEncodedRect(wxRect& rect, int& degrees, double scale } else { return false; } - rect = wxRect(rect.x + bleed + img_offset, rect.y + bleed, rect.width, rect.height); + rect = wxRect(rect.x + offset_x, rect.y + offset_y, rect.width, rect.height); if (degrees >= 360) degrees -= 360; return true; } /// Retreive a rect encoded in a string, apply a transformation, then encode it back -inline static String transformEncodedRect(const String& rectString, double scale, Radians angle, double bleed, int img_width, int img_height, int img_offset) { ///< update the style before calling this +inline static String transformEncodedRect(const String& rectString, double scale, Radians angle, int offset_x, int offset_y, int img_width, int img_height) { wxRect rect; int degrees; if (!decodeRectFromString(rectString, rect, degrees)) return _(""); - if (!transformEncodedRect(rect, degrees, scale, angle, bleed, img_width, img_height, img_offset)) return _(""); + if (!transformEncodedRect(rect, degrees, scale, angle, offset_x, offset_y, img_width, img_height)) return _(""); return encodeRectInWxString(rect, degrees); } /// Retreive all rects encoded in a string, apply a transformation, then encode them back -inline static String transformAllEncodedRects(const String& rectString, double scale, Radians angle, double bleed, int img_width, int img_height, int img_offset) { ///< update the style before calling this +inline static String transformAllEncodedRects(const String& rectString, double scale, Radians angle, int offset_x, int offset_y, int img_width, int img_height) { wxRect rect; int degrees; size_t start = rectString.find(_("")); @@ -119,7 +119,9 @@ inline static String transformAllEncodedRects(const String& rectString, double s while (start != String::npos) { result = result + rectString.substr(end, start - end); end = rectString.find(_(""), start + 15); - result = result + transformEncodedRect(rectString.substr(start, end - start), scale, angle, bleed, img_width, img_height, img_offset); + if (end == String::npos) return rectString; + end += 16; + result = result + transformEncodedRect(rectString.substr(start, end - start), scale, angle, offset_x, offset_y, img_width, img_height); start = rectString.find(_(""), end); } result = result + rectString.substr(end); @@ -127,8 +129,8 @@ inline static String transformAllEncodedRects(const String& rectString, double s } /// Apply a transformation to a rect, then encode it in a string -inline static std::string transformAndEncodeRectInString(wxRect rect, int degrees, double scale, Radians angle, double bleed, int img_width, int img_height, int img_offset) { - if (!transformEncodedRect(rect, degrees, scale, angle, bleed, img_width, img_height, img_offset)) return ""; +inline static std::string transformAndEncodeRectInString(wxRect rect, int degrees, double scale, Radians angle, int offset_x, int offset_y, int img_width, int img_height) { + if (!transformEncodedRect(rect, degrees, scale, angle, offset_x, offset_y, img_width, img_height)) return ""; return encodeRectInStdString(rect, degrees); } diff --git a/src/gfx/generated_image.cpp b/src/gfx/generated_image.cpp index 7d1b639a..c66b5087 100644 --- a/src/gfx/generated_image.cpp +++ b/src/gfx/generated_image.cpp @@ -433,6 +433,11 @@ Image BleedEdgedImage::generate(const Options& opt) { pixels[3 * pixel + 2] = pixels[3 * mirror + 2]; alpha[pixel] = alpha[mirror]; } + } + // transfer metadata + if (base_img.HasOption(wxIMAGE_OPTION_PNG_DESCRIPTION)) { + String desc = transformAllEncodedRects(base_img.GetOption(wxIMAGE_OPTION_PNG_DESCRIPTION), 1.0, 0.0, dw, dh, width, height); + img.SetOption(wxIMAGE_OPTION_PNG_DESCRIPTION, desc); } // done return img; @@ -460,13 +465,17 @@ Image InsertedImage::generate(const Options& opt) { Image img = wxImage(width, height, false); img.InitAlpha(); Byte* data = img.GetData(); - Byte* alpha = img.GetAlpha(); + Byte* alpha = img.GetAlpha(); + Byte r = background_color.Red(); + Byte g = background_color.Green(); + Byte b = background_color.Blue(); + Byte a = background_color.Alpha(); for (UInt i = 0; i < size; ++i) { - data[0] = background_color.Red(); - data[1] = background_color.Green(); - data[2] = background_color.Blue(); + data[0] = r; + data[1] = g; + data[2] = b; data += 3; - alpha[0] = background_color.Alpha(); + alpha[0] = a; alpha += 1; } img.Paste(base_img, base_x, base_y, wxIMAGE_ALPHA_BLEND_COMPOSE); @@ -488,13 +497,33 @@ bool InsertedImage::operator == (const GeneratedImage& that) const { // ----------------------------------------------------------------------------- : CropImage Image CropImage::generate(const Options& opt) { - return image->generate(opt).Size(wxSize((int)width, (int)height), wxPoint(-(int)offset_x, -(int)offset_y)); + UInt size = width * height; + Image img = wxImage(width, height, false); + img.InitAlpha(); + Byte* data = img.GetData(); + Byte* alpha = img.GetAlpha(); + Byte r = background_color.Red(); + Byte g = background_color.Green(); + Byte b = background_color.Blue(); + Byte a = background_color.Alpha(); + for (UInt i = 0; i < size; ++i) { + data[0] = r; + data[1] = g; + data[2] = b; + data += 3; + alpha[0] = a; + alpha += 1; + } + Image base_img = image->generate(opt); + img.Paste(base_img, -(int)offset_x, -(int)offset_y, wxIMAGE_ALPHA_BLEND_OVER); + return img; } bool CropImage::operator == (const GeneratedImage& that) const { const CropImage* that2 = dynamic_cast(&that); return that2 && *image == *that2->image && width == that2->width && height == that2->height - && offset_x == that2->offset_x && offset_y == that2->offset_y; + && offset_x == that2->offset_x && offset_y == that2->offset_y + && background_color == that2->background_color; } // ----------------------------------------------------------------------------- : DropShadowImage diff --git a/src/gfx/generated_image.hpp b/src/gfx/generated_image.hpp index d37c3555..654cf137 100644 --- a/src/gfx/generated_image.hpp +++ b/src/gfx/generated_image.hpp @@ -308,14 +308,15 @@ private: /// Crop an image at a certain point, to a certain size class CropImage : public SimpleFilterImage { public: - inline CropImage(const GeneratedImageP& image, double width, double height, double offset_x, double offset_y) - : SimpleFilterImage(image), width(width), height(height), offset_x(offset_x), offset_y(offset_y) + inline CropImage(const GeneratedImageP& image, double width, double height, double offset_x, double offset_y, Color background_color) + : SimpleFilterImage(image), width(width), height(height), offset_x(offset_x), offset_y(offset_y), background_color(background_color) {} Image generate(const Options& opt) override; bool operator == (const GeneratedImage& that) const override; private: double width, height; double offset_x, offset_y; + Color background_color; }; // ----------------------------------------------------------------------------- : StrokeImage diff --git a/src/gfx/rotate_image.cpp b/src/gfx/rotate_image.cpp index aa0dd10e..b5c0daa0 100644 --- a/src/gfx/rotate_image.cpp +++ b/src/gfx/rotate_image.cpp @@ -8,6 +8,7 @@ #include #include +#include // ----------------------------------------------------------------------------- : Implementation @@ -38,6 +39,14 @@ Image rotate_image_impl(const Image& img) { in += 1; } } + } + // transfer metadata + if (img.HasOption(wxIMAGE_OPTION_PNG_DESCRIPTION)) { + if (!almost_equal(Rotater::angle(), rad180)) { + swap(width, height); + } + String desc = transformAllEncodedRects(img.GetOption(wxIMAGE_OPTION_PNG_DESCRIPTION), 1.0, Rotater::angle(), 0, 0, width, height); + ret.SetOption(wxIMAGE_OPTION_PNG_DESCRIPTION, desc); } // ret is rotated image return ret; @@ -56,7 +65,8 @@ struct Rotate90deg { int mx = y; int my = w - x - 1; return h * my + mx; // note: h, since that is the width of the target image - } + } + inline static Radians angle() { return rad90; } }; struct Rotate180deg { @@ -67,7 +77,8 @@ struct Rotate180deg { UInt mx = w - x - 1; UInt my = h - y - 1; return w * my + mx; - } + } + inline static Radians angle() { return rad180; } }; struct Rotate270deg { @@ -78,7 +89,8 @@ struct Rotate270deg { UInt mx = h - y - 1; UInt my = x; return h * my + mx; - } + } + inline static Radians angle() { return rad270; } }; // ----------------------------------------------------------------------------- : Interface diff --git a/src/gui/control/card_list.cpp b/src/gui/control/card_list.cpp index 5d0da217..27becabb 100644 --- a/src/gui/control/card_list.cpp +++ b/src/gui/control/card_list.cpp @@ -306,7 +306,11 @@ bool CardListBase::parseImage(Image& image, vector& out) { if (value && !value->filename.empty()) { wxRect rect = wxRect(0,0,0,0); int degrees = 0; - value->filename.getExternalRect(rect, degrees); + value->filename.getExternalRect(rect, degrees); + rect.x = max(0, rect.x); + rect.y = max(0, rect.y); + rect.width -= max(0, (rect.x + rect.width) - image.GetWidth()); + rect.height -= max(0, (rect.y + rect.height) - image.GetHeight()); if (rect.width > 0 && rect.height > 0) { Image img = image.GetSubImage(rect); img = rotate_image(img, deg_to_rad(360-degrees)); diff --git a/src/script/functions/image.cpp b/src/script/functions/image.cpp index 1c6344c4..3bc9881f 100644 --- a/src/script/functions/image.cpp +++ b/src/script/functions/image.cpp @@ -202,7 +202,8 @@ SCRIPT_FUNCTION(crop) { SCRIPT_PARAM(int, height); SCRIPT_PARAM(double, offset_x); SCRIPT_PARAM(double, offset_y); - return make_intrusive(input, width, height, offset_x, offset_y); + SCRIPT_OPTIONAL_PARAM_(Color, background_color); + return make_intrusive(input, width, height, offset_x, offset_y, background_color); } SCRIPT_FUNCTION(flip_horizontal) { @@ -215,6 +216,13 @@ SCRIPT_FUNCTION(flip_vertical) { return make_intrusive(input); } +SCRIPT_FUNCTION(flip_image) { + SCRIPT_PARAM_C(GeneratedImageP, input); + SCRIPT_PARAM(bool, horizontal); + if (horizontal) return make_intrusive(input); + else return make_intrusive(input); +} + SCRIPT_FUNCTION(rotate) { SCRIPT_PARAM_C(GeneratedImageP, input); SCRIPT_PARAM(Degrees, angle); @@ -314,18 +322,23 @@ 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(_("saturate_image"), script_saturate); ctx.setVariable(_("invert_image"), script_invert_image); ctx.setVariable(_("recolor_image"), script_recolor_image); ctx.setVariable(_("enlarge"), script_enlarge); + ctx.setVariable(_("enlarge_image"), script_enlarge); ctx.setVariable(_("add_stroke_effect"),script_add_stroke_effect); ctx.setVariable(_("add_bleed_edge"), script_add_bleed_edge); ctx.setVariable(_("resize_image"), script_resize_image); ctx.setVariable(_("crop"), script_crop); + ctx.setVariable(_("crop_image"), script_crop); ctx.setVariable(_("flip_horizontal"), script_flip_horizontal); ctx.setVariable(_("flip_vertical"), script_flip_vertical); + ctx.setVariable(_("flip_image"), script_flip_image); ctx.setVariable(_("rotate"), script_rotate); ctx.setVariable(_("rotate_image"), script_rotate); ctx.setVariable(_("drop_shadow"), script_drop_shadow); + ctx.setVariable(_("add_drop_shadow"), script_drop_shadow); ctx.setVariable(_("symbol_variation"), script_symbol_variation); ctx.setVariable(_("built_in_image"), script_built_in_image); ctx.setVariable(_("import_image"), script_import_image);