Java 中的位图创建错误
Errors in bitmap creation in Java
我正在尝试从二维像素值数组创建位图。我在网上找到了一些代码(摘自http://forum.codecall.net/topic/62457-creating-a-bmp-image-in-java/):
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class BMP {
private final static int BMP_CODE = 19778;
byte [] bytes;
public void saveBMP(String filename, int [][] rgbValues){
try {
FileOutputStream fos = new FileOutputStream(new File(filename));
bytes = new byte[54 + 3*rgbValues.length*rgbValues[0].length + getPadding(rgbValues[0].length)*rgbValues.length];
saveFileHeader();
saveInfoHeader(rgbValues.length, rgbValues[0].length);
saveRgbQuad();
saveBitmapData(rgbValues);
fos.write(bytes);
fos.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
private void saveFileHeader() {
byte[]a=intToByteCouple(BMP_CODE);
bytes[0]=a[1];
bytes[1]=a[0];
a=intToFourBytes(bytes.length);
bytes[5]=a[0];
bytes[4]=a[1];
bytes[3]=a[2];
bytes[2]=a[3];
//data offset
bytes[10]=54;
}
private void saveInfoHeader(int height, int width) {
bytes[14]=40;
byte[]a=intToFourBytes(width);
bytes[22]=a[3];
bytes[23]=a[2];
bytes[24]=a[1];
bytes[25]=a[0];
a=intToFourBytes(height);
bytes[18]=a[3];
bytes[19]=a[2];
bytes[20]=a[1];
bytes[21]=a[0];
bytes[26]=1;
bytes[28]=24;
}
private void saveRgbQuad() {
}
private void saveBitmapData(int[][]rgbValues) {
int i;
for(i=0;i<rgbValues.length;i++){
writeLine(i, rgbValues);
}
}
private void writeLine(int row, int [][] rgbValues) {
final int offset=54;
final int rowLength=rgbValues[row].length;
final int padding = getPadding(rgbValues[0].length);
int i;
for(i=0;i<rowLength;i++){
int rgb=rgbValues[row][i];
int temp=offset + 3*(i+rowLength*row) + row*padding;
bytes[temp] = (byte) (rgb>>16);
bytes[temp +1] = (byte) (rgb>>8);
bytes[temp +2] = (byte) rgb;
}
i--;
int temp=offset + 3*(i+rowLength*row) + row*padding+3;
for(int j=0;j<padding;j++)
bytes[temp +j]=0;
}
private byte[] intToByteCouple(int x){
byte [] array = new byte[2];
array[1]=(byte) x;
array[0]=(byte) (x>>8);
return array;
}
private byte[] intToFourBytes(int x){
byte [] array = new byte[4];
array[3]=(byte) x;
array[2]=(byte) (x>>8);
array[1]=(byte) (x>>16);
array[0]=(byte) (x>>24);
return array;
}
private int getPadding(int rowLength){
int padding = (3*rowLength)%4;
if(padding!=0)
padding=4-padding;
return padding;
}
}
现在我尝试使用以下代码创建大小为 10x5 的位图:
int[][] bmpData = new int[10][5];
for(int x = 0; x < 10; x++) {
for(int y = 0; y < 5; y++) {
bmpData[x][y] = 127 | 127 << 8 | 127 << 16;
}
}
new BMP().saveBMP("test.bmp", bmpData);
我得到的结果不正确。我希望有一个 10x5 的灰色 bmp,但相反,我在图像中看到了一条淡黄色的垂直线。当绘制更大的图像 (100x50) 时,我得到这个:
看起来列被绘制成了行。我不确定这是为什么。我在源代码中找到了一些关于填充的内容,但我很难理解它是如何工作的。
谁能解释一下这种行为?请注意,我没有在 Android 上工作,所以我无法使用 Bitmap
class.
在我看来,这段代码没有按预期工作。
检查这部分,例如:
saveInfoHeader(rgbValues.length, rgbValues[0].length);
saveInfoHeader
有这个签名:
saveInfoHeader(int height, int width)
因此,当您通过 int[100][50];
时,您应该得到 高度 100 和宽度 50.
的 bmp
我想这部分代码不正确:
byte[]a=intToFourBytes(width);
bytes[22]=a[3];
bytes[23]=a[2];
bytes[24]=a[1];
bytes[25]=a[0];
a=intToFourBytes(height);
bytes[18]=a[3];
bytes[19]=a[2];
bytes[20]=a[1];
bytes[21]=a[0];
按照 BMP 标准,宽度应该在高度之前声明,这里的宽度处理得更早,但是(我想,通过编辑错误)它被写入了更大的偏移量。
如果将其更改为:
byte[]a=intToFourBytes(width);
bytes[18]=a[3];
bytes[19]=a[2];
bytes[20]=a[1];
bytes[21]=a[0];
a=intToFourBytes(height);
bytes[22]=a[3];
bytes[23]=a[2];
bytes[24]=a[1];
bytes[25]=a[0];
,你会得到这样的结果:
您得到的图案是由于 height/width 不匹配导致 BMP 填充计算错误的结果。
我正在尝试从二维像素值数组创建位图。我在网上找到了一些代码(摘自http://forum.codecall.net/topic/62457-creating-a-bmp-image-in-java/):
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class BMP {
private final static int BMP_CODE = 19778;
byte [] bytes;
public void saveBMP(String filename, int [][] rgbValues){
try {
FileOutputStream fos = new FileOutputStream(new File(filename));
bytes = new byte[54 + 3*rgbValues.length*rgbValues[0].length + getPadding(rgbValues[0].length)*rgbValues.length];
saveFileHeader();
saveInfoHeader(rgbValues.length, rgbValues[0].length);
saveRgbQuad();
saveBitmapData(rgbValues);
fos.write(bytes);
fos.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
private void saveFileHeader() {
byte[]a=intToByteCouple(BMP_CODE);
bytes[0]=a[1];
bytes[1]=a[0];
a=intToFourBytes(bytes.length);
bytes[5]=a[0];
bytes[4]=a[1];
bytes[3]=a[2];
bytes[2]=a[3];
//data offset
bytes[10]=54;
}
private void saveInfoHeader(int height, int width) {
bytes[14]=40;
byte[]a=intToFourBytes(width);
bytes[22]=a[3];
bytes[23]=a[2];
bytes[24]=a[1];
bytes[25]=a[0];
a=intToFourBytes(height);
bytes[18]=a[3];
bytes[19]=a[2];
bytes[20]=a[1];
bytes[21]=a[0];
bytes[26]=1;
bytes[28]=24;
}
private void saveRgbQuad() {
}
private void saveBitmapData(int[][]rgbValues) {
int i;
for(i=0;i<rgbValues.length;i++){
writeLine(i, rgbValues);
}
}
private void writeLine(int row, int [][] rgbValues) {
final int offset=54;
final int rowLength=rgbValues[row].length;
final int padding = getPadding(rgbValues[0].length);
int i;
for(i=0;i<rowLength;i++){
int rgb=rgbValues[row][i];
int temp=offset + 3*(i+rowLength*row) + row*padding;
bytes[temp] = (byte) (rgb>>16);
bytes[temp +1] = (byte) (rgb>>8);
bytes[temp +2] = (byte) rgb;
}
i--;
int temp=offset + 3*(i+rowLength*row) + row*padding+3;
for(int j=0;j<padding;j++)
bytes[temp +j]=0;
}
private byte[] intToByteCouple(int x){
byte [] array = new byte[2];
array[1]=(byte) x;
array[0]=(byte) (x>>8);
return array;
}
private byte[] intToFourBytes(int x){
byte [] array = new byte[4];
array[3]=(byte) x;
array[2]=(byte) (x>>8);
array[1]=(byte) (x>>16);
array[0]=(byte) (x>>24);
return array;
}
private int getPadding(int rowLength){
int padding = (3*rowLength)%4;
if(padding!=0)
padding=4-padding;
return padding;
}
}
现在我尝试使用以下代码创建大小为 10x5 的位图:
int[][] bmpData = new int[10][5];
for(int x = 0; x < 10; x++) {
for(int y = 0; y < 5; y++) {
bmpData[x][y] = 127 | 127 << 8 | 127 << 16;
}
}
new BMP().saveBMP("test.bmp", bmpData);
我得到的结果不正确。我希望有一个 10x5 的灰色 bmp,但相反,我在图像中看到了一条淡黄色的垂直线。当绘制更大的图像 (100x50) 时,我得到这个:
看起来列被绘制成了行。我不确定这是为什么。我在源代码中找到了一些关于填充的内容,但我很难理解它是如何工作的。
谁能解释一下这种行为?请注意,我没有在 Android 上工作,所以我无法使用 Bitmap
class.
在我看来,这段代码没有按预期工作。
检查这部分,例如:
saveInfoHeader(rgbValues.length, rgbValues[0].length);
saveInfoHeader
有这个签名:
saveInfoHeader(int height, int width)
因此,当您通过 int[100][50];
时,您应该得到 高度 100 和宽度 50.
我想这部分代码不正确:
byte[]a=intToFourBytes(width);
bytes[22]=a[3];
bytes[23]=a[2];
bytes[24]=a[1];
bytes[25]=a[0];
a=intToFourBytes(height);
bytes[18]=a[3];
bytes[19]=a[2];
bytes[20]=a[1];
bytes[21]=a[0];
按照 BMP 标准,宽度应该在高度之前声明,这里的宽度处理得更早,但是(我想,通过编辑错误)它被写入了更大的偏移量。
如果将其更改为:
byte[]a=intToFourBytes(width);
bytes[18]=a[3];
bytes[19]=a[2];
bytes[20]=a[1];
bytes[21]=a[0];
a=intToFourBytes(height);
bytes[22]=a[3];
bytes[23]=a[2];
bytes[24]=a[1];
bytes[25]=a[0];
,你会得到这样的结果:
您得到的图案是由于 height/width 不匹配导致 BMP 填充计算错误的结果。