Я хочу сохранить видео того, что я показываю с помощью openGL, используя JOGL. Чтобы сделать это, я пишу свои кадры на рисунки следующим образом, а затем, как только я сохраню все кадры, я буду использовать ffmpeg. Я знаю, что это не лучший подход, но я до сих пор не очень ясно, как ускоряться с tex2dimage и PBOs. Любая помощь в этом направлении была бы очень полезной.glReadPixels возвращает больше данных, чем ожидалось
В любом случае, моя проблема в том, что если я запустил класс opengl, это будет работать, но если я вызову этот класс из другого класса, то вижу, что glReadPixels искажает мне ошибку. Он всегда возвращает больше данных в буфер, чем память была выделена для моего буфера «пикселейRGB». Кто-нибудь знает, почему?
В качестве примера: ширина = 1042; высота = 998. Размещенные = 3.119.748 glPixels вернулся = 3.121.742
public void display(GLAutoDrawable drawable) {
//Draw things.....
//bla bla bla
t++; //This is a time variable for the animation (it says to me the frame).
//Save frame
int width = drawable.getSurfaceWidth();
int height = drawable.getSurfaceHeight();
ByteBuffer pixelsRGB = Buffers.newDirectByteBuffer(width * height * 3);
gl.glReadPixels(0, 0, width,height, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, pixelsRGB);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
int[] pixels = new int[width * height];
int firstByte = width * height * 3;
int sourceIndex;
int targetIndex = 0;
int rowBytesNumber = width * 3;
for (int row = 0; row < height; row++) {
firstByte -= rowBytesNumber;
sourceIndex = firstByte;
for (int col = 0; col < width; col++) {
int iR = pixelsRGB.get(sourceIndex++);
int iG = pixelsRGB.get(sourceIndex++);
int iB = pixelsRGB.get(sourceIndex++);
pixels[targetIndex++] = 0xFF000000
| ((iR & 0x000000FF) << 16)
| ((iG & 0x000000FF) << 8)
| (iB & 0x000000FF);
}
}
bufferedImage.setRGB(0, 0, width, height, pixels, 0, width);
File a = new File(t+".png");
ImageIO.write(bufferedImage, "PNG", a);
}
ПРИМЕЧАНИЕ: с ответом pleluron теперь он работает. Хороший код:
public void display(GLAutoDrawable drawable) {
//Draw things.....
//bla bla bla
t++; //This is a time variable for the animation (it says to me the frame).
//Save frame
int width = drawable.getSurfaceWidth();
int height = drawable.getSurfaceHeight();
ByteBuffer pixelsRGB = Buffers.newDirectByteBuffer(width * height * 4);
gl.glReadPixels(0, 0, width,height, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, pixelsRGB);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
int[] pixels = new int[width * height];
int firstByte = width * height * 4;
int sourceIndex;
int targetIndex = 0;
int rowBytesNumber = width * 4;
for (int row = 0; row < height; row++) {
firstByte -= rowBytesNumber;
sourceIndex = firstByte;
for (int col = 0; col < width; col++) {
int iR = pixelsRGB.get(sourceIndex++);
int iG = pixelsRGB.get(sourceIndex++);
int iB = pixelsRGB.get(sourceIndex++);
sourceIndex++;
pixels[targetIndex++] = 0xFF000000
| ((iR & 0x000000FF) << 16)
| ((iG & 0x000000FF) << 8)
| (iB & 0x000000FF);
}
}
bufferedImage.setRGB(0, 0, width, height, pixels, 0, width);
File a = new File(t+".png");
ImageIO.write(bufferedImage, "PNG", a);
}
Скорее используйте com.jogamp.opengl.util.GLReadBufferUtil с com.jogamp.opengl.util.texture.TextureIO. Если вы используете его правильно, вы можете продолжать использовать тот же буфер (внутри объекта TextureData) для всех изображений, вы избавитесь от AWT, кодер JOGL PNG (на основе PNGJ) работает быстрее и имеет меньший объем памяти, чем AWT/Качели. – gouessej
Кстати, FFMPEG и LibAV уже используются под капотом в JOGL внутри медиаплеера. Возможно, вы можете посмотреть исходный код, чтобы узнать, как выложить необходимые методы для написания, это позволит вам использовать многочисленные файлы PNG. – gouessej