⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitmap.java

📁 Bitmap class for Java
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
public class Bitmap {
	public static final String BITMAP_FLAG = "BM";
	public static final String[] BITMAP_FLAGS = new String[]{"BM","BA","CI", "CP", "IC", "PT"};
	public static final int[] BITSPERPIXELS = new int[] {1, 4, 8, 16, 24, 32};
	public static final int[] COMPRESSIONS = new int[] {0,1,2,3};
	/**
	 * 文件头
	 */
	private Header header;
	
	/**
	 * 图象数据 根据BMP版本及调色板尺寸的不同而不同 Bitmap Data xxx bytes 该域的大小取决于压缩方法及图像的尺寸和图像的位深度,它包含所有的位图数据字节,这些数据可能是彩色调色板的索引号,也可能是实际的RGB值,这将根据图像信息头中的位深度值来决定。 
	 */
	private byte[] data;
	
	
	public boolean valid() {
		if( this.header == null || !this.header.valid() ) return false;
		if( this.data == null && this.header.dataSize > 0 || this.data.length != this.header.dataSize ) return false;
		return true;
	}

	public byte[] getByte() {
		if( !this.valid() ) return null;
		byte[] buffer = new byte[this.header.headerSize + this.header.dataSize];
		byte[] headerBuffer = this.header.getByte();
		this.fill(buffer, 0, headerBuffer, 0, headerBuffer.length);
		if( this.data != null ) this.fill(buffer, 0, this.data, 0, this.data.length);
		return buffer;
	}
	
	public boolean read(byte[] buffer) {
		Header h = new Header();
		if( !h.read(buffer, 0) ) return false;
		if( !h.valid() ) return false;
		if( buffer.length < h.offset + h.dataSize ) return false;
		this.data = new byte[h.dataSize];
		this.header = h;
		this.fill(this.data, 0, buffer, h.offset, h.dataSize);
		return true;
	}
	
	public Header getHeader() {
		return header;
	}

	public byte[] getData() {
		return data;
	}
	
	public void setPixel(int x, int y, int color) {
		Pixel p = new Pixel(x, y);
		p.set(color);
	}
	
	public int getPixel(int x, int y) {
		Pixel p = new Pixel(x, y);
		return p.get();
	}
	
	public class Pixel {
		private int x;
		private int y;
		private int colorIndex;
		
		private int byteIndex;
		private int byteLength;
		private int bitOffset;
		
		public Pixel(int x, int y) {
			this.x = x;
			this.y = y;
			int bitWidth = header.width * header.bitsPerPixel;
			int byteWidth = bitWidth / 8;
			if( bitWidth % 8 > 0 ) byteWidth ++;
			if( byteWidth % 4 > 0 ) byteWidth += 4 - byteWidth % 4; 
			int bitX = x * header.bitsPerPixel;
			int byteX = bitX / 8;
			this.bitOffset = bitX % 8;
			this.byteIndex = y * byteWidth + byteX;
			this.byteLength = header.bitsPerPixel / 8 + (header.bitsPerPixel % 8 > 0 ? 1 : 0);
		}
		
		public int get() {
			byte[] pixel = getbytes(data, byteIndex, byteLength );
			String s = "";
			for(int i=0; i<pixel.length; i++) {
				String ss = "00000000" + Integer.toBinaryString(pixel[i]);
				s = s + ss.substring(ss.length()-8);
			}
			s = s.substring(bitOffset, header.bitsPerPixel);
			int colorIndex = Integer.valueOf(s, 2).intValue();
			int color = this.getColor(colorIndex);
			return color; 
		}
		
