博客
关于我
BMP图存储—代码实现
阅读量:793 次
发布时间:2019-03-24

本文共 3206 字,大约阅读时间需要 10 分钟。

BMP图像存储(Java实现)

作为一名开发人员,我在研究如何在Java中实现BMP图像存储时遇到了许多挑战。本文将详细解释BMP图像的存储方式,并提供相应的代码实现。


一、24色位图的存储结构

BMP文件的存储结构可以分为以下几个部分:

  • BMP文件头

    包含指示BMP文件类型的标记 (82 4D) 和文件大小信息。

  • 位图信息头

    包含位图的宽度、高度、颜色数以及像素信息等参数。

  • 颜色索引表

    存储使用的颜色数组,这部分与实际使用的颜色数有关。

  • 位图数据

    存储实际的像素数据。


  • 二、24色位图的代码实现

    1. BMP文件头代码详解

    文件头是存储标记和文件大小的关键部分。以下是实现代码:

    public void saveBMP(BufferedOutputStream ops) throws IOException {    ops.write('B'); // 标记 B    ops.write('M'); // 标记 M    int size = 14 + 40 + height * width * 3 + ((4 - (width * 3 % 4)) * height); // 文件总大小    writeInt(ops, size);    writeShort(ops, (short) 0); // 信息偏移量    writeShort(ops, (short) 0); // 单位偏移量    writeInt(ops, 54); // 偏移量指向图像数据区}
    • size计算
      公式解析:
      • 14:文件头大小
      • 40:位图信息头大小
      • height * width * 3:每个像素占3字节(红、绿、蓝),总字节数
      • ((4 - (width * 3 % 4)) * height):比特补充部分(确保每行的字节数为4的倍数)

    2. 位图信息头代码详解

    位图信息头包含了位图的宽度、高度以及颜色信息。

    public void savebmpInfo(BufferedOutputStream ops) throws IOException {    writeInt(ops, 40); // 位图信息头大小    writeInt(ops, width); // 位图宽度    writeInt(ops, height); // 位图高度    writeShort(ops, (short) 1); // 颜色数    writeShort(ops, (short) 24); // 像素数    writeInt(ops, 0); // 无压缩信息    writeInt(ops, size - 54); // 偏移量指向颜色索引表    writeInt(ops, 0); // 水平分辨率(缺省)    writeInt(ops, 0); // 垂直分辨率(缺省)    writeInt(ops, 2); // 当前使用的颜色索引数    writeInt(ops, 2); // 当前使用的颜色索引数}

    3. 位图数据存储代码详解

    位图数据是存储像素信息的核心部分。

    public void savebmpData(BufferedOutputStream ops) throws IOException {    int m = 4 - (width * 3 % 4);    if (m > 0) {        System.out.println("补充字节数:" + m);    }    int[][] imgData = new int[width][height];    for (int i = 0; i < width; i++) {        for (int j = 0; j < height; j++) {            imgData[i][j] = image.getRGB(i, j); // 获取像素颜色值        }    }    for (int i = height - 1; i >= 0; i--) {        for (int j = 0; j < width; j++) {            int t = imgData[j][i];            writeColor(ops, t);        }    }    for (int k = 0; k < m; k++) {        ops.write(0);    }}

    三、问题与解决

    在实现过程中,主要遇到的问题包括:

  • 文件大小计算错误

    最终确认文件大小必须包含所有部分,避免遗漏。

  • 颜色写入顺序问题

    确保颜色的红、绿、蓝分量按正确顺序写入文件。

  • 比特补充处理不当

    需要确保每行的字节数符合4字节的倍数要求。


  • 四、单色位图的存储

    单色位图与24色位图的主要区别在于颜色索引表的存在。以下是实现代码:

    public void saveBMP(BufferedOutputStream ops) throws IOException {    ops.write('B');    ops.write('M');    int size = 14 + 40 + 8 + (height * width);    writeInt(ops, size);    writeShort(ops, (short) 0);    writeShort(ops, (short) 0);    writeInt(ops, 62);}

    五、代码工具与配套方法

    为了提高开发效率,可以编写以下工具方法:

    private void writeShort(BufferedOutputStream ops, short t) throws IOException {    int c = (t >> 8) & 0xff;    int d = t & 0xff;    ops.write(d);    ops.write(c);}private void writeInt(BufferedOutputStream ops, int t) throws IOException {    int a = (t >> 24) & 0xff;    int b = (t >> 16) & 0xff;    int c = (t >> 8) & 0xff;    int d = t & 0xff;    ops.write(d);    ops.write(c);    ops.write(b);    ops.write(a);}private byte[] divide(int num) {    byte[] bytes = new byte[4];    bytes[0] = (byte) (num & 0xff);    bytes[1] = (byte) ((num >> 8) & 0xff);    bytes[2] = (byte) ((num >> 16) & 0xff);    bytes[3] = (byte) ((num >> 24) & 0xff);    return bytes;}private int toGray(int t) {    int r = (t >> 16) & 0xff;    int g = (t >> 8) & 0xff;    int b = t & 0xff;    int gray = (int) (r * 0.3 + g * 0.59 + b * 0.11);    return gray;}

    通过以上详细的实现和优化,可以有效解决BMP图像存储问题。

    转载地址:http://bjekk.baihongyu.com/

    你可能感兴趣的文章
    mysql 修改默认字符集为utf8
    查看>>
    Mysql 共享锁
    查看>>
    MySQL 内核深度优化
    查看>>
    mysql 内连接、自然连接、外连接的区别
    查看>>
    mysql 写入慢优化
    查看>>
    mysql 分组统计SQL语句
    查看>>
    Mysql 分页
    查看>>
    Mysql 分页语句 Limit原理
    查看>>
    MySql 创建函数 Error Code : 1418
    查看>>
    MySQL 创建新用户及授予权限的完整流程
    查看>>
    mysql 创建表,不能包含关键字values 以及 表id自增问题
    查看>>
    mysql 删除日志文件详解
    查看>>
    mysql 判断表字段是否存在,然后修改
    查看>>
    MySQL 到底能不能放到 Docker 里跑?
    查看>>
    mysql 前缀索引 命令_11 | Mysql怎么给字符串字段加索引?
    查看>>
    MySQL 加锁处理分析
    查看>>
    mysql 协议的退出命令包及解析
    查看>>
    mysql 参数 innodb_flush_log_at_trx_commit
    查看>>
    mysql 取表中分组之后最新一条数据 分组最新数据 分组取最新数据 分组数据 获取每个分类的最新数据
    查看>>
    MySQL 命令和内置函数
    查看>>