in libheif/pixelimage.cc [1035:1153]
Error HeifPixelImage::overlay(std::shared_ptr<HeifPixelImage>& overlay, int32_t dx, int32_t dy)
{
std::set<enum heif_channel> channels = overlay->get_channel_set();
bool has_alpha = overlay->has_channel(heif_channel_Alpha);
//bool has_alpha_me = has_channel(heif_channel_Alpha);
int alpha_stride = 0;
uint8_t* alpha_p;
alpha_p = overlay->get_plane(heif_channel_Alpha, &alpha_stride);
for (heif_channel channel : channels) {
if (!has_channel(channel)) {
continue;
}
int in_stride = 0;
const uint8_t* in_p;
int out_stride = 0;
uint8_t* out_p;
in_p = overlay->get_plane(channel, &in_stride);
out_p = get_plane(channel, &out_stride);
uint32_t in_w = overlay->get_width(channel);
uint32_t in_h = overlay->get_height(channel);
uint32_t out_w = get_width(channel);
uint32_t out_h = get_height(channel);
// top-left points where to start copying in source and destination
uint32_t in_x0;
uint32_t in_y0;
uint32_t out_x0;
uint32_t out_y0;
if (dx > 0 && static_cast<uint32_t>(dx) >= out_w) {
// the overlay image is completely outside the right border -> skip overlaying
return Error::Ok;
}
else if (dx < 0 && in_w <= negate_negative_int32(dx)) {
// the overlay image is completely outside the left border -> skip overlaying
return Error::Ok;
}
if (dx < 0) {
// overlay image started partially outside of left border
in_x0 = negate_negative_int32(dx);
out_x0 = 0;
in_w = in_w - in_x0; // in_x0 < in_w because in_w > -dx = in_x0
}
else {
in_x0 = 0;
out_x0 = static_cast<uint32_t>(dx);
}
// we know that dx >= 0 && dx < out_w
if (static_cast<uint32_t>(dx) > UINT32_MAX - in_w ||
dx + in_w > out_w) {
// overlay image extends partially outside of right border
in_w = out_w - static_cast<uint32_t>(dx); // we know that dx < out_w from first condition
}
if (dy > 0 && static_cast<uint32_t>(dy) >= out_h) {
// the overlay image is completely outside the bottom border -> skip overlaying
return Error::Ok;
}
else if (dy < 0 && in_h <= negate_negative_int32(dy)) {
// the overlay image is completely outside the top border -> skip overlaying
return Error::Ok;
}
if (dy < 0) {
// overlay image started partially outside of top border
in_y0 = negate_negative_int32(dy);
out_y0 = 0;
in_h = in_h - in_y0; // in_y0 < in_h because in_h > -dy = in_y0
}
else {
in_y0 = 0;
out_y0 = static_cast<uint32_t>(dy);
}
// we know that dy >= 0 && dy < out_h
if (static_cast<uint32_t>(dy) > UINT32_MAX - in_h ||
dy + in_h > out_h) {
// overlay image extends partially outside of bottom border
in_h = out_h - static_cast<uint32_t>(dy); // we know that dy < out_h from first condition
}
for (uint32_t y = in_y0; y < in_h; y++) {
if (!has_alpha) {
memcpy(out_p + out_x0 + (out_y0 + y - in_y0) * out_stride,
in_p + in_x0 + y * in_stride,
in_w - in_x0);
}
else {
for (uint32_t x = in_x0; x < in_w; x++) {
uint8_t* outptr = &out_p[out_x0 + (out_y0 + y - in_y0) * out_stride + x];
uint8_t in_val = in_p[in_x0 + y * in_stride + x];
uint8_t alpha_val = alpha_p[in_x0 + y * in_stride + x];
*outptr = (uint8_t) ((in_val * alpha_val + *outptr * (255 - alpha_val)) / 255);
}
}
}
}
return Error::Ok;
}