从数据转储中提取 JPEG/PNG/GIF 图像

Posted

技术标签:

【中文标题】从数据转储中提取 JPEG/PNG/GIF 图像【英文标题】:Extracting JPEG/PNG/GIF Images from Data dump 【发布时间】:2017-07-24 15:23:37 【问题描述】:

我收到了磁盘中数据的二进制/十六进制转储。我的任务是从中提取图像。它是 JPEG、PNG 和 GIF 图像的混合转储。

你可以在link找到数据文件。

图片页眉和页脚

jpg:
 header: FF D8 FF E0 xx xx 4A 46 49 46 00, footer: FF D9
png:
 header: 89 50 4E 47 0D 0A 1A 0A, footer: 49 45 4E 44 AE 42 60 82
gif:
 header: 47 49 46 38 39 61, footer: 00 3B

在里面完好无损。如何使用 Java 提取图像?

【问题讨论】:

是的,看起来寻找标题将是一个非常好的开始......现在您可以搜索方法来做到这一点。 我实际上不知道如何处理这些数据...... 搜索:java中的二分查找 “不知道如何处理这些数据……” 到底是什么问题?你的意思是你不知道byteArray 是什么?或者你不能在字节内移动?或者您不能创建While 循环来搜索字节内的值?或者你甚至不能将你的十六进制转储带入 Java?您需要什么帮助? 【参考方案1】:

我建议你:

    FileInputStream 的形式打开输入文件。 扫描输入,直到找到其中一个标题。 为输出文件打开一个新的FileOutputStream,使用正确的图像文件扩展名,并将内容复制到该文件,直到找到相应的页脚。 关闭输出流。 从第 2 步重新开始,直到到达流的末尾。 关闭输入流。完成。

【讨论】:

【参考方案2】:

Download的源代码和Marco Schmidt's jpegextractor的字节码。

这适用于 jpg。

对于png

copyJpeg 函数替换为

private void copypng(InputStream in, OutputStream out) throws
    IOException

    boolean notFinished = true;
    long copiedBytes = 3;
    do
    
        int v1 = in.read();
        if (v1 == 0x89) // marker
        
            int v2 = in.read();
            if (v2 < 0) // end of file
            
                out.write(0x82);
                copiedBytes++;
                notFinished = false;
            
            else
            if (v2 == 0x49) // embedded png stream ended
            
                // copy the end of stream marker
                out.write(0x49);
                out.write(0x45);
                out.write(0x4E);
                out.write(0x44);
                out.write(0xAE);
                out.write(0x42);
                out.write(0x60);
                out.write(0x82);
                copiedBytes += 2;
                notFinished = false;
            
            else
            
                // copy the two bytes, just a marker of the embedded png
                out.write(0x89);
                out.write(v2);
                copiedBytes += 2;
            
        
        else
        if (v1 == -1) // unexpected end of input file
        
            notFinished = false;
        
        else // just copy that value
        
            out.write(v1);
            copiedBytes++;
        
    
    while (notFinished);
    totalBytes += copiedBytes;
    if (!quiet)
    
        System.out.println(" (" + copiedBytes + " bytes)");
    
    totalOutputFiles++;
    // close output stream
    try
    
        out.close();
    
    catch (IOException ioe)
    
        // ignore error when closing output stream
    

并将process(InputStream in)替换为

private void process(InputStream in) throws
    IOException

    int v1;
    do
    
        v1 = in.read();
        if (v1 == 0x89)
        
            int v2 = in.read();
            if (v2 == 0x50)
            
                int v3 = in.read();
                if (v3 == 0x4E)
                
                    int v4 = in.read();
                    if (v4 == 0x47)
                    
                        int v5 = in.read();
                        if (v5 == 0x0D)
                        
                            int v6 = in.read();
                            if (v6 == 0x0A)
                            
                                int v7 = in.read();
                                if (v7 == 0x1A)
                                
                                    int v8 = in.read();
                                    if (v8 == 0x0A)
                                    
                                        OutputStream out = createNextOutputStream();
                                        out.write(v1);
                                        out.write(v2);
                                        out.write(v3);
                                        out.write(v4);
                                        out.write(v5);
                                        out.write(v6);
                                        out.write(v7);
                                        out.write(v8);
                                        copypng(in, out);
                                    
                                
                            
                        
                    
                
            
        
    
    while (v1 != -1);

对于 gif, 将copyJpeg 函数替换为

private void copygif(InputStream in, OutputStream out) throws
        IOException
    
        boolean notFinished = true;
        long copiedBytes = 3;
        do
        
            int v1 = in.read();
            if (v1 == 0x47) // marker
            
                int v2 = in.read();
                if (v2 < 0) // end of file
                
                    out.write(0x00);
                    copiedBytes++;
                    notFinished = false;
                
                else
                if (v2 == 0x21) // embedded png stream ended
                
                    // copy the end of stream marker
                    out.write(0x21);
                    out.write(0x00);
                    out.write(0x00);
                    out.write(0x3B);
                    out.write(0x00);
                    copiedBytes += 2;
                    notFinished = false;
                
                else
                
                    // copy the two bytes, just a marker of the embedded png
                    out.write(0x47);
                    out.write(v2);
                    copiedBytes += 2;
                
            
            else
            if (v1 == -1) // unexpected end of input file
            
                notFinished = false;
            
            else // just copy that value
            
                out.write(v1);
                copiedBytes++;
            
        
        while (notFinished);
        totalBytes += copiedBytes;
        if (!quiet)
        
            System.out.println(" (" + copiedBytes + " bytes)");
        
        totalOutputFiles++;
        // close output stream
        try
        
            out.close();
        
        catch (IOException ioe)
        
            // ignore error when closing output stream
        
    

process(InputStream in)替换为

private void process(InputStream in) throws
    IOException

    int v1;
    do
    
        v1 = in.read();
        if (v1 == 0x47)
        
            int v2 = in.read();
            if (v2 == 0x49)
            
                int v3 = in.read();
                if (v3 == 0x46)
                
                    int v4 = in.read();
                    if (v4 == 0x38)
                    
                        int v5 = in.read();
                        if (v5 == 0x39)
                        
                            int v6 = in.read();
                            if (v6 == 0x61)
                            
                                OutputStream out = createNextOutputStream();
                                out.write(v1);
                                out.write(v2);
                                out.write(v3);
                                out.write(v4);
                                out.write(v5);
                                out.write(v6);
                                copygif(in, out);
                            
                        
                    
                
            
        
    
    while (v1 != -1);

并更新private void setDefaultArguments()outputSuffix的值

【讨论】:

以上是关于从数据转储中提取 JPEG/PNG/GIF 图像的主要内容,如果未能解决你的问题,请参考以下文章

我的训练数据集中的隐藏文件使 tensorflow 返回“未知的图像文件格式。需要 JPEG、PNG、GIF、BMP 之一。”

Tensorflow Keras 错误:未知的图像文件格式。需要 JPEG、PNG、GIF、BMP 之一

Head First HTML与CSS — 为你的页面加图像

如何在 PHP 中将图像从 base 64 转换为它们的文件类型?

Flutter之Image Widget(六)

Flutter 基本组件之Image