我用Java创建简单的BMP图像。不幸的是,当宽度或高度的大小超过255的十进制值(十六进制的FF值)时,我不知道如何将宽度和高度大小信息存储到DIB头中。要创建小尺寸图像(255x255),我只需输入
表示宽度: FF 00 00 00 ,
表示身高: FF 00 00 00 。
我可以在一个地方输入的最大值是十六进制的FF(十进制数为255)。如何在这四个位置 00 00 00 00 中输入大于255(十六进制FF)的值,以便创建任何大尺寸图像,例如513x513像素?不知怎的,我必须使用其他零,但我无法在任何地方找到任何合适的解释。我应该如何在Java代码中实现这个原则?我会非常感谢任何帮助。
这是我的Java代码的一部分,用于向DIB标头输入大小值以创建不大于255x255的图像。
writer = new FileOutputStream(new File(onName));
// width
writer.write(255);
writer.write(0);
writer.write(0);
writer.write(0);
// height
writer.write(255);
writer.write(0);
writer.write(0);
writer.write(0);
这是我的完整Java代码:
package fractalTerrain.midpointDisplacement;
import java.io.*;
import java.util.Random;
// User: Fataho
// Date: 2015-01-10
public class MonochromeMidpointDisplacement {
private static final String onName = "src\\fractalTerrain\\midpointDisplacement\\test2.bmp";
private Random random = new Random();
private static final int H_GRID = 256;
private static final int V_GRID = 256;
public static void main(String[] args) {
MonochromeMidpointDisplacement midpointDisplacement = new MonochromeMidpointDisplacement();
midpointDisplacement.go();
}
private void go(){
// fillMap(map, min, max);
printMap();
}
public void printMap(){
// 3.0 output to file
// 3.1 Begin the file
// 3.1.1 open output file
FileOutputStream writer = null;
try {
writer = new FileOutputStream(new File(onName));
// 3.1.2 copy the header
// 3.1.2.1 magic number
writer.write(66);
writer.write(77);
// 3.1.2.2 file size/unused space
for (int i = 0; i < 8; i++){
writer.write(0);
}
// 3.1.2.3 data offset
writer.write(54);
// 3.1.2.4 unused space
for (int i = 0; i < 3; i++){
writer.write(0);
}
// 3.1.2.5 header size
writer.write(40);
// 3.1.2.6 unused space
for (int i = 0; i < 3; i++){
writer.write(0);
}
// 3.1.2.7 file width (trickier)
writer.write(255);
writer.write(0);
writer.write(0);
writer.write(0);
// 3.1.2.8 file height (trickier)
writer.write(255);
writer.write(0);
writer.write(0);
writer.write(0);
// 3.1.2.9 color planes
writer.write(1);
writer.write(0);
// 3.1.2.10 bit depth
writer.write(24);
// 3.1.2.11 the rest
for (int i = 0; i < 25; i++){
writer.write(0);
}
for(int g = 0; g < ((V_GRID) * (H_GRID )); g++){
writer.write(255);
writer.write(0);
writer.write(0);
}
for (int k = 0; k < (H_GRID % 4); k++){
writer.write(0);
}
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:1)
尝试移动值以写入更高的值
public void WriteDWORD(int i)
{
writer.write((byte)(i >> 24));
writer.write((byte)(i >> 16));
writer.write((byte)(i >> 8));
writer.write((byte)i);
}
也可能是小端(向后) 查看此维基百科有关endianness http://en.wikipedia.org/wiki/Endianness
的信息public void WriteDWORDLittleEndian(int i)
{
writer.write((byte)i);
writer.write((byte)(i >> 8));
writer.write((byte)(i >> 16));
writer.write((byte)(i >> 24));
}
同时检查您的作者是否有.writeLong
或.writeInt
或.writeInteger
等命令
所以你不必自己制作一个。
要获得这些命令,您必须执行http://docs.oracle.com/javase/7/docs/api/java/io/DataOutputStream.html
import java.io.DataOutputStream;
DataOutputStream dos = new DataOutputStream(writer);
dos.writeInt(1234567);
dos.close();
答案 1 :(得分:0)
我找到了解决方案。我将仅告诉如何存储宽度信息,因为高度信息以相同的方式存储。我们有4个字节来存储宽度信息,如下所示:
<00> 00 00 00 00此处存储的所有信息必须是十六进制,因此如果我们要存储255个宽度信息,我们会在前两个零中放置FF十六进制值(小数点为255),如下所示:
FF 00 00 00
如果我们想要存储更大的宽度,例如256,我们不能简单地在前两个零的位置输入100值(十六进制为256),如下所示:
100 00 00 00 这是非常错误而不是逻辑
相反,我们还必须使用这样的第二个零:
00 01 00 00
如果我们要存储257或258或259个宽度值,我们会这样做:
01 01 00 00 for 257
02 01 00 00 for 258
03 01 00 00 for 259
注意第二个2的零保持为01并且只改变前两个值。当前两个零点低于FF时会发生这种情况,当值变得高于FF时,我们必须将后两个值更改为02并再次开始向前两个零添加值。例如,如果我们想要存储到DIB头512或513或1024或1025中,我们必须这样做:
00 02 00 00 for 512
01 02 00 00 for 513
00 04 00 00 for 1024
01 04 00 00 for 1025
等等。我错了,但我相信这个系统被称为little-endian系统。正如已经提到的SSpoke,可以找到关于这些字节顺序的更多信息here。同样如SSpoke所述,要以Java或其他语言实现此原则,您必须使用按位运算&gt;&gt;来移动值。以下是实现此原则的代码:
writer.write(H_GRID % 256);
writer.write(H_GRID >> 8 % 256);
writer.write(H_GRID >> 16 % 256);
writer.write(H_GRID >> 24 % 256);
让我们使用这行代码V_GRID >> 8 % 256
并假设V_GRID值为257。
为简单起见,要理解这条线是如何工作的,我将告诉我如何理解它,但它可能与计算机的不同之处有所不同。将257转换为二进制数100000001,然后按位运算&gt;&gt;将此100000001二进制数向右移动8个值,得到1(100000001>&gt; 8 = 1)。最后1转换为十进制值(在本例中为1),我们得到提醒(也是1)然后我们将此值(1)放入BMP DIB头。可以找到关于按位运算的合适解释here。这是我的最终和完整的Java代码:
package fractalTerrain.midpointDisplacement;
import java.io.*;
import java.util.Random;
public class MonochromeMidpointDisplacement {
private static final String onName = "src\\fractalTerrain\\midpointDisplacement\\test2.bmp";
private Random random = new Random();
private static final int H_GRID = 257;
private static final int V_GRID = H_GRID;
public static void main(String[] args) {
MonochromeMidpointDisplacement midpointDisplacement = new MonochromeMidpointDisplacement();
midpointDisplacement.go();
}
private void go(){
// fillMap(map, min, max);
printMap();
}
public void printMap(){
// 3.0 output to file
// 3.1 Begin the file
// 3.1.1 open output file
FileOutputStream writer = null;
try {
writer = new FileOutputStream(new File(onName));
// 3.1.2 copy the header
// 3.1.2.1 magic number
writer.write(66);
writer.write(77);
// 3.1.2.2 file size/unused space
for (int i = 0; i < 8; i++){
writer.write(0);
}
// 3.1.2.3 data offset
writer.write(54);
// 3.1.2.4 unused space
for (int i = 0; i < 3; i++){
writer.write(0);
}
// 3.1.2.5 header size
writer.write(40);
// 3.1.2.6 unused space
for (int i = 0; i < 3; i++){
writer.write(0);
}
// 3.1.2.7 file width (trickier)
writer.write(H_GRID % 256);
writer.write(H_GRID >> 8 % 256);
writer.write(H_GRID >> 16 % 256);
writer.write(H_GRID >> 24 % 256);
// 3.1.2.8 file height (trickier)
writer.write(V_GRID % 256);
writer.write(V_GRID >> 8 % 256);
writer.write(V_GRID >> 16 % 256);
writer.write(V_GRID >> 24 % 256);
// 3.1.2.9 color planes
writer.write(1);
writer.write(0);
// 3.1.2.10 bit depth
writer.write(24);
// 3.1.2.11 the rest
for (int i = 0; i < 25; i++){
writer.write(0);
}
for(int i = 0; i < V_GRID; i++){
for(int g = 0; g < H_GRID; g++){
writer.write(255);
writer.write(0);
writer.write(0);
}
for (int k = 0; k < (H_GRID % 4); k++){
writer.write(0);
}
}
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}