我想在游戏中添加截图功能。
int width = 320;
int height = width / 4*3;
pixels是一个int [],它包含与屏幕上任何时间出现的每个像素相对应的76800 RGB int值
public static void buildBitmap() {
File f = new File("C:/scr/game_name" + LocalDate.now().toString() +".bmp");
try(FileOutputStream fos = new FileOutputStream(f)){
fos.write(66);
fos.write(77);
fos.write(230428); //width * height * 3
fos.write(0);
fos.write(0);
fos.write(0);
fos.write(0);
fos.write(0);
fos.write(0);
fos.write(0);
fos.write(26);
fos.write(0);
fos.write(0);
fos.write(0);
fos.write(12);
fos.write(0);
fos.write(0);
fos.write(0);
fos.write(320);
fos.write(0);
fos.write(240);
fos.write(0);
fos.write(1);
fos.write(0);
fos.write(24);
fos.write(0);
for(int y = height-1; y > 0; y--) {
for(int x = 0; x < width-1; x++){
fos.write(pixels[x + y * width] & 0xFF); //blue
fos.write((pixels[x + y * width] >> 8) & 0xFF); //green
fos.write((pixels[x + y * width] >> 16) & 0xFF); //red
}
}
fos.write(0);
fos.write(0);
}catch(IOException e) {
e.printStackTrace();
}
System.out.println("Screenshot saved to " + f);
}
应该填充写入文件的嵌套循环,使实际的图像数据从数组的底部到顶部进行迭代:从左到右,将RGB int值转换为单独的蓝色,绿色,红色,并将它们写入文件(按此顺序)。
从数学上来说,声音是正确的,并且所产生的图像虽然变形和变形,但至少可以识别出来自游戏。我的代码有什么问题?
输出图像的宽度也是64,为什么呢?
答案 0 :(得分:0)
您需要确保标题正确。例如,标头中的文件大小字段需要为4个字节(请参阅:BMP file format)。要准确写出正确的字节数,可以使用DataOutputStream。
您需要反转值endianess。 Java是大端,而BMP文件是小端。 (请参阅代码中对reverseBytes
的所有调用。)
您的循环会忽略每一行和最后一行的最后一个字节。
您还忽略了位图跨度。这些是每行末尾的额外填充字节。由于示例的宽度为320像素,因此碰巧没有多余的字节,但是要处理奇数大小的宽度,您应该处理这些。
File f = new File("C:/scr/game_name" + LocalDate.now().toString() +".bmp");
try (FileOutputStream fos = new FileOutputStream(f)){
DataOutputStream dos = new DataOutputStream(fos);
int header_size = 14 + 40; // Size of both headers
int width = 320;
int height = 240;
short bpp = 24;
// Calculate the stride
int stride = 4 * ((width * bpp + 31) / 32);
// BITMAPFILEHEADER
dos.writeByte(66); // B
dos.writeByte(77); // M
int fileSize = (stride * height) + header_size;
dos.writeInt(Integer.reverseBytes(fileSize)); // Actual size of entire file
dos.writeShort(0); // Reserved
dos.writeShort(0); // Reserved
dos.writeInt(Integer.reverseBytes(header_size)); // starting address of bitmap image data
// BITMAPINFOHEADER
dos.writeInt(Integer.reverseBytes(40)); // Size of header
dos.writeInt(Integer.reverseBytes(width)); // Width
dos.writeInt(Integer.reverseBytes(height)); // Height
dos.writeShort(Short.reverseBytes((short)1)); // Color planes
dos.writeShort(Short.reverseBytes(bpp)); // BPP
dos.writeInt(0); // Compression method
dos.writeInt(0); // Image size
dos.writeInt(0); // Horizontal res
dos.writeInt(0); // Vertical res
dos.writeInt(0); // Number of colors
dos.writeInt(0); // Important colors
for (int y = height - 1; y >= 0; y--) {
for(int x = 0; x < width; x++) {
dos.writeByte(pixels[x + y * width] & 0xFF); //blue
dos.writeByte((pixels[x + y * width] >> 8) & 0xFF); //green
dos.writeByte((pixels[x + y * width] >> 16) & 0xFF); //red
}
// Add padding bytes
for (int s = width * 3; s < stride; s++) {
dos.writeByte(0);
}
}
fos.close();
}
catch(IOException e) {
e.printStackTrace();
}
从长远来看,最好找到一个可以为您完成所有工作的第三方库。