mirror of
https://github.com/lovell/sharp.git
synced 2026-02-06 06:36:17 +01:00
overlayWith improvements: diff sizes/formats, gravity, buffer input
This commit is contained in:
@@ -4,34 +4,49 @@
|
||||
#include "operations.h"
|
||||
|
||||
using vips::VImage;
|
||||
using vips::VError;
|
||||
|
||||
namespace sharp {
|
||||
|
||||
/*
|
||||
Alpha composite src over dst
|
||||
Assumes alpha channels are already premultiplied and will be unpremultiplied after
|
||||
Alpha composite src over dst with given gravity.
|
||||
Assumes alpha channels are already premultiplied and will be unpremultiplied after.
|
||||
*/
|
||||
VImage Composite(VImage src, VImage dst) {
|
||||
VImage Composite(VImage src, VImage dst, const int gravity) {
|
||||
using sharp::CalculateCrop;
|
||||
using sharp::HasAlpha;
|
||||
|
||||
// Split src into non-alpha and alpha
|
||||
if (!HasAlpha(src)) {
|
||||
throw VError("Overlay image must have an alpha channel");
|
||||
}
|
||||
if (!HasAlpha(dst)) {
|
||||
throw VError("Image to be overlaid must have an alpha channel");
|
||||
}
|
||||
if (src.width() > dst.width() || src.height() > dst.height()) {
|
||||
throw VError("Overlay image must have same dimensions or smaller");
|
||||
}
|
||||
|
||||
// Enlarge overlay src, if required
|
||||
if (src.width() < dst.width() || src.height() < dst.height()) {
|
||||
// Calculate the (left, top) coordinates of the output image within the input image, applying the given gravity.
|
||||
int left;
|
||||
int top;
|
||||
std::tie(left, top) = CalculateCrop(dst.width(), dst.height(), src.width(), src.height(), gravity);
|
||||
// Embed onto transparent background
|
||||
std::vector<double> background { 0.0, 0.0, 0.0, 0.0 };
|
||||
src = src.embed(left, top, dst.width(), dst.height(), VImage::option()
|
||||
->set("extend", VIPS_EXTEND_BACKGROUND)
|
||||
->set("background", background)
|
||||
);
|
||||
}
|
||||
|
||||
// Split src into non-alpha and alpha channels
|
||||
VImage srcWithoutAlpha = src.extract_band(0, VImage::option()->set("n", src.bands() - 1));
|
||||
VImage srcAlpha = src[src.bands() - 1] * (1.0 / 255.0);
|
||||
|
||||
// Split dst into non-alpha and alpha channels
|
||||
VImage dstWithoutAlpha;
|
||||
VImage dstAlpha;
|
||||
if (HasAlpha(dst)) {
|
||||
// Non-alpha: extract all-but-last channel
|
||||
dstWithoutAlpha = dst.extract_band(0, VImage::option()->set("n", dst.bands() - 1));
|
||||
// Alpha: Extract last channel
|
||||
dstAlpha = dst[dst.bands() - 1] * (1.0 / 255.0);
|
||||
} else {
|
||||
// Non-alpha: Copy reference
|
||||
dstWithoutAlpha = dst;
|
||||
// Alpha: Use blank, opaque (0xFF) image
|
||||
dstAlpha = VImage::black(dst.width(), dst.height()).invert();
|
||||
}
|
||||
VImage dstWithoutAlpha = dst.extract_band(0, VImage::option()->set("n", dst.bands() - 1));
|
||||
VImage dstAlpha = dst[dst.bands() - 1] * (1.0 / 255.0);
|
||||
|
||||
//
|
||||
// Compute normalized output alpha channel:
|
||||
|
||||
Reference in New Issue
Block a user