我正在使用间隔拍摄摄影,并试图通过将多张照片混合到一帧来实现脚本来平滑过渡。像照片1到30一样产生第1帧,照片2到31产生第2帧,依此类推。
当我尝试用GIMP合并30张连续照片时,效果非常顺畅;当我使用Java BufferedImages和AlphaComposite实现相同的逻辑时,我得到了似乎不可接受的压缩工件。
我已经尝试了不同的东西,比如用无压缩的ImageWriter替换ImageIO.write(),但结果几乎相同。现在我没有想法。可能是AlphaComposite混合会导致质量损失吗?
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
public class SimplePhotoBlender {
public static void main(String[] args) throws IOException {
if (args.length < 1)
System.out.println("Usage: java SimplePhotoBlender <PATH_TO_IMAGE_FOLDER>");
else
new SimplePhotoBlender(args[0]);
}
public SimplePhotoBlender(String path) throws IOException {
// Get all images in folder
List<File> fileList = getFilesInFolder(new File(path));
Collections.sort(fileList);
// Iterate through the list ...
for (int i = 0; i < fileList.size(); i++) {
File originalImage = fileList.get(i);
BufferedImage blended = ImageIO.read(originalImage);
// ... and blend it with the following 30 images.
for (int j = 1; j <= 30 && i + j < fileList.size() - 1; j++)
blended = blend(blended, ImageIO.read(fileList.get(i + j)), 0.9);
// Finally, save it in a new file.
File blendedFile = new File(originalImage.getParent() + "/blended/" + originalImage.getName());
blendedFile.getParentFile().mkdirs();
blendedFile.createNewFile();
// I double-checked but the JPG compression in ImageIO.write()
// doesn't account for the tremendous amount of quality loss.
ImageIO.write(blended, "jpg", blendedFile);
}
}
// Needless to say that I copied this from the sources like
// http://www.informit.com/articles/article.aspx?p=1245201&seqNum=2
private BufferedImage blend(BufferedImage bi1, BufferedImage bi2, double weight) {
BufferedImage bi3 = new BufferedImage(bi1.getWidth(), bi1.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi3.createGraphics();
g2d.drawImage(bi1, null, 0, 0);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) (1.0 - weight)));
g2d.drawImage(bi2, null, 0, 0);
g2d.dispose();
return bi3;
}
public List<File> getFilesInFolder(final File folder) {
List<File> fileNames = new ArrayList<>();
for (final File fileEntry : folder.listFiles())
if (!fileEntry.isDirectory())
fileNames.add(fileEntry);
return fileNames;
}
}