mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
add insert_image and add_bleed_edge functions
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
Function: add_bleed_edge
|
||||
|
||||
--Usage--
|
||||
> add_bleed_edge(input: image, horizontal_size: number, vertical_size: number, background_color: color)
|
||||
|
||||
Add a crude print bleed edge around an image.
|
||||
The sizes are given in percentages of the image size, so @horizontal_size: 1@ makes the image three times as large by putting a bleed edge of 100% on both sides.
|
||||
|
||||
--Parameters--
|
||||
! Parameter Type Description
|
||||
| @input@ [[type:image]] Image that needs a print bleed edge
|
||||
| @horizontal_size@ [[type:double]] Size of the bleed edge on the sides, in percentage of the image width. Optional, defaults to 0.048
|
||||
| @vertical_size@ [[type:double]] Size of the bleed edge on the top and bottom, in percentage of the image height. Optional, defaults to 0.037
|
||||
| @background_color@ [[type:color]] Background color, optional, defaults to transparent
|
||||
|
||||
@@ -9,7 +9,7 @@ The border size is given in percentages of the image size, so @border_size: 1@ m
|
||||
--Parameters--
|
||||
! Parameter Type Description
|
||||
| @input@ [[type:image]] Image to enlarge
|
||||
| @border_size@ [[type:double]] Amount of border to add
|
||||
| @border_size@ [[type:double]] Amount of border to add, in percentage of the image
|
||||
|
||||
--Examples--
|
||||
> enlarge(input: "image1.png", border_size: 0.1) == [[Image]]
|
||||
|
||||
@@ -89,6 +89,7 @@ These functions are built into the program, other [[type:function]]s can be defi
|
||||
| [[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: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.
|
||||
|
||||
@@ -318,6 +318,193 @@ bool ResizeImage::operator == (const GeneratedImage& that) const {
|
||||
&& height == that2->height;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : BleedEdgedImage
|
||||
|
||||
Image BleedEdgedImage::generate(const Options& opt) const {
|
||||
// create enlarged image
|
||||
Image base_img = base_image->generate(opt);
|
||||
int w = base_img.GetWidth(), h = base_img.GetHeight();
|
||||
if (w <= 0 || h <= 0) {
|
||||
queue_message(MESSAGE_ERROR, _("Cannot add bleed edge to empty image"));
|
||||
return base_img;
|
||||
}
|
||||
bool is_landscape = w > h;
|
||||
int dw = int(w * (horizontal_size > 0.0 ? horizontal_size : is_landscape ? 0.037 : 0.048));
|
||||
int dh = int(h * (vertical_size > 0.0 ? vertical_size : is_landscape ? 0.048 : 0.037));
|
||||
if (dw <= 0 && dh <= 0) {
|
||||
return base_img;
|
||||
}
|
||||
int width = w + dw + dw, height = h + dh + dh;
|
||||
UInt size = width * height;
|
||||
Image img = wxImage(width, height, false);
|
||||
img.InitAlpha();
|
||||
Byte* data = img.GetData();
|
||||
Byte* alpha = img.GetAlpha();
|
||||
// fill with background color
|
||||
for (UInt i = 0; i < size; ++i) {
|
||||
data[3 * i + 0] = background_color.Red();
|
||||
data[3 * i + 1] = background_color.Green();
|
||||
data[3 * i + 2] = background_color.Blue();
|
||||
alpha[i] = background_color.Alpha();
|
||||
}
|
||||
// paste original image
|
||||
img.Paste(base_img, dw, dh, wxIMAGE_ALPHA_BLEND_COMPOSE);
|
||||
// fill top left corner
|
||||
int pixel;
|
||||
int x_start = 0;
|
||||
int y_start = 0;
|
||||
int ref = dw + dh * width;
|
||||
for (int y = 0; y < dh; ++y) {
|
||||
for (int x = 0; x < dw; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill top right corner
|
||||
x_start = width - dw;
|
||||
y_start = 0;
|
||||
ref = x_start - 1 + dh * width;
|
||||
for (int y = 0; y < dh; ++y) {
|
||||
for (int x = 0; x < dw; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill bottom left corner
|
||||
x_start = 0;
|
||||
y_start = height - dh;
|
||||
ref = dw + (y_start - 1) * width;
|
||||
for (int y = 0; y < dh; ++y) {
|
||||
for (int x = 0; x < dw; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill bottom right corner
|
||||
x_start = width - dw;
|
||||
y_start = height - dh;
|
||||
ref = (x_start - 1) + (y_start - 1) * width;
|
||||
for (int y = 0; y < dh; ++y) {
|
||||
for (int x = 0; x < dw; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill left border
|
||||
x_start = 0;
|
||||
y_start = dh;
|
||||
for (int y = 0; y < height - dh - dh; ++y) {
|
||||
ref = dw + (y_start + y) * width;
|
||||
for (int x = 0; x < dw; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill top border
|
||||
x_start = dw;
|
||||
y_start = 0;
|
||||
for (int y = 0; y < dh; ++y) {
|
||||
for (int x = 0; x < width - dw - dw; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
ref = x_start + x + dh * width;
|
||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill right border
|
||||
x_start = width - dw;
|
||||
y_start = dh;
|
||||
for (int y = 0; y < height - dh - dh; ++y) {
|
||||
ref = width - dw - 1 + (y_start + y) * width;
|
||||
for (int x = 0; x < dw; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill bottom border
|
||||
x_start = dw;
|
||||
y_start = height - dh;
|
||||
for (int y = 0; y < dh; ++y) {
|
||||
for (int x = 0; x < width - dw - dw; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
ref = x_start + x + (height - dh - 1) * width;
|
||||
data[3 * pixel + 0] = data[3 * ref + 0];
|
||||
data[3 * pixel + 1] = data[3 * ref + 1];
|
||||
data[3 * pixel + 2] = data[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// done
|
||||
return img;
|
||||
}
|
||||
bool BleedEdgedImage::operator == (const GeneratedImage& that) const {
|
||||
const BleedEdgedImage* that2 = dynamic_cast<const BleedEdgedImage*>(&that);
|
||||
return that2 && *base_image == *that2->base_image
|
||||
&& horizontal_size == that2->horizontal_size
|
||||
&& vertical_size == that2->vertical_size
|
||||
&& background_color == that2->background_color;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : InsertedImage
|
||||
|
||||
Image InsertedImage::generate(const Options& opt) const {
|
||||
Image base_img = base_image->generate(opt);
|
||||
Image inserted_img = inserted_image->generate(opt);
|
||||
int base_x = offset_x < 0 ? -offset_x : 0;
|
||||
int base_y = offset_y < 0 ? -offset_y : 0;
|
||||
int inserted_x = offset_x < 0 ? 0 : offset_x;
|
||||
int inserted_y = offset_y < 0 ? 0 : offset_y;
|
||||
int width = max(base_x + base_img.GetWidth(), inserted_x + inserted_img.GetWidth());
|
||||
int height = max(base_y + base_img.GetHeight(), inserted_y + inserted_img.GetHeight());
|
||||
UInt size = width * height;
|
||||
Image img = wxImage(width, height, false);
|
||||
img.InitAlpha();
|
||||
Byte* data = img.GetData();
|
||||
Byte* alpha = img.GetAlpha();
|
||||
for (UInt i = 0; i < size; ++i) {
|
||||
data[0] = background_color.Red();
|
||||
data[1] = background_color.Green();
|
||||
data[2] = background_color.Blue();
|
||||
data += 3;
|
||||
alpha[0] = background_color.Alpha();
|
||||
alpha += 1;
|
||||
}
|
||||
img.Paste(base_img, base_x, base_y, wxIMAGE_ALPHA_BLEND_COMPOSE);
|
||||
img.Paste(inserted_img, inserted_x, inserted_y, wxIMAGE_ALPHA_BLEND_COMPOSE);
|
||||
return img;
|
||||
}
|
||||
ImageCombine InsertedImage::combine() const {
|
||||
return base_image->combine();
|
||||
}
|
||||
bool InsertedImage::operator == (const GeneratedImage& that) const {
|
||||
const InsertedImage* that2 = dynamic_cast<const InsertedImage*>(&that);
|
||||
return that2
|
||||
&& *base_image == *that2->base_image
|
||||
&& *inserted_image == *that2->inserted_image
|
||||
&& offset_x == that2->offset_x
|
||||
&& offset_y == that2->offset_y;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : CropImage
|
||||
|
||||
Image CropImage::generate(const Options& opt) const {
|
||||
|
||||
@@ -317,6 +317,40 @@ private:
|
||||
double offset_x, offset_y;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : BleedEdgedImage
|
||||
|
||||
/// Add a crude bleed edge to an image
|
||||
class BleedEdgedImage : public GeneratedImage {
|
||||
public:
|
||||
inline BleedEdgedImage(const GeneratedImageP& base_image, double horizontal_size, double vertical_size, Color background_color)
|
||||
: base_image(base_image), horizontal_size(horizontal_size), vertical_size(vertical_size), background_color(background_color)
|
||||
{}
|
||||
Image generate(const Options& opt) const override;
|
||||
bool operator == (const GeneratedImage& that) const override;
|
||||
private:
|
||||
GeneratedImageP base_image;
|
||||
double horizontal_size, vertical_size;
|
||||
Color background_color;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : InsertedImage
|
||||
|
||||
/// Insert an image at a certain point inside another image
|
||||
class InsertedImage : public GeneratedImage {
|
||||
public:
|
||||
inline InsertedImage(const GeneratedImageP& base_image, const GeneratedImageP& inserted_image, int offset_x, int offset_y, Color background_color)
|
||||
: base_image(base_image), inserted_image(inserted_image), offset_x(offset_x), offset_y(offset_y), background_color(background_color)
|
||||
{}
|
||||
Image generate(const Options& opt) const override;
|
||||
ImageCombine combine() const override;
|
||||
bool operator == (const GeneratedImage& that) const override;
|
||||
bool local() const override { return base_image->local() && inserted_image->local(); }
|
||||
private:
|
||||
GeneratedImageP base_image, inserted_image;
|
||||
int offset_x, offset_y;
|
||||
Color background_color;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : DropShadowImage
|
||||
|
||||
/// Add a drop shadow to an image
|
||||
|
||||
@@ -70,6 +70,15 @@ SCRIPT_FUNCTION(height_of) {
|
||||
SCRIPT_RETURN(image.GetHeight());
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(insert_image) {
|
||||
SCRIPT_PARAM(GeneratedImageP, base_image);
|
||||
SCRIPT_PARAM(GeneratedImageP, inserted_image);
|
||||
SCRIPT_PARAM(int, offset_x);
|
||||
SCRIPT_PARAM(int, offset_y);
|
||||
SCRIPT_OPTIONAL_PARAM_(Color, background_color);
|
||||
return make_intrusive<InsertedImage>(base_image, inserted_image, offset_x, offset_y, background_color);
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(linear_blend) {
|
||||
SCRIPT_PARAM(GeneratedImageP, image1);
|
||||
SCRIPT_PARAM(GeneratedImageP, image2);
|
||||
@@ -144,6 +153,14 @@ SCRIPT_FUNCTION(enlarge) {
|
||||
return make_intrusive<EnlargeImage>(input, border_size);
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(add_bleed_edge) {
|
||||
SCRIPT_PARAM_C(GeneratedImageP, input);
|
||||
SCRIPT_PARAM_DEFAULT(double, horizontal_size, -1.0);
|
||||
SCRIPT_PARAM_DEFAULT(double, vertical_size, -1.0);
|
||||
SCRIPT_OPTIONAL_PARAM_(Color, background_color);
|
||||
return make_intrusive<BleedEdgedImage>(input, horizontal_size, vertical_size, background_color);
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(resize_image) {
|
||||
SCRIPT_PARAM_C(GeneratedImageP, input);
|
||||
SCRIPT_PARAM(int, width);
|
||||
@@ -263,6 +280,7 @@ void init_script_image_functions(Context& ctx) {
|
||||
ctx.setVariable(_("linear_blend"), script_linear_blend);
|
||||
ctx.setVariable(_("masked_blend"), script_masked_blend);
|
||||
ctx.setVariable(_("combine_blend"), script_combine_blend);
|
||||
ctx.setVariable(_("insert_image"), script_insert_image);
|
||||
ctx.setVariable(_("set_mask"), script_set_mask);
|
||||
ctx.setVariable(_("set_alpha"), script_set_alpha);
|
||||
ctx.setVariable(_("set_combine"), script_set_combine);
|
||||
@@ -270,6 +288,7 @@ void init_script_image_functions(Context& ctx) {
|
||||
ctx.setVariable(_("invert_image"), script_invert_image);
|
||||
ctx.setVariable(_("recolor_image"), script_recolor_image);
|
||||
ctx.setVariable(_("enlarge"), script_enlarge);
|
||||
ctx.setVariable(_("add_bleed_edge"), script_add_bleed_edge);
|
||||
ctx.setVariable(_("resize_image"), script_resize_image);
|
||||
ctx.setVariable(_("crop"), script_crop);
|
||||
ctx.setVariable(_("flip_horizontal"), script_flip_horizontal);
|
||||
|
||||
@@ -85,6 +85,7 @@ $built_in_functions = array(
|
||||
'recolor_image' =>'',
|
||||
'resize_image' =>'',
|
||||
'enlarge' =>'',
|
||||
'add_bleed_edge' =>'',
|
||||
'crop' =>'',
|
||||
'flip_horizontal' =>'',
|
||||
'flip_vertical' =>'',
|
||||
|
||||
Reference in New Issue
Block a user