mirror of
https://github.com/lovell/sharp.git
synced 2026-02-04 13:46:19 +01:00
Improve multi-frame image resizing (#2789)
* Ports vips_thumbnail logic to sharp * Deprecates the pageHeight output option for WebP/GIF
This commit is contained in:
committed by
GitHub
parent
659cdabd8e
commit
513fb40f40
@@ -308,4 +308,98 @@ namespace sharp {
|
||||
return image;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split and crop each frame, reassemble, and update pageHeight.
|
||||
*/
|
||||
VImage CropMultiPage(VImage image, int left, int top, int width, int height,
|
||||
int nPages, int *pageHeight) {
|
||||
if (top == 0 && height == *pageHeight) {
|
||||
// Fast path; no need to adjust the height of the multi-page image
|
||||
return image.extract_area(left, 0, width, image.height());
|
||||
} else {
|
||||
std::vector<VImage> pages;
|
||||
pages.reserve(nPages);
|
||||
|
||||
// Split the image into cropped frames
|
||||
for (int i = 0; i < nPages; i++) {
|
||||
pages.push_back(
|
||||
image.extract_area(left, *pageHeight * i + top, width, height));
|
||||
}
|
||||
|
||||
// Reassemble the frames into a tall, thin image
|
||||
VImage assembled = VImage::arrayjoin(pages,
|
||||
VImage::option()->set("across", 1));
|
||||
|
||||
// Update the page height
|
||||
*pageHeight = height;
|
||||
|
||||
return assembled;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Split into frames, embed each frame, reassemble, and update pageHeight.
|
||||
*/
|
||||
VImage EmbedMultiPage(VImage image, int left, int top, int width, int height,
|
||||
std::vector<double> background, int nPages, int *pageHeight) {
|
||||
if (top == 0 && height == *pageHeight) {
|
||||
// Fast path; no need to adjust the height of the multi-page image
|
||||
return image.embed(left, 0, width, image.height(), VImage::option()
|
||||
->set("extend", VIPS_EXTEND_BACKGROUND)
|
||||
->set("background", background));
|
||||
} else if (left == 0 && width == image.width()) {
|
||||
// Fast path; no need to adjust the width of the multi-page image
|
||||
std::vector<VImage> pages;
|
||||
pages.reserve(nPages);
|
||||
|
||||
// Rearrange the tall image into a vertical grid
|
||||
image = image.grid(*pageHeight, nPages, 1);
|
||||
|
||||
// Do the embed on the wide image
|
||||
image = image.embed(0, top, image.width(), height, VImage::option()
|
||||
->set("extend", VIPS_EXTEND_BACKGROUND)
|
||||
->set("background", background));
|
||||
|
||||
// Split the wide image into frames
|
||||
for (int i = 0; i < nPages; i++) {
|
||||
pages.push_back(
|
||||
image.extract_area(width * i, 0, width, height));
|
||||
}
|
||||
|
||||
// Reassemble the frames into a tall, thin image
|
||||
VImage assembled = VImage::arrayjoin(pages,
|
||||
VImage::option()->set("across", 1));
|
||||
|
||||
// Update the page height
|
||||
*pageHeight = height;
|
||||
|
||||
return assembled;
|
||||
} else {
|
||||
std::vector<VImage> pages;
|
||||
pages.reserve(nPages);
|
||||
|
||||
// Split the image into frames
|
||||
for (int i = 0; i < nPages; i++) {
|
||||
pages.push_back(
|
||||
image.extract_area(0, *pageHeight * i, image.width(), *pageHeight));
|
||||
}
|
||||
|
||||
// Embed each frame in the target size
|
||||
for (int i = 0; i < nPages; i++) {
|
||||
pages[i] = pages[i].embed(left, top, width, height, VImage::option()
|
||||
->set("extend", VIPS_EXTEND_BACKGROUND)
|
||||
->set("background", background));
|
||||
}
|
||||
|
||||
// Reassemble the frames into a tall, thin image
|
||||
VImage assembled = VImage::arrayjoin(pages,
|
||||
VImage::option()->set("across", 1));
|
||||
|
||||
// Update the page height
|
||||
*pageHeight = height;
|
||||
|
||||
return assembled;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sharp
|
||||
|
||||
Reference in New Issue
Block a user