		public void set(int color) {
			String str0 = Long.toBinaryString(0x100000000l).substring(1);
			String str1 = Long.toBinaryString(0xFFFFFFFFl);
			String mask = str1.substring(0,this.bitOffset) + str0.substring(0,header.bitsPerPixel) + str1.substring(0,this.byteLength*8-header.bitsPerPixel-this.bitOffset);

			int value = this.getColorIndex(color);
			String vbits = Long.toBinaryString(0x100000000l+value);
			vbits = vbits.substring(vbits.length() - header.bitsPerPixel);
			vbits = mask.substring(0,this.bitOffset) + vbits + mask.substring(this.bitOffset+header.bitsPerPixel);
			
			String bits = this.getBinaryString(data, this.byteIndex, this.byteLength);
			long lmask = Long.valueOf(mask, 2);
			long lvmask = Long.valueOf(vbits, 2);
			long lbytes = Long.valueOf(bits, 2);
			lbytes &= lmask;
			lbytes |= lvmask;
			
			bits = Long.toBinaryString(0x100000000l + lbytes);
			bits = bits.substring(bits.length() - this.byteLength * 8);
			for(int i=0; i<this.byteLength; i++)  {
				data[this.byteIndex+i] = (byte)Integer.valueOf(bits.substring(i*8,(i+1)*8), 2).intValue();
			}
		}
		
		private String getBinaryString(byte[] buffer, int index, int length) {
			String s = "";
			for(int i=0; i<length; i++) {
				String ss = "00000000" + Integer.toBinaryString(buffer[index+i]);
				s = s + ss.substring(ss.length()-8);
			}
			return s;
		}

		private int getColor(int index) {
			int color = 0;
			if( header.getPalette() != null && header.palette.length != 0 ){
				if( header.palette.length > index ) color = header.palette[index].getColor();
			}
			else {
				int cmax = Integer.valueOf(Integer.toBinaryString(0xFFFFFF).substring(0,header.bitsPerPixel),2);
				int Cmax = 0xFFFFFF;
				int Cindex = Cmax / cmax * index;
				color = Cindex;
			}
			return color;
		}

		private int getColorIndex(int color) {
			int index = 0;
			if( header.getPalette() != null && header.palette.length != 0 ) {
				for(int i=0; i<header.palette.length; i++) 
					if( header.palette[i].getColor() == color ) return i; 
			}
			else {
				int cmax = Integer.valueOf(Integer.toBinaryString(0xFFFFFF).substring(0,header.bitsPerPixel),2);
				int Cmax = 0xFFFFFF;
				index = (cmax + 1) / (Cmax + 1) * (color + 1) - 1;
			}
			return index;
		}
	}
	
	
	/**
	 * BITMAP图像头
	 * 
	 * @author Katherine
	 *
	 */
	public class Header {
		/**
		 * 0000h
		 * 文件标识 2 bytes 两字节的内容用来识别位图的类型: 
			 * ‘BM’ : Windows 3.1x, 95, NT, … 
		 * ‘BA’ :OS/2 Bitmap Array 
		 * ‘CI’ :OS/2 Color Icon 
		 * ‘CP’ :OS/2 Color Pointer 
		 * ‘IC’ : OS/2 Icon 
		 * ‘PT’ :OS/2 Pointer
		 * 注:因为OS/2系统并没有被普及开,所以在编程时,你只需判断第一个标识“BM”就行。
		 */
		private String flag;
		
		/**
		 * 0002h
		 * File Size 1 dword 用字节表示的整个文件的大小
		 */
		private int fileSize;
		
		/**
		 * 0006h
		 * Reserved 1 dword 保留,必须设置为0 
		 */
		private int reserved = 0;
		
		/**
		 * 000Ah
		 * Bitmap Data Offset 1 dword 从文件开始到位图数据开始之间的数据(bitmap data)之间的偏移量 
		 */
		private int offset;
		
		/**
		 * 000Eh
		 * Bitmap Header Size 1 dword 位图信息头(Bitmap Info Header)的长度,用来描述位图的颜色、压缩方法等。下面的长度表示:
		 * 	28h - Windows 3.1x, 95, NT, …
		 * 	0Ch - OS/2 1.x
		 * 	F0h - OS/2 2.x
		 * 注:在Windows95、98、2000等操作系统中,位图信息头的长度并不一定是28h,因为微软已经制定出了新的BMP文件格式,其中的信息头结构变化比较大,长度加长。所以最好不要直接使用常数28h,而是应该从具体的文件中读取这个值。这样才能确保程序的兼容性。
		 */
		private int headerSize;

