- 浏览: 205190 次
- 性别:
- 来自: 长沙
最新评论
-
螺旋懒虫:
原本是想自己画点阵的,一来画的不标准,也不好解析(用excel ...
超级详细解析——字模 -
螺旋懒虫:
这个程序解决了我怎么加载点阵字库文件的问题,和怎么去拿到汉字对 ...
超级详细解析——字模 -
慕容墨风:
你好,我用你的测试程序发现数字提取不了
超级详细解析——字模 -
文之若素:
求代码,我最近在学这个,公司需要,呜呜呜,159374403 ...
初学EXTJS做的系统界面 -
csrhlu:
为什么我压缩之后文件还变大了呢? 而且解压eclipse下边会 ...
自己动手写压缩软件,超详细解释(哈夫曼实现)
首先,对于BMP 格式的图片大家都不感觉到陌生吧。
简单的说明下:
BMP是一种与硬件设备无关的图像文件格式,使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此, BMP 文件所占用的空间很大。 BMP 文件的图像深度可选 lbit 、 4bit 、 8bit 及 24bit 。 BMP 文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。 由于 BMP 文件格式是 Windows 环境中交换与图有关的数据的一种标准,因此在 Windows 环境中运行的图形图像软件都支持 BMP 图像格式。
要解析文件,就必须知道他的文件结构
文件结构
组成
典型的BMP 图像文件由四部分组成:
1 : 位图文件 头数据结构 ,它包含BMP 图像文件的类型、显示内容等信息;
2 : 位图信息数据结构 ,它包含有BMP 图像的宽、高、压缩方法,以及定义颜色等信息;
3: 调色板 ,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24 位的 BMP )就不需要调色板;
4 : 位图数据 ,这部分的内容根据BMP 位图使用的位数不同而不同,在 24 位图中直接使用 RGB ,而其他的小于 24 位的使用调色板中颜色索引值。
对应的数据结构
1. BMP文件头 (14 字节 )
BMP文件头数据结构含有 BMP 文件的类型、文件大小和位图起始位置等信息。
其结构定义如下:
Int bfType; // 位图文件的类型,必须为 ' B '' M '两个字母 (0-1字节 )
Int bfSize; // 位图文件的大小,以字节为单位 (2-5 字节 )
usignedshort bfReserved1; // 位图文件保留字,必须为 0(6-7 字节 )
usignedshort bfReserved2; // 位图文件保留字,必须为 0(8-9 字节 )
Int bfOffBits; // 位图数据的起始位置,以相对于位图 (10-13 字节 )
Int bfOffBits ; / / 文件头的偏移量表示,以字节为单位
2 :位图信息头(40 字节 )
BMP 位图信息头数据用于说明位图的尺寸等信息。
Int Size ; // 本结构所占用字节数 (14-17 字节 )
Int image_width ; // 位图的宽度,以像素为单位 (18-21 字节 )
int image_heigh ; // 位图的高度,以像素为单位 (22-25 字节 )
Int Planes; // 目标设备的级别,必须为 1(26-27 字节 )
int n biBitCount;// 每个像素所需的位数,必须是 1( 双色 ),(28-29 字节 ) // 4(16 色 ) , 8(256 色 ) 或 24( 真彩色 ) 之一
Int biCompression; // 位图压缩类型,必须是 0( 不压缩 ),(30-33 字节 ) // 1(BI_RLE8 压缩类型 ) 或 2(BI_RLE4 压缩类型 ) 之一
Int n SizeImage; // 位图的大小,以字节为单位 (34-37 字节 )
Int biXPelsPerMeter; // 位图水平分辨率,每米像素数 (38-41 字节 )
Int biYPelsPerMeter; // 位图垂直分辨率,每米像素数 (42-45 字节 )
Int biClrUsed;// 位图实际使用的颜色表中的颜色数 (46-49 字节 )
Int biClrImportant;// 位图显示过程中重要的颜色数 (50-53 字节 )
3 :颜色表
颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD 类型的结构,定义一种颜色。
class RGBQUAD
{
byte rgbBlue;// 蓝色的亮度 ( 值范围为 0-255)
byte rgbGreen; // 绿色的亮度 ( 值范围为 0-255)
byte rgbRed; // 红色的亮度 ( 值范围为 0-255)
byte rgbReserved;// 保留,必须为 0
}
颜色表中RGBQUAD 结构数据的个数有 biBitCount 来确定 :
当biBitCount=1,4,8 时,分别有 2,16,256 个表项 ;
当biBitCount=24 时,没有颜色表项。
位图信息头和颜色表组成位图信息,
BITMAPINFO结构定义如下 :
class BITMAPINFO
{
BITMAPINFOHEADER bmiHeader; // 位图信息头
RGBQUAD bmiColors[1]; // 颜色表
}
4 :位图数据
位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右, 扫描行之间是从下到上。
位图的一个像素值所占的字节数:
当biBitCount=1 时, 8 个像素占 1 个字节 ;
当biBitCount=4 时, 2 个像素占 1 个字节 ;
当biBitCount=8 时, 1 个像素占 1 个字节 ;
当biBitCount=24 时 ,1 个像素占 3 个字节 ;
Windows规定一个扫描行所占的字节数必须是 4 的倍数 ( 即以 long 为单位 ), 不足的以 0 填充,
具体数据举例: 如某BMP 文件开头: 424D 4690 0000 0000 0000 4600 0000 2800 0000 8000 0000 9000 0000 0100*1000 0300 0000
0090 0000 A00F 0000 A00F 0000 0000 0000 0000 0000*00F8 E007 1F00 0000*02F1 84F1
04F1 84F1 84F1 06F2 84F1 06F2 04F2 86F2 06F2 86F2 86F2 .... ....
BMP 文件可分为四个部分:位图文件头、位图信息头、彩色板、图像数据阵列,在上图中已用 * 分隔。
-----------------------------------猥琐分割线-------------------------------------------------------------
比方说,我们就可以做一个BMP图片的查看器
1、打开BMP文件时,我们这里选择使用dataInputstream 读取一个最常见的24位真彩色BMP图片
// 创建文件输入流 java.io.FileInputStream fis = new java.io.FileInputStream(path); // 将文件流包装成一个可以写基本数据类型的输出流 java.io.DataInputStream dis = new java.io.DataInputStream(fis);
2、读入BMP头文件的基本信息
int bflen=14; byte bf[]=new byte[bflen]; dis.read(bf,0,bflen); //读取14字节BMP文件头
因为看到了BMP头文件中没有说明显示图片重要的信息,我只是开一个BF的数组,把头文件信息读取了出来,不做任何的处理。
3、读入位图信息头
int bilen=40; byte bi[]=new byte[bilen]; dis.read(bi,0,bilen);//读取40字节BMP信息头 // 获取一些重要数据 image_width=ChangeInt(bi,7); //源图宽度 System.out.println("宽:"+image_width); image_heigh=ChangeInt(bi,11); //源图高度 System.out.println("高:"+image_heigh); //位数 int nbitcount=(((int)bi[15]&0xff)<<8) | (int)bi[14]&0xff; System.out.println("位数:"+nbitcount); //源图大小 int nsizeimage=ChangeInt(bi,23); System.out.println("源图大小:"+nsizeimage);
由位图信息头中我们也可以看出来,要显示图片,重要的信息也就只有几个,其他都是一些不重要的,我们直接忽略掉。
因为我是直接读取40位的信息头
所以要将一些byte转为int 即ChangeInt
即 4个byte -------> 一个int
//转成int public int ChangeInt(byte[] bi,int start){ return (((int)bi[start]&0xff)<<24) | (((int)bi[start-1]&0xff)<<16) | (((int)bi[start-2]&0xff)<<8) | (int)bi[start-3]&0xff; }
因为24为的没有颜色表,所以我们直接读位图数据
最后,最关键的就是,读取位图数据
public void showRGB24(DataInputStream dis) throws IOException{ this.setTitle(path); //弹出一个图片的窗口一个大小 this.setSize(image_width, image_heigh); this.setResizable(false); this.setVisible(true); g=this.getGraphics(); if(!(image_width*3 % 4==0)){//图片的宽度不为0 skip_width =4-image_width*3%4; }//判断是否后面有补0 的情况 //装载RGB颜色的数据数组 imageR = new int[image_heigh][image_width]; imageG = new int[image_heigh][image_width]; imageB = new int[image_heigh][image_width]; //按行读取 如果H,W为正则倒着来 for (int h=image_heigh-1;h>=0;h--){ for (int w=0;w<image_width;w++){ // 读入三原色 int blue = dis.read(); int green = dis.read(); int red = dis.read(); imageB[h][w]=blue; imageG[h][w]=green; imageR[h][w]=red; if(w==0){//跳过补0项 System.out.println(dis.skipBytes(skip_width)); } } } repaint(); }
关键就是在于 位图是否有补0
有则要跳过,没有就直接读,不然显示出来的BMP图像会倾斜。
即注释掉这句话得到的效果
if(w==0){ System.out.println(dis.skipBytes(skip_width)); }
最后paint()中显示就可以看见图片了
public void paint(java.awt.Graphics g){ for (int h=0;h<image_heigh;h++){ for (int w=0;w<image_width;w++){ g.setColor(new java.awt.Color(imageR[h][w],imageG[h][w],imageB[h][w])); g.fillOval(w, h, 1, 1); } } }
如果是黑白的图,只是一个bit表示白或者黑
/**
* 黑白 图
* @param dis
* @throws IOException
*/
public void showRGB2(DataInputStream dis) throws IOException{
this.setTitle(path);
//弹出一个图片的窗口一个大小
this.setSize(image_width, image_heigh);
this.setResizable(false);
this.setVisible(true);
g=this.getGraphics();
if(!(image_width*3 % 4==0)){//图片的宽度不为0
skip_width =4-image_width*3%4;
}
imageR = new int[image_heigh][image_width];
imageG = new int[image_heigh][image_width];
imageB = new int[image_heigh][image_width];
//按行读取 如果H,W为正则倒着来
for (int h=image_heigh-1;h>=0;h--){
for (int w=0;w<image_width;w++){
int black = dis.read();
//System.out.println("read black is "+black);
if(black==0){
imageB[h][w]=0;
imageG[h][w]=0;
imageR[h][w]=0;
}else{
imageB[h][w]=255;
imageG[h][w]=255;
imageR[h][w]=255;
}
if(w==0){
System.out.println(dis.skipBytes(skip_width));
}
}
}
}
附上自己的测试代码:
评论
不错的建议~
发表评论
-
《动感地下城》,让宅男变猛男
2011-10-03 11:11 1600动感地下城 写在之前: 好久都没有发表文章了, ... -
RGP游戏的非主流应用——虚拟地图
2011-06-30 01:02 6115RGP游戏的非主流应用——虚拟地图 写在之前: 本 ... -
一个项目完整制作过程的分享
2011-05-22 14:23 8216St书店管理系统 写在文章之前: 本项 ... -
一个项目完整制作过程的分享
2011-05-22 14:18 0St书店管理系统 写在文章之前: 本项 ... -
eclipse下的1245个图标
2011-05-19 17:23 2157eclipse下的1245个图标 大家随便拿写 ... -
超级详细解析——字模
2011-05-17 21:09 6726超级详细解析——字模 一、简介 汉字库: 即 ... -
JavaSE 的MV模式(国际化)
2011-05-14 12:13 2770JavaSE 的 MV 模式 ... -
分享一个绿色版本的 JAR TO EXE工具(附上一个视频教程)
2011-03-15 14:05 1564如题,使用灰常简单 附上一个视频教程: -
偶然玩分形 java测试
2011-03-09 13:54 2600分形世界 我从拉丁文形容词fractus(分裂的)造出了fr ... -
Oracle, SQL Server, My SQL数据分页查询语句汇总
2011-03-05 23:16 2026之前一直在学习SQL Server,然而其的分 ... -
小议MVC模式开发
2011-02-27 22:08 1288做web项目是所经常提到的mvc模式。 MVC是三个 ... -
菜鸟 利用VE、截图 快速打造仿QQ绚丽界面
2011-02-12 02:52 2953自绘菜鸟 利用VE、截图 快速打造仿QQ绚丽界面 ... -
JAVA的几个重要概念小总结
2011-01-17 12:20 1409JAVA的几个重要概念小总结 方法声明: 写一个方 ... -
几个文字编码小总结
2011-01-17 12:03 1203ASCII 我们入门学习是最 ... -
超详细解释常用网络命令
2011-01-15 12:10 1582常用网络命令 PING请求 Ping www.google ... -
达通杯 赛后感想
2010-12-23 13:09 3588比赛结束两三天了今天才抽出了时间写写心得。 其实想想自己 ... -
自己动手实现高压缩比压缩软件 超详细解释(LZW算法)
2010-12-07 17:27 5003Lzw 针对大量的子串多次重复出现的压缩 之前 ... -
自己动手写压缩软件,超详细解释(哈夫曼实现)
2010-12-04 10:58 19707说到文件压缩大家很容 ... -
Java 挂链 Hash表 手动实现
2010-11-19 13:08 2182前些天一直在纠结的 ... -
五子棋 图片版
2010-11-16 12:45 5528近来发现自绘的东西怎么都比不了自己PS加载图片所作的界面好看。 ...
相关推荐
可以把文件编码为bmp图片 当然编码出来的图片当然是很不美观的~~~ 注意:不要编码或解码过大的文件~~ 因为该程序的所有操作都是在内存中进行的~~ 且是单线程的~~ 编码出来的位图是BITMAPCOREHEADER类型的~~ 并且是8...
首先,让我们详细探讨Java编程和BMP图像处理的知识点。在Java中,处理BMP图像通常涉及使用Java的内置`java.awt.image`和`javax.imageio`包。`BufferedImage`类是核心,可以用来创建、修改和显示图像。通过`ImageIO`...
这个名为“bmp.rar”的压缩包文件,结合其描述,表明它包含了使用Java编程语言实现的BMP图像格式的信息隐藏算法。BMP(Bitmap)是Windows操作系统中常见的位图图像格式,常用于存储未压缩的图像数据。 在描述中提到...
解析BMP文件主要就是读取文件头和信息头,并根据这些信息解码像素数据。由于BMP文件是未压缩的,像素数据通常按行存储,从底部行(图像的最顶部)开始,逐行向上。对于24位BMP(真彩色),每个像素由红、绿、蓝三个8...
本文将深入探讨如何将JPEG图像解码为BMP格式,并着重讲解DIB(Device Independent Bitmap,设备无关位图)结构在这个过程中的关键作用。 JPEG是一种广泛使用的有损压缩图像格式,适合于存储照片或色彩丰富的图像。...
Java Windows Bitmap(BMP)编码器与解码器是一个用于处理图像文件的工具,它允许在Java环境中读取和创建Windows BMP格式的图像。BMP是一种无损的图像存储格式,广泛应用于各种操作系统中,尤其是Windows系统。由于...
java.nio.charset 定义用来在字节和 Unicode 字符之间转换的 charset、解码器和编码器。 java.nio.charset.spi java.nio.charset 包的服务提供者类。 java.rmi 提供 RMI 包。 java.rmi.activation 为 RMI 对象...
以下是对这个Java实现程序的详细知识点介绍: 1. **图像处理**:首先,你需要将图像数据读入到程序中。Java提供了多种库,如Java Advanced Imaging (JAI) 或 JavaFX,可以用来读取、处理和分析图像文件。读取的图像...
转换时,需要根据DCM文件的信息创建对应的BMP头,并将解码后的像素数据写入BMP文件。 5. **编码与压缩**:BMP文件允许无损压缩,但不强制。在转换过程中,可以选择是否对像素数据进行压缩,这会影响转换后文件的...
2. **颜色数据解码**:BMP文件可以存储不同位深度的颜色信息,比如8位、24位等。24位BMP文件通常使用RGB(红绿蓝)三色模型,每个像素由三个字节表示。代码需要将这些颜色数据解码为单色,因为LCD12864通常只能显示...
因此,RAW文件通常比其他常见的图像格式(如JPEG)更大,需要专门的软件进行解码和编辑。对于专业摄影师而言,RAW格式提供了更大的后期处理灵活性。 **BMP格式**: BMP(Bitmap)是一种无损的位图格式,广泛支持于...
在Java编程语言中,位图图像解码器是用于处理位图图像文件(如BMP、JPEG、PNG等)的核心组件。位图图像是一种像素数组的表示方式,它存储了图像的每个像素的颜色信息。Java提供了多种库和API来支持位图图像的解码和...
每个`char`变量可以存储一个Unicode码点,但需要注意的是,对于超出BMP范围的字符,Java使用代理对(Surrogate Pair)来存储。一个代理对由两个`char`组成,它们共同表示一个码点。 将中文字符转换为Unicode编码,...
源代码部分可能包含C++、C#或Python等语言实现的读取函数,展示了从磁盘加载BMP文件,解析其头部信息,然后将数据解码并显示的具体步骤。外文翻译可能涉及原始的BMP格式标准文档或相关研究论文,以更深入地理解该...
5. **写入BMP文件**:最后,将解码后的RGB像素数据和创建的文件头写入新的BMP文件。这个过程需要遵循BMP文件的特定字节顺序,例如,BMP格式通常以“蓝色”像素开始,然后是“绿色”,最后是“红色”。 示例代码...
6. **编程实现**:可以使用各种编程语言来实现avi到bmp的转换,例如C++、Python、Java等。通常,这些语言都有现成的库(如FFmpeg、OpenCV)可以直接调用,它们提供了对视频解码和图像编码的支持。 7. **工具使用**...
下面将详细介绍如何读取BMP图像以及相关知识点。 1. BMP文件结构: BMP文件由两部分组成:位图头信息和位图数据。位图头信息包含了图像的宽度、高度、颜色深度等元数据,而位图数据则存储实际的像素颜色值。常见的...
1. **文件读取**:使用合适的库函数或API读取文件,例如C++的`fread`,Java的`BufferedInputStream`,Python的`PIL`库等。 2. **解码图像数据**:根据文件格式解析头部信息,解码压缩的图像数据。 3. **内存表示**:...