正如您在 cmets 中已经发现并说的那样,OpenGL 不能将多个帧导出为视频。
虽然如果您只是想过滤/处理视频的每一帧,那么您根本不需要 OpenGL,也不需要片段着色器,您可以简单地自己循环遍历所有像素。
现在假设您一次处理一帧视频,每一帧都是一个BufferedImage,您当然可以使用任何您想要或提供的内容,只要您可以选择获取和设置像素。
我只是为您提供一种计算和应用过滤器的方法,您必须自己对视频文件进行解码和编码。
但回到BufferedImage,首先我们要获取BufferedImage 中的所有像素,我们使用以下方法来实现。
BufferedImage bi = ...; // Here you would get a frame from the video
int width = bi.getWidth();
int height = bi.getHeight();
int[] pixels = ((DataBufferInt) bi.getRaster().getDataBuffer()).getData();
请注意,根据图像的类型,如果图像包含透明度,DataBuffer 可能会在 DataBufferInt 到 DataBufferByte 之间变化,等等。您可以阅读不同的DataBuffers 在 Oracle 文档中,click here。
现在只需循环遍历图像中的像素,我们就可以应用和创建任何类型的效果和过滤。
假设我们要创建一个grayscale 效果,也称为black-and-white 效果,您可以通过以下方式进行。
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
final int index = x + y * width;
final int pixel = pixels[index];
final int alpha = (pixel >> 24) & 0xFF;
final int red = (pixel >> 16) & 0xFF;
final int green = (pixel >> 8) & 0xFF;
final int blue = pixel & 0xFF;
final int gray = (red + green + blue) / 3;
pixels[index] = alpha << 24 | gray << 16 | gray << 8 | gray;
}
}
现在您可以简单地再次保存图像,或做任何您想做的事情。虽然你也可以使用和绘制BufferedImage,因为BufferedImage提供的像素数组当然也会改变BufferedImage。
重要如果要执行模糊效果,则在计算每个像素后将其存储到另一个数组中,因为执行模糊效果需要周围的像素。因此,如果在计算所有像素时替换旧的一次,某些像素将使用计算值而不是实际值。
上面的代码当然也适用于图片。
额外
如果您想获取存储在单个 int 中的 RGBA 值,则可以执行以下操作。
int pixel = 0xFFFF8040; // This is a random testing value
int alpha = (pixel >> 24) & 0xFF; // Would equal 255 using the testing value
int red = (pixel >> 16) & 0xFF; // ... 255 ...
int green = (pixel >> 8) & 0xFF; // ... 128 ...
int blue = pixel & 0xFF; // ... 64 ...
如果您有 RGBA 值并希望将它们组合成一个 int,那么您可以执行以下操作。
int alpha = 255;
int red = 255;
int green = 128;
int blue = 64;
int pixel = alpha << 24 | red << 16 | green << 8 | blue;
如果您只有 RGB 值,那么您就可以,red << 16 | green << 8 | blue 或255 << 24 | red << 16 | green << 8 | blue