• AS3.0 位图(BMP)解析类


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

      

  • 相关阅读:
    BZOJ 3262 cdq分治 OR 树套树
    Weekly Contest 132
    1007. Minimum Domino Rotations For Equal Row
    1002. Find Common Characters
    974. Subarray Sums Divisible by K
    926. Flip String to Monotone Increasing
    918. Maximum Sum Circular Subarray
    914. X of a Kind in a Deck of Cards
    907. Sum of Subarray Minimums
    900. RLE Iterator
  • 原文地址:https://www.cnblogs.com/fengziwu/p/10908730.html
Copyright © 2020-2023  润新知