After unpacking the installation package and upgrade package of Arknights, there are extra pixels around the illustrations, which need to be obtained with the grayscale image separated to have an illustration image with an alpha channel.
It is quite simple to achieve this with sharp, so I wrote a small tool to complete this process (all illustrations are available for download in the repository at the end of the article).
Implementation with Sharp#
In the old version of sharp, it was possible to directly combine the grayscale image with the original image using the OverlayWith method to obtain an image with an alpha channel. However, in the new version, the OverlayWith method has been deprecated, so I implemented a similar function using the following method.
Ⅰ. Load the images to be processed#
Since sharp returns a Promise object, the entire code below will use async functions and await.
(async function () {
let mask = await sharp("mask.png"); // Load the grayscale image
let image = await sharp("origin.png"); // Load the original image
})()
Ⅱ. Get the channel information of the grayscale image#
To merge the grayscale image as an alpha channel, it is necessary to ensure that the original image does not have an alpha channel, and the grayscale image has only one channel. Only in this way can we ensure that the grayscale image is merged as an alpha channel into the original image.
What we need to do is to remove the alpha channel of the original image and keep only one channel of the grayscale image.
(async function () {
let mask = await sharp("mask.png") // Load the grayscale image
.extractChannel("red"); // Extract any channel of the grayscale image,
// it doesn't matter which channel is extracted here
let image = await sharp(`origin.png`) // Load the original image
.removeAlpha(); // Remove the alpha channel of the original image
})()
Ⅲ. Combine the two images#
(async function () {
let mask = await sharp("mask.png") // Load the grayscale image
.extractChannel("red"); // Extract any channel of the grayscale image,
// it doesn't matter which channel is extracted here
let image = await sharp(`origin.png`) // Load the original image
.removeAlpha(); // Remove the alpha channel of the original image
let maskBuffer = await mask.toBuffer();
let imageBuffer = await image.toBuffer();
sharp(imageBuffer) // Load the original image as a Buffer,
// actually this line can be replaced with 'image',
// but I wrote it like this to satisfy my OCD 😂
.joinChannel(maskBuffer) // Add the red channel of the grayscale image
// to the original image, because the alpha channel
// of the original image was removed earlier,
// it is actually re-adding the alpha channel
.toFile(`out.png`) // Output the final image
})()