/**
* *-----------------------------*
* | *** BMP格式解析类 *** |
* *-----------------------------*
*
* 编辑修改收录:fengzi(疯子、wu341、wgq341)
*
* 不会写代码,我是代码搬运工。
*
* 联系方式:QQ(493712833)。
*
* 随 笔: https://www.cnblogs.com/fengziwu/
*
* 版权协议:请自觉遵守LGPL协议,欢迎修改、复制、转载、传播给更多需要的人。
* 免责声明:任何因使用此软件导致的纠纷与软件/程序开发者无关。
* 日 期: 2019.05.08
*
* ---------------------- 实例 --------------------------- *
var req : URLRequest;
var loa : URLLoader;
// 二进制加载BMP文件
load( "4位压缩.bmp" );
// 二进制加载BMP文件
function load ( url:String ) : void{
req = new URLRequest( url );
loa = new URLLoader();
loa.dataFormat = URLLoaderDataFormat.BINARY;
loa.addEventListener( Event.COMPLETE, loaComplete );
loa.load( req );
}
// 加载BMP完成
function loaComplete ( eve:Event ) : void
{
loa.removeEventListener( Event.COMPLETE, loaComplete );
// 解析BMP文件
analysisDisplay();
}
//***** BMP解析以及显示 ***
// BMP格式解析对象
var bmpAna : BMPAnalytical;
// 舞台上的Bitmap对象数组,用于显示位图
var bitmap : Bitmap;
// 解析显示BMP文件
function analysisDisplay () : void
{
bmpAna = new BMPAnalytical();
bmpAna.analyticalByteArray( loa.data );
bitmap = new Bitmap( bmpAna.ImageDate );
bitmap.x = 100;
bitmap.y = 100;
addChild( bitmap );
}
*/
package fengzi.bmd
{
import flash.utils.ByteArray;
import flash.utils.Endian;
import flash.display.BitmapData;
/**
* BMPAnalytical BMP格式解析类,用于解析BMP格式二进制数据,并且从中获取位图数据信息。
*/
public class BMPAnalytical
{
private var mydata : ByteArray;
//BMP图像数据的地址
private var bfOffBits : uint;
//BMP图像的宽度,单位像素
private var biWidth : uint;
//BMP图像的高度,单位像素
private var biHeight : uint;
//平面数
private var biPlanes : uint;
//BMP图像的色深,即一个像素用多少位表示,常见有1、4、8、16、24和32,分别对应单色、16色、256色、16位高彩色、24位真彩色和32位增强型真彩色
private var biBitCount : uint;
//压缩方式,0表示不压缩,1表示RLE8压缩,2表示RLE4压缩,3表示每个像素值由指定的掩码决定
private var biCompression : uint;
//BMP图像数据大小,必须是4的倍数,图像数据大小不是4的倍数时用0填充补足
private var biSizeImage : uint;
//水平分辨率
private var biXPelsPerMeter : uint;
//垂直分辨率
private var biYPelsPerMeter : uint;
//BMP图像使用的颜色,0表示使用全部颜色,对于256色位图来说,此值为100h = 256
private var biClrUsed : uint;
//重要的颜色数,此值为0时所有颜色都重要,对于使用调色板的BMP图像来说,当显卡不能够显示所有颜色时,此值将辅助驱动程序显示颜色
private var biClrImportant : uint;
//调色盘
private var colorArray : Vector.<uint>;
//位图数据
private var imagedata : BitmapData;
/**
* 构造函数
*/
public function BMPAnalytical ()
{
}
/**
* 解析由[Embed()]元素直接获取的图片对象,例如:[Embed(source="4位压缩.bmp",mimeType="application/octet-stream")]
*/
public function analyticalClass ( bmpClass:Class ) : void
{
// constructor code
this.mydata = new bmpClass as ByteArray;
this.mydata.endian = Endian.LITTLE_ENDIAN;
BITMAPFILEHEADER();
BITMAPINFOHEADER();
colortable();
bitmapdata();
}
/**
* 解析由URLLoader等方法二进制加载图片对象
*/
public function analyticalByteArray ( bmpByteArray:ByteArray ) : void
{
this.mydata = bmpByteArray;
this.mydata.endian = Endian.LITTLE_ENDIAN;
BITMAPFILEHEADER();
BITMAPINFOHEADER();
colortable();
bitmapdata();
}
private function BITMAPFILEHEADER () : void
{
if ( this.mydata.readUTFBytes(2) != "BM" )
{
throw new Error( "不是BMP文件!" )
}
if ( this.mydata.readUnsignedInt() != this.mydata.length )
{
throw new Error( "文件不全!" );
}
this.mydata.position += 4;
this.bfOffBits = this.mydata.readUnsignedInt();
//trace( "BMP图像数据的地址:" + this.bfOffBits );
}
//位图文件头
private function BITMAPINFOHEADER () : void
{
this.mydata.position += 4;
this.biWidth = this.mydata.readUnsignedInt();
//trace( "BMP图像的宽度:" + this.biWidth )
this.biHeight = this.mydata.readUnsignedInt();
//trace( "BMP图像的高度:" + this.biHeight )
this.biPlanes = this.mydata.readUnsignedShort();
this.biBitCount = this.mydata.readUnsignedShort();
//trace( "BMP图像的色深:" + this.biBitCount );
this.biCompression = this.mydata.readUnsignedInt();
//trace( "压缩方式:" + this.biCompression );
this.biSizeImage = this.mydata.readUnsignedInt();
//trace( "BMP图像数据大小:" + this.biSizeImage );
this.biXPelsPerMeter = this.mydata.readUnsignedInt();
this.biYPelsPerMeter = this.mydata.readUnsignedInt();
this.biClrUsed = this.mydata.readUnsignedInt();
this.biClrImportant = this.mydata.readUnsignedInt();
}
//位图信息头
private function colortable () : void
{
if ( this.biBitCount <= 8 )
{
this.colorArray = new Vector.<uint>();
//trace( "使用调色盘!" )
var r:uint,g:uint,b:uint,color:uint,i:uint;
var end : uint = Math.pow( 2, this.biBitCount );
for ( i = 0; i < end; i++ )
{
b = this.mydata.readUnsignedByte();
g = this.mydata.readUnsignedByte();
r = this.mydata.readUnsignedByte();
this.mydata.position++;
color = (r<<16) + (g<<8) + b;
this.colorArray[i] = color;
}
}
else
{
//trace("不使用调色盘!")
}
}
//彩色表/调色板
private function bitmapdata () : void
{
this.mydata.position = this.bfOffBits;
var Offset : uint;//每行偏移
var i:uint,j:uint,p:uint,color:uint,r:uint,g:uint,b:uint,a:uint;
var end:uint,bytes1:uint,bytes2:uint,k:uint,x:uint,y:uint;
if ( this.biBitCount <= 8 )
{
this.imagedata = new BitmapData( this.biWidth, this.biHeight, false, 0x000000 );
if ( this.biBitCount == 8 )
{
if ( this.biCompression == 0 )
{
Offset = this.biSizeImage / this.biHeight - this.biWidth;//每行偏移
for ( i = 0; i < this.biHeight; i++ )
{
for ( j = 0; j < this.biWidth; j++ )
{
p = this.mydata.readUnsignedByte();
color = this.colorArray[p];
this.imagedata.setPixel( j, this.biHeight - i - 1, color );
if ( j == this.biWidth - 1 )
{
this.mydata.position += Offset;
}
}
}
//不压缩
}
else
{
x = 0;
y = 0;
while ( this.mydata.bytesAvailable > 0 )
{
bytes1 = this.mydata.readUnsignedByte();
bytes2 = this.mydata.readUnsignedByte();
if ( bytes1 >= 0x01 )
{
for ( i = 0; i < bytes1; i++ )
{
color = this.colorArray[bytes2];
this.imagedata.setPixel( x, this.biHeight - y - 1, color );
x++;
}
//每像素8位的BMP文件,连续重复数据以两字节表示,第一个字节记录重复次数,第二字节记录重复数据。
}
else
{
if ( bytes2 >= 0x03 )
{
for ( i = 0; i < bytes2; i++ )
{
p = this.mydata.readUnsignedByte();
color = this.colorArray[p];
this.imagedata.setPixel( x, this.biHeight - y - 1, color );
x++;
}
if ( this.mydata.readUnsignedByte() == 0x00 )
{
//无重复像素结束符
}
else
{
this.mydata.position--;
}
}
//如果是3个以上不重复的数据字节,第1个字节为00,第2个字节记录该不重复的数据串的长度(以字节为单位)
else if ( bytes2 == 0x02 )
{
x += this.mydata.readUnsignedByte();
y += this.mydata.readUnsignedByte();
}
//像素位置跳转符
else if ( bytes2 == 0x01 )
{
//图像结束符
break;
}
else
{
x = 0;
y++;
//换行符
}
}
}
//压缩
}
}
//8位图像
var bit:uint,str:String,Num:uint;
var p1:uint,p2:uint,p3:uint,p4:uint,p5:uint,p6:uint,p7:uint,p8:uint;
if ( this.biBitCount == 1 )
{
Offset = this.biSizeImage / this.biHeight;//每行偏移
for ( i = 0; i < this.biHeight; i++ )
{
for ( j = 0; j < Offset; j++ )
{
bit = this.mydata.readUnsignedByte() + 256;
str = bit.toString(2);
p1 = uint( str.charAt(1) );
p2 = uint( str.charAt(2) );
p3 = uint( str.charAt(3) );
p4 = uint( str.charAt(4) );
p5 = uint( str.charAt(5) );
p6 = uint( str.charAt(6) );
p7 = uint( str.charAt(7) );
p8 = uint( str.charAt(8) );
this.imagedata.setPixel( j*8,this.biHeight-i-1,this.colorArray[p1] );
this.imagedata.setPixel( j*8+1,this.biHeight-i-1,this.colorArray[p2] );
this.imagedata.setPixel( j*8+2,this.biHeight-i-1,this.colorArray[p3] );
this.imagedata.setPixel( j*8+3,this.biHeight-i-1,this.colorArray[p4] );
this.imagedata.setPixel( j*8+4,this.biHeight-i-1,this.colorArray[p5] );
this.imagedata.setPixel( j*8+5,this.biHeight-i-1,this.colorArray[p6] );
this.imagedata.setPixel( j*8+6,this.biHeight-i-1,this.colorArray[p7] );
this.imagedata.setPixel( j*8+7,this.biHeight-i-1,this.colorArray[p8] );
}
}
}
//1位图像
if ( this.biBitCount == 4 )
{
if ( this.biCompression == 0 )
{
Offset = this.biSizeImage/this.biHeight;//每行偏移
for ( i = 0; i < this.biHeight; i++ )
{
for ( j = 0; j < Offset; j++ )
{
bit = this.mydata.readUnsignedByte();
p2 = bit>>4;
p1 = bit-(p2<<4);
this.imagedata.setPixel(j*2,this.biHeight-i-1,this.colorArray[p2]);
this.imagedata.setPixel(j*2+1,this.biHeight-i-1,this.colorArray[p1]);
}
}
//不压缩
}
else
{
x = 0;
y = 0;
var col1:uint,col2:uint,b1:uint;
while ( this.mydata.bytesAvailable > 0 )
{
bytes1 = this.mydata.readUnsignedByte();
bytes2 = this.mydata.readUnsignedByte();
if ( bytes1 >= 0x01 )
{
col2 = bytes2>>4;
col1 = bytes2-(col2<<4);
for ( i = 0; i < bytes1; i++ )
{
if ( i%2 == 0 )
{
p = col2;
}
else
{
p = col1;
}
color = this.colorArray[p];
this.imagedata.setPixel( x, this.biHeight-y-1, color );
x++;
}
//重复的像素值
}
else
{
if ( bytes2 >= 0x03 )
{
for ( i = 0; i < bytes2; i++ )
{
if ( i%2 == 0 )
{
b1 = this.mydata.readUnsignedByte();
col2 = b1>>4;
col1 = b1-(col2<<4);
p = col2;
}
else
{
p = col1;
}
color = this.colorArray[p];
this.imagedata.setPixel(x,this.biHeight-y-1,color);
x++;
}
if ( this.mydata.readUnsignedByte() == 0x00 )
{
//无重复像素结束符
}
else
{
this.mydata.position--;
}
//如果是3个以上不重复的数据字节,第1个字节为00,第2个字节记录该不重复的数据串的长度(以字节为单位)
//不重复的像素值
}
else if ( bytes2 == 0x02 )
{
x += this.mydata.readUnsignedByte();
y += this.mydata.readUnsignedByte();
//像素位置跳转符
}
else if ( bytes2 == 0x01 )
{
break;
//图像结束符
}
else
{
x = 0;
y++;
//换行符
}
}
}
//压缩
}
}//4位图像
//使用调色盘
}
else
{
if ( this.biBitCount == 32 )
{
this.imagedata = new BitmapData(this.biWidth,this.biHeight,true,0xff000000);
Offset = (this.biSizeImage-this.biWidth*this.biHeight*4)/this.biHeight;
for ( i = 0; i < this.biHeight; i++ )
{
for ( j = 0; j < this.biWidth; j++ )
{
b = this.mydata.readUnsignedByte();
g = this.mydata.readUnsignedByte();
r = this.mydata.readUnsignedByte();
a = this.mydata.readUnsignedByte();
color = (a<<24)+(r<<16)+(g<<8)+b;
this.imagedata.setPixel(j,this.biHeight-i-1,color);
if ( j == this.biWidth-1 )
{
this.mydata.position += Offset;
}
}
}
//有透明度的位图
}
else
{
this.imagedata = new BitmapData(this.biWidth,this.biHeight,false,0x000000);
if ( this.biBitCount == 24 )
{
Offset = (this.biSizeImage-this.biWidth*this.biHeight*3)/this.biHeight;
for ( i = 0; i < this.biHeight; i++ )
{
for ( j = 0; j < this.biWidth; j++ )
{
b = this.mydata.readUnsignedByte();
g = this.mydata.readUnsignedByte();
r = this.mydata.readUnsignedByte();
color = (r<<16)+(g<<8)+b;
this.imagedata.setPixel(j,this.biHeight-i-1,color);
if ( j == this.biWidth-1 )
{
this.mydata.position += Offset;
}
}
}
}//24位图像
var shortint:uint;
if ( this.biBitCount == 16 )
{
Offset = (this.biSizeImage-this.biWidth*this.biHeight*2)/this.biHeight;
if ( this.biCompression == 3 )
{
for ( i = 0; i < this.biHeight; i++ )
{
for ( j = 0; j < this.biWidth; j++ )
{
shortint = this.mydata.readUnsignedShort();
r = shortint>>11;
g = (shortint-(b<<11))>>5;
b = shortint-(b<<11)-(g<<5);
color = (r<<19)+(g<<10)+(b<<3);
this.imagedata.setPixel(j,this.biHeight-i-1,color);
if ( j == this.biWidth-1 )
{
this.mydata.position += Offset;
}
}
}
}//565压缩
if ( this.biCompression == 0 )
{
for ( i = 0; i < this.biHeight; i++ )
{
for ( j = 0; j < this.biWidth; j++ )
{
shortint = this.mydata.readUnsignedShort();
shortint = shortint-((shortint>>15)<<15);
r = shortint>>10;
g = (shortint-(b<<10))>>5;
b = shortint-(b<<10)-(g<<5);
color = (r<<19)+(g<<11)+(b<<3);
this.imagedata.setPixel(j,this.biHeight-i-1,color);
if ( j == this.biWidth-1 )
{
this.mydata.position += Offset;
}
}
}
}//X555压缩
}//16位图像
//没有透明度的位图
}
//不使用调色盘
}
}//位图数据
public function get ImageDate() : BitmapData
{
return this.imagedata;
}//返回位图数据
}
}