		/**
		 * 0012h
		 * Width 1 dword 位图的宽度,以象素为单位 
		 */
		private int width;
		
		/**
		 * 0016h
		 * Height 1 dword 位图的高度,以象素为单位 
		 */
		private int height;
		
		/**
		 * 001Ah
		 * Planes 1 word 位图的位面数(注:该值将总是1) 
		 */
		private short planes = 1;
		
		/**
		 * 001Ch
		 * Bits Per Pixel 1 word 每个象素的位数
		 * 	1 - 单色位图(实际上可有两种颜色,缺省情况下是黑色和白色。你可以自己定义这两种颜色)
		 * 	4 - 16 色位图
		 * 	8 - 256 色位图
		 * 	16 - 16bit 高彩色位图
		 * 	24 - 24bit 真彩色位图
		 * 	32 - 32bit 增强型真彩色位图
		 */
		private short bitsPerPixel = 1;
		
		/**
		 * 001Eh
		 * Compression 1 dword 压缩说明:
		 * 	0 - 不压缩 (使用BI_RGB表示)
		 * 	1 - RLE 8-使用8位RLE压缩方式(用BI_RLE8表示)
		 * 	2 - RLE 4-使用4位RLE压缩方式(用BI_RLE4表示)
		 * 	3 - Bitfields-位域存放方式(用BI_BITFIELDS表示)
		 */
		private int compression;

		/**
		 * 0022h
		 * Bitmap Data Size 1 dword 用字节数表示的位图数据的大小。该数必须是4的倍数 
		 */
		private int dataSize;
		
		/**
		 * 0026h
		 * HResolution 1 dword 用象素/米表示的水平分辨率 
		 */
		private int hResolution;
		
		/**
		 * 002Ah
		 * VResolution 1 dword 用象素/米表示的垂直分辨率 
		 */
		private int vResolution;
		
		/**
		 * 002Eh
		 * Colors 1 dword 位图使用的颜色数。如8-比特/象素表示为100h或者 256. 
		 */
		private int colors;
		
		/**
		 * 0032h
		 * Important Colors 1 dword 指定重要的颜色数。
		 * 当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要 
		 */
		private int importantColors;
		
		/**
		 * 0036h
		 * 调色板数据
		 * 根据BMP版本的不同而不同
		 * Palette N * 4 byte 调色板规范。
		 */
		private Palette[] palette;

		public Header() {
			this.flag = BITMAP_FLAGS[0];
			this.fileSize = 0;
			this.offset = 0;
			this.headerSize = 0x0036;
			this.width = 0;
			this.height = 0;
			this.bitsPerPixel = 1;
			this.compression = 0;
			this.dataSize = 0;
			this.hResolution = 0;
			this.vResolution = 0;
			this.colors = 0x0010;
			this.importantColors = 0;
			this.palette = null;
		}

		public boolean valid() {
			if( this.flag == null ) return false;
			boolean isvalid = false;
			for(int i=0; i<BITMAP_FLAGS.length; i++) 
				if( isequal(this.flag.getBytes(), BITMAP_FLAGS[i].getBytes()) ) {
					isvalid = true;
					break;
				}
			if( !isvalid ) return false;
			if( this.fileSize != this.offset + this.dataSize ) return false;
			if( this.reserved != 0 ) return false;
			if( this.offset < (0x0036 + (this.palette == null ? 0 : this.palette.length)*Palette.SIZE) ) return false;
			if( this.width < 0 ) return false;
			if( this.height < 0 ) return false;
			if( this.planes != 1 ) return false;
			isvalid = false;
			for(int i=0; i<BITSPERPIXELS.length; i++) 
				if( BITSPERPIXELS[i] == this.bitsPerPixel ) {
					isvalid = true;
					break;
				}
			if( !isvalid ) return false;
			isvalid = false;
			for(int i=0; i<BITSPERPIXELS.length; i++) 
				if( BITSPERPIXELS[i] == this.bitsPerPixel ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -