add brighten_image script function, 'average' and 'offset' combine modes

This commit is contained in:
GenevensiS
2026-04-11 04:51:59 +02:00
parent c167272ae6
commit d49cfda407
8 changed files with 89 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
Function: brighten_image
DOC_MSE_VERSION: since 2.6.0
--Usage--
> brighten_image(input: image, amount: brightening amount)
Brighten or darken an image.
To brighten use an amount between @0@ (no effect) and @1@ (entire image is pure white).
To darken use an amount between @0@ (no effect) and @-1@ (entire image is pure black).
--Parameters--
! Parameter Type Description
| @input@ [[type:image]] Image to brighten/darken.
| @alpha@ [[type:double]] Brightening factor.
+1
View File
@@ -87,6 +87,7 @@ 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_alpha]] Change the transparency of an image.
| [[fun:set_combine]] Change how the image should be combined with the background. | [[fun:set_combine]] Change how the image should be combined with the background.
| [[fun:saturate_image]] Saturate/desaturate an image. | [[fun:saturate_image]] Saturate/desaturate an image.
| [[fun:brighten_image]] Brighten/darken an image.
| [[fun:invert_image]] Invert the colors of 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: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:resize_image]] Stretch or squeeze an image to a given height and width.
+8
View File
@@ -21,6 +21,7 @@ String combine_to_string(const ImageCombine& combine) {
case COMBINE_NORMAL: return "normal"; case COMBINE_NORMAL: return "normal";
case COMBINE_ADD: return "add"; case COMBINE_ADD: return "add";
case COMBINE_SUBTRACT: return "subtract"; case COMBINE_SUBTRACT: return "subtract";
case COMBINE_AVERAGE: return "average";
case COMBINE_STAMP: return "stamp"; case COMBINE_STAMP: return "stamp";
case COMBINE_DIFFERENCE: return "difference"; case COMBINE_DIFFERENCE: return "difference";
case COMBINE_NEGATION: return "negation"; case COMBINE_NEGATION: return "negation";
@@ -41,6 +42,7 @@ String combine_to_string(const ImageCombine& combine) {
case COMBINE_OR: return "or"; case COMBINE_OR: return "or";
case COMBINE_XOR: return "xor"; case COMBINE_XOR: return "xor";
case COMBINE_SHADOW: return "shadow"; case COMBINE_SHADOW: return "shadow";
case COMBINE_OFFSET: return "offset";
case COMBINE_SYMMETRIC_OVERLAY: return "symmetric overlay"; case COMBINE_SYMMETRIC_OVERLAY: return "symmetric overlay";
case COMBINE_BRIGHTNESS_TO_ALPHA: return "brightness to alpha"; case COMBINE_BRIGHTNESS_TO_ALPHA: return "brightness to alpha";
case COMBINE_DARKNESS_TO_ALPHA: return "darkness to alpha"; case COMBINE_DARKNESS_TO_ALPHA: return "darkness to alpha";
@@ -152,6 +154,7 @@ IMPLEMENT_REFLECTION_ENUM(ImageCombine) {
VALUE_N("normal", COMBINE_NORMAL); VALUE_N("normal", COMBINE_NORMAL);
VALUE_N("add", COMBINE_ADD); VALUE_N("add", COMBINE_ADD);
VALUE_N("subtract", COMBINE_SUBTRACT); VALUE_N("subtract", COMBINE_SUBTRACT);
VALUE_N("average", COMBINE_AVERAGE);
VALUE_N("stamp", COMBINE_STAMP); VALUE_N("stamp", COMBINE_STAMP);
VALUE_N("difference", COMBINE_DIFFERENCE); VALUE_N("difference", COMBINE_DIFFERENCE);
VALUE_N("negation", COMBINE_NEGATION); VALUE_N("negation", COMBINE_NEGATION);
@@ -172,6 +175,7 @@ IMPLEMENT_REFLECTION_ENUM(ImageCombine) {
VALUE_N("or", COMBINE_OR); VALUE_N("or", COMBINE_OR);
VALUE_N("xor", COMBINE_XOR); VALUE_N("xor", COMBINE_XOR);
VALUE_N("shadow", COMBINE_SHADOW); VALUE_N("shadow", COMBINE_SHADOW);
VALUE_N("offset", COMBINE_OFFSET);
VALUE_N("symmetric overlay", COMBINE_SYMMETRIC_OVERLAY); VALUE_N("symmetric overlay", COMBINE_SYMMETRIC_OVERLAY);
VALUE_N("brightness to alpha", COMBINE_BRIGHTNESS_TO_ALPHA); VALUE_N("brightness to alpha", COMBINE_BRIGHTNESS_TO_ALPHA);
VALUE_N("darkness to alpha", COMBINE_DARKNESS_TO_ALPHA); VALUE_N("darkness to alpha", COMBINE_DARKNESS_TO_ALPHA);
@@ -294,6 +298,7 @@ template <ImageCombine combine> struct Combine {
COMBINE_FUN(COMBINE_NORMAL, b) COMBINE_FUN(COMBINE_NORMAL, b)
COMBINE_FUN(COMBINE_ADD, top(a + b)) COMBINE_FUN(COMBINE_ADD, top(a + b))
COMBINE_FUN(COMBINE_SUBTRACT, bot(a - b)) COMBINE_FUN(COMBINE_SUBTRACT, bot(a - b))
COMBINE_FUN(COMBINE_AVERAGE, (a + b) / 2)
COMBINE_FUN(COMBINE_STAMP, col(a - 2 * b + 256)) COMBINE_FUN(COMBINE_STAMP, col(a - 2 * b + 256))
COMBINE_FUN(COMBINE_DIFFERENCE, abs(a - b)) COMBINE_FUN(COMBINE_DIFFERENCE, abs(a - b))
COMBINE_FUN(COMBINE_NEGATION, 255 - abs(255 - a - b)) COMBINE_FUN(COMBINE_NEGATION, 255 - abs(255 - a - b))
@@ -318,6 +323,7 @@ COMBINE_FUN(COMBINE_AND, a & b)
COMBINE_FUN(COMBINE_OR, a | b) COMBINE_FUN(COMBINE_OR, a | b)
COMBINE_FUN(COMBINE_XOR, a ^ b) COMBINE_FUN(COMBINE_XOR, a ^ b)
COMBINE_FUN(COMBINE_SHADOW, (b * a * a) / (255 * 255)) COMBINE_FUN(COMBINE_SHADOW, (b * a * a) / (255 * 255))
COMBINE_FUN(COMBINE_OFFSET, col(a + b - 128))
COMBINE_FUN(COMBINE_SYMMETRIC_OVERLAY, (Combine<COMBINE_OVERLAY>::f(a, b) + Combine<COMBINE_OVERLAY>::f(b, a)) / 2) COMBINE_FUN(COMBINE_SYMMETRIC_OVERLAY, (Combine<COMBINE_OVERLAY>::f(a, b) + Combine<COMBINE_OVERLAY>::f(b, a)) / 2)
COMBINE_FUN(COMBINE_BRIGHTNESS_TO_ALPHA, ((255 - a) * a + a * b) / 255) COMBINE_FUN(COMBINE_BRIGHTNESS_TO_ALPHA, ((255 - a) * a + a * b) / 255)
COMBINE_FUN(COMBINE_DARKNESS_TO_ALPHA, (255 * a + (255 - a) * b) / 255) COMBINE_FUN(COMBINE_DARKNESS_TO_ALPHA, (255 * a + (255 - a) * b) / 255)
@@ -453,6 +459,7 @@ void combine_image(Image& a, const Image& b, ImageCombine combine) {
case COMBINE_NORMAL: a = b; return; // no need to do a per pixel operation case COMBINE_NORMAL: a = b; return; // no need to do a per pixel operation
DISPATCH(COMBINE_ADD); DISPATCH(COMBINE_ADD);
DISPATCH(COMBINE_SUBTRACT); DISPATCH(COMBINE_SUBTRACT);
DISPATCH(COMBINE_AVERAGE);
DISPATCH(COMBINE_STAMP); DISPATCH(COMBINE_STAMP);
DISPATCH(COMBINE_DIFFERENCE); DISPATCH(COMBINE_DIFFERENCE);
DISPATCH(COMBINE_NEGATION); DISPATCH(COMBINE_NEGATION);
@@ -473,6 +480,7 @@ void combine_image(Image& a, const Image& b, ImageCombine combine) {
DISPATCH(COMBINE_OR); DISPATCH(COMBINE_OR);
DISPATCH(COMBINE_XOR); DISPATCH(COMBINE_XOR);
DISPATCH(COMBINE_SHADOW); DISPATCH(COMBINE_SHADOW);
DISPATCH(COMBINE_OFFSET);
DISPATCH(COMBINE_SYMMETRIC_OVERLAY); DISPATCH(COMBINE_SYMMETRIC_OVERLAY);
DISPATCH(COMBINE_BRIGHTNESS_TO_ALPHA); DISPATCH(COMBINE_BRIGHTNESS_TO_ALPHA);
DISPATCH(COMBINE_DARKNESS_TO_ALPHA); DISPATCH(COMBINE_DARKNESS_TO_ALPHA);
+13
View File
@@ -201,6 +201,19 @@ bool SaturateImage::operator == (const GeneratedImage& that) const {
&& amount == that2->amount; && amount == that2->amount;
} }
// ----------------------------------------------------------------------------- : BrightenImage
Image BrightenImage::generate(const Options& opt) {
Image img = image->generate(opt);
brighten(img, amount);
return img;
}
bool BrightenImage::operator == (const GeneratedImage& that) const {
const BrightenImage* that2 = dynamic_cast<const BrightenImage*>(&that);
return that2 && *image == *that2->image
&& amount == that2->amount;
}
// ----------------------------------------------------------------------------- : InvertImage // ----------------------------------------------------------------------------- : InvertImage
Image InvertImage::generate(const Options& opt) { Image InvertImage::generate(const Options& opt) {
+14
View File
@@ -203,6 +203,20 @@ private:
double amount; double amount;
}; };
// ----------------------------------------------------------------------------- : BrightenImage
/// Brighten/darken an image
class BrightenImage : public SimpleFilterImage {
public:
inline BrightenImage(const GeneratedImageP& image, double amount)
: SimpleFilterImage(image), amount(amount)
{}
Image generate(const Options& opt) override;
bool operator == (const GeneratedImage& that) const override;
private:
double amount;
};
// ----------------------------------------------------------------------------- : InvertImage // ----------------------------------------------------------------------------- : InvertImage
/// Invert an image /// Invert an image
+5
View File
@@ -93,6 +93,9 @@ void mask_blend(Image& img1, const Image& img2, const Image& mask);
/// Saturate an image /// Saturate an image
void saturate(Image& image, double amount); void saturate(Image& image, double amount);
/// Brighten an image
void brighten(Image& image, double amount);
/// Invert the colors in an image /// Invert the colors in an image
void invert(Image& img); void invert(Image& img);
@@ -120,6 +123,7 @@ enum ImageCombine
, COMBINE_NORMAL , COMBINE_NORMAL
, COMBINE_ADD , COMBINE_ADD
, COMBINE_SUBTRACT , COMBINE_SUBTRACT
, COMBINE_AVERAGE
, COMBINE_STAMP , COMBINE_STAMP
, COMBINE_DIFFERENCE , COMBINE_DIFFERENCE
, COMBINE_NEGATION , COMBINE_NEGATION
@@ -140,6 +144,7 @@ enum ImageCombine
, COMBINE_OR , COMBINE_OR
, COMBINE_XOR , COMBINE_XOR
, COMBINE_SHADOW , COMBINE_SHADOW
, COMBINE_OFFSET
, COMBINE_SYMMETRIC_OVERLAY , COMBINE_SYMMETRIC_OVERLAY
, COMBINE_BRIGHTNESS_TO_ALPHA , COMBINE_BRIGHTNESS_TO_ALPHA
, COMBINE_DARKNESS_TO_ALPHA , COMBINE_DARKNESS_TO_ALPHA
+24
View File
@@ -65,6 +65,30 @@ void saturate(Image& image, double amount) {
} }
} }
// ----------------------------------------------------------------------------- : Brightness
void brighten(Image& image, double amount) {
if (almost_equal(amount, 0.0)) return;
Byte* pix = image.GetData();
Byte* end = pix + image.GetWidth() * image.GetHeight() * 3;
amount = min(max(amount, -1.0), 1.0);
if (amount > 0.0) {
double s = 255 * amount;
double t = 1.0 - amount;
while (pix != end) {
pix[0] = s + pix[0] * t;
pix++;
}
} else {
double t = 1.0 + amount;
while (pix != end) {
pix[0] = pix[0] * t;
pix++;
}
}
}
// ----------------------------------------------------------------------------- : Color inversion // ----------------------------------------------------------------------------- : Color inversion
void invert(Image& img) { void invert(Image& img) {
+7
View File
@@ -168,6 +168,12 @@ SCRIPT_FUNCTION(saturate) {
return make_intrusive<SaturateImage>(input, amount); return make_intrusive<SaturateImage>(input, amount);
} }
SCRIPT_FUNCTION(brighten_image) {
SCRIPT_PARAM_C(GeneratedImageP, input);
SCRIPT_PARAM(double, amount);
return make_intrusive<BrightenImage>(input, amount);
}
SCRIPT_FUNCTION(invert_image) { SCRIPT_FUNCTION(invert_image) {
SCRIPT_PARAM_C(GeneratedImageP, input); SCRIPT_PARAM_C(GeneratedImageP, input);
return make_intrusive<InvertImage>(input); return make_intrusive<InvertImage>(input);
@@ -345,6 +351,7 @@ void init_script_image_functions(Context& ctx) {
ctx.setVariable(_("set_combine"), script_set_combine); ctx.setVariable(_("set_combine"), script_set_combine);
ctx.setVariable(_("saturate"), script_saturate); ctx.setVariable(_("saturate"), script_saturate);
ctx.setVariable(_("saturate_image"), script_saturate); ctx.setVariable(_("saturate_image"), script_saturate);
ctx.setVariable(_("brighten_image"), script_brighten_image);
ctx.setVariable(_("invert_image"), script_invert_image); ctx.setVariable(_("invert_image"), script_invert_image);
ctx.setVariable(_("recolor_image"), script_recolor_image); ctx.setVariable(_("recolor_image"), script_recolor_image);
ctx.setVariable(_("enlarge"), script_enlarge); ctx.setVariable(_("enlarge"), script_enlarge);