我正在使用VideoSurfaceView来渲染已过滤的视频。我正在根据我的需要购买更改片段着色器。现在我想在更改相同格式的文件(例如mp4 - h264)后保存/渲染视频,但找不到如何操作。
PS - 将纹理保存为位图并将位图保存到文件很简单,但我可以找到如何使用视频...
这里有专家吗?
答案 0 :(得分:0)
正如您已经发现并在评论中说的,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
等而异。您可以在Oracle文档中了解不同的DataBuffers
,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