读取 .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 中重新创建图像的主要内容,如果未能解决你的问题,请参考以下文章