读取 .bmp 图像并从图像的第 10 个字节中减去 10 并在 Java 中重新创建图像

Posted

技术标签:

【中文标题】读取 .bmp 图像并从图像的第 10 个字节中减去 10 并在 Java 中重新创建图像【英文标题】:Read .bmp image and subtract 10 from 10th byte of the image and re-create the image in Java 【发布时间】:2013-02-05 09:37:31 【问题描述】:

我正在创建一个应用程序,它将从 .bmp 图像中读取图像字节/像素/数据并将其存储在 byte/char/int/etc 数组中。

现在,从这个数组中,我想从数组的第 10 个索引中存储的数据中减去 10(十进制)。

我能够成功地将图像信息存储在创建的数组中。但是当我尝试将数组信息写回 .bmp 图像时,创建的图像是不可见的。

这是我尝试这样做的一段代码。

在这段代码中,我不是从数组的第 10 个索引中减去 10

public class Test1 

    public static void main(String[] args) throws IOException
        File inputFile = new File("d://test.bmp");
        FileReader inputStream = new FileReader("d://test.bmp");
        FileOutputStream outputStream = new FileOutputStream("d://test1.bmp");
        /*
         * Create byte array large enough to hold the content of the file.
         * Use File.length to determine size of the file in bytes.
         */
        char fileContent[] = new char[(int)inputFile.length()];


        for(int i = 0; i < (int)inputFile.length(); i++)
            fileContent[i] = (char) inputStream.read();
        

        for(int i = 0; i < (int)inputFile.length(); i++)
            outputStream.write(fileContent[i]);
        
    

【问题讨论】:

你为什么使用char[]?您没有文本数据。请改用byte[] “我想从数组的第 10 个索引中存储的数据中减去 10(十进制)。” 为什么? 我想在这张图片中隐藏一些信息,然后再检索相同的信息。我也尝试过使用 char[],它没有用。字节文件内容[] = 新字节[(int)inputFile.length()]; for(int i = 0; i 1) 这通常称为steganography。我已将标签添加到帖子中。 2)它通常不是通过更改File 中的特定字节来实现的,就像您似乎正在做的那样,而是通过图像或声音本身的“数据”来实现。在这种情况下,您会将 fie 读入 BufferedImage,操作图像本身,然后将其写回文件。 3)添加@JonSkeet(或任何人)以通知他们有新评论。 4) cmets 中的代码不可读。而是将edit 放入问题中并使用代码格式。 【参考方案1】:

用字节[]代替char[]

如果您的代码有效,这里是修改后的版本:

public class Test 

public static void main(String[] args) throws IOException 
    File inputFile = new File("someinputfile.bmp");
    FileOutputStream outputStream = new FileOutputStream("outputfile.bmp");
    /*
     * Create byte array large enough to hold the content of the file.
     * Use File.length to determine size of the file in bytes.
     */
    byte fileContent[] = new byte[(int)inputFile.length()];


    new FileInputStream(inputFile).read(fileContent);

    for(int i = 0; i < (int)inputFile.length(); i++)
        outputStream.write(fileContent[i]);
    

    outputStream.close();
 

【讨论】:

使用 byte[] 数组而不是 char[] 后仍然无法正常工作 你还记得关闭OutputStream吗?【参考方案2】:

要使现有代码正常工作,您应该将 FileReader 替换为 FileInputStream。根据 FileReader javadoc:

FileReader 用于读取字符流。要读取原始字节流,请考虑使用 FileInputStream。

如下修改您的示例

  public static void main(String[] args) throws IOException
 
File inputFile = new File("d://test.bmp");
FileInputStream inputStream = new FileInputStream("d://test.bmp");
FileOutputStream outputStream = new FileOutputStream("d://test1.bmp");
/*
 * Create byte array large enough to hold the content of the file.
 * Use File.length to determine size of the file in bytes.
 */
byte fileContent[] = new byte[(int)inputFile.length()];

for(int i = 0; i < (int)inputFile.length(); i++)
    fileContent[i] =  (byte) inputStream.read();


inputStream.close();
for(int i = 0; i < (int)inputFile.length(); i++)
    outputStream.write(fileContent[i]);


outputStream.flush();
outputStream.close();

这项工作为我创建了原始图像的副本。

尽管如上面的 cmets 中所述,这可能不是您要达到的目标的正确方法。

【讨论】:

【参考方案3】:

其他人指出您的代码中存在错误(主要使用 char 而不是 byte),但是,即使您修复了该问题,如果您更改文件中的第 10 个字节。

这是因为,.bmp 图像文件以包含有关文件信息(颜色深度、尺寸……请参阅BMP file format)的标题开头,然后是任何实际图像数据。具体来说,第 10 个字节是 4 字节整数的一部分,用于存储实际图像数据(像素阵列)的偏移量。所以从这个值中减去 10 可能会使偏移量指向文件中的错误点,并且您的图像加载器进行边界检查可能会认为这是无效的。

您真正想要做的是将图像加载为图像并直接操作像素值。类似的东西:

BufferedImage originalImage = ImageIO.read(new File("d://test.bmp"));
int rgb = originalImage.getRGB(10, 0);
originalImage.setRGB(rgb >= 10 ? rgb - 10 : 0);
ImageIO.write(originalImage, "bmp", new File("d://test1.bmp"));

【讨论】:

以上是关于读取 .bmp 图像并从图像的第 10 个字节中减去 10 并在 Java 中重新创建图像的主要内容,如果未能解决你的问题,请参考以下文章

将字节数组转换/显示为 bmp/jpeg 图像

用标准c读取某bmp文件的长宽及象素等信息需要哪些函数?

BMP字节数组到BMP图像php

如何使用 C++ 正确计算 BMP 图像中每个像素的字节数?

如何在java中从像素字节数组制作bmp图像

使用 qdbmp 读取.bmp 图像