java bufferedimage数组数据立即改变

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

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

最佳答案

问题是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/

相关文章:

javascript - 获取 Javascript 数组的唯一值

FFMPEG : Redirecting MP4 muxed data to socket

command-line - 如何在mac上安装最新的ffmpeg

linux - FFmpeg v4l2 复制不稳定

java - 我将如何完成这段java代码?

java - 如何将字节数组转换为人类可读的格式?

java - java中的ProcessBuilder环境变量

python - 构成 pandas dataframe 单元的数组的最大值

java - Java 中的继承和方法作用域

c - char[ ] 和 char * 存在缓冲区溢出漏洞