我不确定为什么在您的特定示例中需要进行检查。如果目标图像不使用 alpha 通道(它都是不透明的),您可以简单地使用源图像的 alpha 通道覆盖数据。
顺便说一句,如果您使用的是pixels[],则应该使用单个循环:
PImage withAlpha;
PImage noAlpha;
void setup(){
size(120, 130);
background(0);
withAlpha = loadImage("8fXFk.png");
noAlpha = loadImage("AOsi0.png");
copyAlphaChannel(withAlpha, noAlpha);
}
void draw(){
background(map(sin(frameCount * 0.1), -1.0, 1.0, 0, 192), 0, 0);
image(withAlpha, 0, 0);
image(noAlpha, 60, 0);
}
void copyAlphaChannel(PImage src, PImage dst){
// quick error check
if(src.width != dst.width || src.height != dst.height){
println(String.format("error, mismatching dimensions src(%d,%d) != dst(%d,%d)",
src.width, src.height, dst.width, dst.height));
return;
}
// load pixel data
src.loadPixels();
dst.loadPixels();
int numPixels = src.pixels.length;
// for each pixel
for(int i = 0 ; i < numPixels; i++){
// extract source alpha
int srcAlpha = (src.pixels[i] >> 24) & 0xFF;
// apply it to the destination image
// src alpha | dst RGB
dst.pixels[i] = srcAlpha << 24 | (dst.pixels[i] & 0xFFFFFF);
}
dst.updatePixels();
}
更新感谢您指出这一点:我错过了这个细节。
PImage 可以有三种格式:
RGB (=1)
ARGB (=2)
ALPHA(=4)
将RGB 格式PImage 转换为ARGB 格式的一种解决方法是应用不透明的mask():
PImage withAlpha;
PImage noAlpha;
void setup(){
size(120, 130);
background(0);
withAlpha = loadImage("8fXFk.png");
noAlpha = loadImage("AOsi0.png");
println("before",withAlpha.format, noAlpha.format, ARGB, RGB); // notice noAlpha's format is RGB
forceAlphaChannel(noAlpha);
println("after",withAlpha.format, noAlpha.format, ARGB, RGB); // notice noAlpha's format is ARGB
copyAlphaChannel(withAlpha, noAlpha);
noAlpha.save("test.png");
}
void draw(){
background(map(sin(frameCount * 0.1), -1.0, 1.0, 0, 192), 0, 0);
image(withAlpha, 0, 0);
image(noAlpha, 60, 0);
}
void forceAlphaChannel(PImage src){
// make an opaque mask
PImage mask = createImage(src.width, src.height, ALPHA);
java.util.Arrays.fill(mask.pixels, color(255));
mask.updatePixels();
// apply the mask force the RGB image into ARGB format
src.mask(mask);
}
void copyAlphaChannel(PImage src, PImage dst){
// quick error check
if(src.width != dst.width || src.height != dst.height){
println(String.format("error, mismatching dimensions src(%d,%d) != dst(%d,%d)",
src.width, src.height, dst.width, dst.height));
return;
}
// load pixel data
src.loadPixels();
dst.loadPixels();
int numPixels = src.pixels.length;
// for each pixel
for(int i = 0 ; i < numPixels; i++){
// extract source alpha
int srcAlpha = (src.pixels[i] >> 24) & 0xFF;
// apply it to the destination image
// src alpha | dst RGB
dst.pixels[i] = srcAlpha << 24 | (dst.pixels[i] & 0xFFFFFF);
}
dst.updatePixels();
}
由于上述循环遍历像素很多次(一次创建蒙版,然后再次应用它),首先创建ARGBPImage,然后复制RGB数据可能更有效来自一个PImage 和另一个ALPHA:
PImage withAlpha;
PImage noAlpha;
void setup(){
size(120, 130);
background(0);
withAlpha = loadImage("8fXFk.png");
noAlpha = loadImage("AOsi0.png");
println("before",withAlpha.format, noAlpha.format, ARGB, RGB); // notice noAlpha's format is RGB
noAlpha = getAlphaChannelCopy(withAlpha, noAlpha);
println("after",withAlpha.format, noAlpha.format, ARGB, RGB); // notice noAlpha's format is ARGB
noAlpha.save("test.png");
}
void draw(){
background(map(sin(frameCount * 0.1), -1.0, 1.0, 0, 192), 0, 0);
image(withAlpha, 0, 0);
image(noAlpha, 60, 0);
}
// copy src alpha and dst rgb into new ARGB PImage
PImage getAlphaChannelCopy(PImage src, PImage dst){
// quick error check
if(src.width != dst.width || src.height != dst.height){
println(String.format("error, mismatching dimensions src(%d,%d) != dst(%d,%d)",
src.width, src.height, dst.width, dst.height));
return null;
}
PImage out = createImage(src.width, src.height, ARGB);
// load pixel data
src.loadPixels();
dst.loadPixels();
out.loadPixels();
int numPixels = src.pixels.length;
// for each pixel
for(int i = 0 ; i < numPixels; i++){
// extract source alpha
int srcAlpha = (src.pixels[i] >> 24) & 0xFF;
// apply it to the destination image
// src alpha | dst RGB
out.pixels[i] = srcAlpha << 24 | (dst.pixels[i] & 0xFFFFFF);
}
out.updatePixels();
return out;
}
(这里唯一的小缺点是loadPixels() 三次:每张图片一次。)