ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AS3.0 位图(BMP)解析类

2019-05-22 21:54:57  阅读:196  来源: 互联网

标签:AS3.0 mydata private BMP uint biHeight var 解析


/**
 * *-----------------------------*
 * |    *** 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;
		}//返回位图数据
	}
}

  

标签:AS3.0,mydata,private,BMP,uint,biHeight,var,解析
来源: https://www.cnblogs.com/fengziwu/p/10908730.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有