源码中实现了一个功能:能够把二维数组的值,保存在BMP图片中。从而形象的观察数据峰值等在数组中的分布情况。实现基于Java,不依赖任何第三方库。
默认生成灰度图,也可生成彩色图。数组的值取值范围0-255(彩色的图建议取值范围0-192,即红到紫的颜色部分)。
图片效果:(0->255)
调用示例:
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
byte[][] bitmap = new byte[100][256];
for (byte[] x : bitmap) {
for (int i = 0; i < x.length; i++) {
x[i] = (byte) i;
}
}
try {
BitmapFile bitmapFile = new BitmapFile(bitmap);
// bitmapFile.setGrayColors();
bitmapFile.setHueColors();
bitmapFile.drawBitmap(new File("test.bmp"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
实现源码:
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
class BitmapFile {
private final int[] mColors = new int[256]; // 调色板
private final byte[][] mBitmap;
public BitmapFile(byte[][] bitmap) {
mBitmap = bitmap;
setGrayColors();
}
private static void writeShort(OutputStream os, short s) throws IOException {
os.write((byte) (s & 0xFF));
os.write((byte) ((s >> 8) & 0xFF));
}
private static void writeInt(OutputStream os, int i) throws IOException {
os.write((byte) (i & 0xFF));
os.write((byte) ((i >> 8) & 0xFF));
os.write((byte) ((i >> 16) & 0xFF));
os.write((byte) ((i >> 24) & 0xFF));
}
private static int rangeColor(int c) {
if (c < 0) return 0;
else if (c > 255) return 255;
else return c;
}
private void writeFileHeader(OutputStream os) throws IOException {
int size = ((mBitmap[0].length + 3) / 4 * 4) * mBitmap.length;
int offset = 14 + 40 + 256 * 4;
// 位图文件头,共14字节
writeShort(os, (short) 0x4D42); // 文件标识
writeInt(os, offset + size); // 文件大小
writeInt(os, 0); // 保留
writeInt(os, offset); // 从头到点阵数据的偏移
}
private void writeInfoHeader(OutputStream os) throws IOException {
int size = ((mBitmap[0].length + 3) / 4 * 4) * mBitmap.length;
// 位图信息头,共40字节
writeInt(os, 40); // 位图信息头的大小
writeInt(os, mBitmap[0].length); // 位图的宽度
writeInt(os, mBitmap.length); // 位图的高度
writeShort(os, (short) 1); // 颜色平面数
writeShort(os, (short) 8); // 比特数/像素数
writeInt(os, 0); // 压缩类型,BI_RGB(0)为不压缩
writeInt(os, size); // 点阵数据大小
writeInt(os, 0); // 水平分辨率
writeInt(os, 0); // 垂直分辨率
writeInt(os, 0); // 调色板的颜色数,为0则颜色数为2的biBitCount次方
writeInt(os, 0); // 重要的颜色数,0代表所有颜色都重要
// 调色板
for (int i = 0; i < 256; i++) {
writeInt(os, mColors[i]);
}
}
private void writeBitmapData(OutputStream os) throws IOException {
for (byte[] x : mBitmap) {
os.write(x);
switch (x.length % 4) {
case 1: os.write((byte) 0);
case 2: os.write((byte) 0);
case 3: os.write((byte) 0);
case 0:
default: break;
}
}
}
public void setGrayColors() {
for (int i = 0; i < 256; i++) {
mColors[i] = i * 0x00010101;
}
}
public void setHueColors(int saturate, int bright) {
// HSB(HSV)颜色空间
saturate = rangeColor(saturate);
bright = rangeColor(bright);
float s = saturate / 255f * bright;
int r, g, b;
for (int i = 0; i < 256; i++) {
float hue = i / 256f * 6;
float dh = hue - (int) hue;
r = g = b = bright;
if (hue < 1) { // 红->黄
g -= s * (1 - dh);
b -= s;
} else if (hue < 2) { // 黄->绿
r -= s * dh;
b -= s;
} else if (hue < 3) { // 绿->青
r -= s;
b -= s * (1 - dh);
} else if (hue < 4) { // 青->蓝
r -= s;
g -= s * dh;
} else if (hue < 5) { // 蓝->品红
r -= s * (1 - dh);
g -= s;
} else { // 品红->红
g -= s;
b -= s * dh;
}
mColors[i] = (rangeColor(r) << 16) | (rangeColor(g) << 8) | rangeColor(b);
}
}
public void setHueColors() {
setHueColors(255, 255);
}
public void drawBitmap(OutputStream os) throws IOException {
writeFileHeader(os);
writeInfoHeader(os);
writeBitmapData(os);
}
public void drawBitmap(File file) throws IOException {
OutputStream os = new FileOutputStream(file);
os = new BufferedOutputStream(os);
drawBitmap(os);
os.close();
}
}