java bufferedimage数组数据立即更改

时间:2016-03-25 20:32:23

标签: java arrays ffmpeg bufferedimage

    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);
    }

我不明白为什么我会反复获得相同的图像。 如果需要进一步的信息,请知道,这是我在线的第一个编程问题...通常找到我正在寻找的其他人提出的问题。无法找到这个。 谢谢你的时间 肯

1 个答案:

答案 0 :(得分:0)

问题是grab()。getBufferedImage()每次都在同一个缓冲区中工作。在循环中为该缓冲区分配引用时,您将分配对相同缓冲区numofFrames次的引用。那你写的不是第一帧,而是最后一帧。为了解决这个问题,你需要做一个&#34;深层复制&#34; 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&GT;我更新了代码以使用bytedeco库的1.1版本。