import javax.imageio.ImageIO;
import org.bytedeco.javacv.FFmpegFrameGrabber;
public class FrameData
{
int count = 0;
int picWidth;
int picHeight;
BufferedImage img = null;
//GET FRAME COUNT
public int gf_count(int numofFrames, BufferedImage[] frameArray, String fileLocationsent, String videoNamesent) throws IOException
{
String fileLocation = fileLocationsent;
String videoName = videoNamesent;
int frameNums = numofFrames;
int totFrames = 0;
FFmpegFrameGrabber grab = new FFmpegFrameGrabber(fileLocation + videoName);
try { grab.start(); }
catch (Exception e) { System.out.println("Unable to grab frames"); }
for(int i = 0 ; i < frameNums ; i++)
{
try
{
frameArray[i]= grab.grab().getBufferedImage();
totFrames = i;
File outputfile = new File(fileLocation + "GrayScaledImage" + i + ".jpg");
ImageIO.write(frameArray[i], "jpg", outputfile);
}
catch (Exception e) { /*e.printStackTrace();*/ }
}//END for
return totFrames;
}//END METHOD long getFrameCount()
希望有人可以向我解释这个...
我只是在学习java,所以这里......
我编写了这段代码来计算 .mov 文件中的帧数,并测试我生成的图像文件的缓冲图像数组。正如代码所示,它按计划工作......问题出在捕获后,如果我将缓冲图像作为文件发送出去,它们似乎都只是第一张图像。见下面的例子...
for(int i = 0 ; i < frameNums ; i++)
{
try
{
frameArray[i]= grab.grab().getBufferedImage();
totFrames = i;
File outputfile = new File(fileLocation + "GrayScaledImage" + i + ".jpg");
ImageIO.write(frameArray[i], "jpg", outputfile);
}
catch (Exception e) { /*e.printStackTrace();*/ }
}//END for
现在,如果我将其更改为...
for(int i = 0 ; i < frameNums ; i++)
{
try
{
frameArray[i]= grab.grab().getBufferedImage();
totFrames = i; catch (Exception e) { /*e.printStackTrace();*/ }}
for(int j = 0; j < frameNums; j++)
{
File outputfile = new File(fileLocation + "GrayScaledImage" + j + ".jpg");
ImageIO.write(frameArray[j], "jpg", outputfile);
}
我不明白为什么我会反复获得相同的图像。
如果需要更多信息,请让我知道,这是我在网上的第一个编程问题......通常会找到我正在寻找的其他人提出的问题。没找到这个。
谢谢你的时间
肯
最佳答案
问题是grab().getBufferedImage() 每次都在同一个缓冲区中工作。当您在循环中分配对该缓冲区的引用时,您将引用分配给相同的缓冲区 numofFrames 次。你写的不是第一帧,而是最后一帧。为了解决这个问题,您需要对 BufferedImage 进行“深拷贝”。请参见下面的代码:
public class FrameData {
BufferedImage img;
Graphics2D g2;
// GET FRAME COUNT
public int gf_count(int numFrames, BufferedImage[] frameArray, String fileLocation, String videoName) throws Exception, IOException {
Java2DFrameConverter converter = new Java2DFrameConverter();
int totFrames = 0;
img = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB);
g2 = img.createGraphics();
FFmpegFrameGrabber grab = new FFmpegFrameGrabber(fileLocation + videoName);
grab.start();
for (int i = 0; i < numFrames; i++) {
frameArray[i] = deepCopy(converter.convert(grab.grab()));
totFrames = i;
}
for (int j = 0; j < totFrames; j++) {
File outputfile = new File(fileLocation + "TImage" + j + ".jpg");
ImageIO.write(frameArray[j], "jpg", outputfile);
}
return totFrames;
}// END METHOD long getFrameCount()
BufferedImage deepCopy(BufferedImage bi) {
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(null);
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
// This does what the converter.convert seems to do, which
// is decode an image into the same place over and over.
// if you don't copy the result every time, then you end up
// with an array of references to the same last frame.
BufferedImage draw() {
g2.setColor(new Color(-1));
g2.fillRect(0, 0, 100, 50);
g2.setColor(new Color(0));
g2.drawLine(0, 0, (int)(Math.random()*100.0), (int)(Math.random()*50.0));
return img;
}
public static void main(String... args) throws Exception, IOException {
new FrameData().run();
}
private void run() throws Exception, IOException {
BufferedImage images[] = new BufferedImage[50];
gf_count(50, images, "C:/Users/karl/Videos/", "dance.mpg");
}
}
我已经包含了
draw()
该方法通过示例显示如何在同一个 BufferedImage 中重复完成工作,以防您想复制问题。当然还有其他方法可以进行深度复制,并且显示的方法可能存在问题。引用:How do you clone a BufferedImage .
PS> 我更新了代码使用1.1版本的bytedeco库。
关于java bufferedimage数组数据立即改变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36227586/