将文件内容隐藏在bmp位图中

首先要实现这个功能,你必须知道bmp位图文件的格式,这里我就不多说了,请看:http://www.cnblogs.com/xiehy/archive/2011/06/07/2074405.html

接下来主要讲解实现的思路和源码:

实现思路:
根据bmp的文件的格式(记录了文件大小,文件数据的位置等信息)和读取文件内容的方式(只读取指定偏移点的数据),
可得出:当我们改变数据偏移点的值和文件的大小,将要隐藏的文件内容保存在头部到偏移点的区域即可。


实现步骤:
1、解析整个文件的格式信息
2、获取偏移点位置
3、定位到调色板结束位置,将文件数据插入到调色板结束位置后面
4、修改偏移位置,加上要隐藏文件的大小
5、重新写入文件中


读取文件步骤:
1、解析bmp文件格式
2、获取偏移位置end和比特/像素和颜色索引数目
3、定位到调色板的结束位置,即数据的开始位置start
4、读取start到end之间的数据到文件中,即为原来文件的内容


根据上述实现步骤,初步的实现已完成,后期完善某些不足之处,例读取位图信息时使用byte数组存储,
这样如果文件过大,可能会溢出


优化:
1、基本类型的字节的优化,避免强制转换
2、位图数据可以不存储,在需要写入的时候再去读原文件的位图数据部分
3、调色板数据在这个方法里也可以不存储,但其实不会很大,所以也没多大关系,可做可不做
4、抽除掉重复功能的代码


思考:
可以直接将文件数据写入到位图数据的最后面?
可以,这个更加的简单


实现步骤:
1、解析总的文件大小
2、读取bmp所有的数据到新的文件中
3、读取将要隐藏的文件的内容,写入到新的文件中


读取文件内容步骤:
1、解析出原来bmp文件的大小
2、将输入流读取位置跳到bmp文件尾
3、读取输入流中剩下的内容,写入到其它文件中即可


这种实现方式的关键在于解析bmp格式中记录的bmp文件的大小,其它什么都不需要获取,数据的隐藏性较差


重要源码:


package com.pan.entity;

/**
 * @author yp2
 * @date 2015-11-17
 * @description Bmp文件格式
 */
public class Bmp {
	
	private BmpHeader bmpHeader;
	private BmpInfoHeader bmpInfoHeader;
	private BmpPalette bmpPalette;
	/**
	 * bmp位图数据
	 */
	private byte[] datas;
	public BmpHeader getBmpHeader() {
		return bmpHeader;
	}
	public void setBmpHeader(BmpHeader bmpHeader) {
		this.bmpHeader = bmpHeader;
	}
	public BmpInfoHeader getBmpInfoHeader() {
		return bmpInfoHeader;
	}
	public void setBmpInfoHeader(BmpInfoHeader bmpInfoHeader) {
		this.bmpInfoHeader = bmpInfoHeader;
	}
	public BmpPalette getBmpPalette() {
		return bmpPalette;
	}
	public void setBmpPalette(BmpPalette bmpPalette) {
		this.bmpPalette = bmpPalette;
	}
	public byte[] getDatas() {
		return datas;
	}
	public void setDatas(byte[] datas) {
		this.datas = datas;
	}

}



package com.pan.entity;

/**
 * @author yp2
 * @date 2015-11-17
 * @description Bmp文件头部
 */
public class BmpHeader {
	
	/**
	 * 文件的类型,2个字节
	 */
	private byte[] bfType;	
	/**
	 * 位图文件的大小,字节为单位,4个字节
	 */
	private byte[] bfSize;	
	/**
	 * 保留,2个字节
	 */
	private byte[] bfReserved1;
	/**
	 * 保留,2个字节
	 */
	private byte[] bfReserved2;
	/**
	 * 说明从文件开始到实际的图像数据之间的字节的偏移量
	 * 4个字节
	 */
	private byte[] bfOffBits;
	public BmpHeader() {
		bfType = new byte[2];
		bfSize = new byte[4];
		bfReserved1 = new byte[2];
		bfReserved2 = new byte[2];
		bfOffBits = new byte[4];
	}
	
	public byte[] getBfType() {
		return bfType;
	}
	public void setBfType(byte[] bfType) {
		this.bfType = bfType;
	}
	public byte[] getBfSize() {
		return bfSize;
	}
	public void setBfSize(byte[] bfSize) {
		this.bfSize = bfSize;
	}
	public byte[] getBfReserved1() {
		return bfReserved1;
	}
	public void setBfReserved1(byte[] bfReserved1) {
		this.bfReserved1 = bfReserved1;
	}
	public byte[] getBfReserved2() {
		return bfReserved2;
	}
	public void setBfReserved2(byte[] bfReserved2) {
		this.bfReserved2 = bfReserved2;
	}
	public byte[] getBfOffBits() {
		return bfOffBits;
	}
	public void setBfOffBits(byte[] bfOffBits) {
		this.bfOffBits = bfOffBits;
	}
	
	
}

package com.pan.entity;

/**
 * @author yp2
 * @date 2015-11-17
 * @description Bmp文件信息头部
 */
public class BmpInfoHeader {
	
	/**
	 * 位图信息头部所需要的字数,4个字节
	 */
	private byte[] biSize;
	/**
	 * 图像的宽度,像素为单位,4个字节
	 */
	private byte[] biWidth;
	/**
	 * 图像的高度,像素为单位,4个字节
	 */
	private byte[] biHeight;
	/**
	 * 为目标设备说明颜色平面数,其值将总是设为1,2个字节
	 */
	private byte[] biPlans;
	/**
	 * 说明比特数/像素,其值为1、4、8、16、24、32,2个字节
	 */
	private byte[] biBitCount;
	/**
	 * 说明图像数据压缩的类型,0 不压缩,4个字节
	 */
	private byte[] biCompression;
	/**
	 * 说明图像的大小,字节为单位,当压缩格式为0时,可设置为0,4个字节
	 */
	private byte[] biSizeImage;
	/**
	 * 说明水平分辨率,像素/米表示,有符号整数,4个字节
	 */
	private byte[] biXPelsPerMeter;
	/**
	 * 说明垂直分辨率,像素/米表示,有符号整数,4个字节
	 */
	private byte[] biYPelsPerMeter;
	/**
	 * 说明位图实际使用的彩色表中的颜色索引数,4个字节
	 */
	private byte[] biClrUsed;
	/**
	 * 说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要
	 * 4个字节
	 */
	private byte[] biClrImportant;
	public BmpInfoHeader() {
		biSize = new byte[4];
		biWidth = new byte[4];
		biHeight = new byte[4];
		biPlans = new byte[2];
		biBitCount = new byte[2];
		biCompression = new byte[4];
		biSizeImage = new byte[4];
		biXPelsPerMeter = new byte[4];
		biYPelsPerMeter = new byte[4];
		biClrUsed = new byte[4];
		biClrImportant = new byte[4];
	}
	public byte[] getBiSize() {
		return biSize;
	}
	public void setBiSize(byte[] biSize) {
		this.biSize = biSize;
	}
	public byte[] getBiWidth() {
		return biWidth;
	}
	public void setBiWidth(byte[] biWidth) {
		this.biWidth = biWidth;
	}
	public byte[] getBiHeight() {
		return biHeight;
	}
	public void setBiHeight(byte[] biHeight) {
		this.biHeight = biHeight;
	}
	public byte[] getBiPlans() {
		return biPlans;
	}
	public void setBiPlans(byte[] biPlans) {
		this.biPlans = biPlans;
	}
	public byte[] getBiBitCount() {
		return biBitCount;
	}
	public void setBiBitCount(byte[] biBitCount) {
		this.biBitCount = biBitCount;
	}
	public byte[] getBiCompression() {
		return biCompression;
	}
	public void setBiCompression(byte[] biCompression) {
		this.biCompression = biCompression;
	}
	public byte[] getBiSizeImage() {
		return biSizeImage;
	}
	public void setBiSizeImage(byte[] biSizeImage) {
		this.biSizeImage = biSizeImage;
	}
	public byte[] getBiXPelsPerMeter() {
		return biXPelsPerMeter;
	}
	public void setBiXPelsPerMeter(byte[] biXPelsPerMeter) {
		this.biXPelsPerMeter = biXPelsPerMeter;
	}
	public byte[] getBiYPelsPerMeter() {
		return biYPelsPerMeter;
	}
	public void setBiYPelsPerMeter(byte[] biYPelsPerMeter) {
		this.biYPelsPerMeter = biYPelsPerMeter;
	}
	public byte[] getBiClrUsed() {
		return biClrUsed;
	}
	public void setBiClrUsed(byte[] biClrUsed) {
		this.biClrUsed = biClrUsed;
	}
	public byte[] getBiClrImportant() {
		return biClrImportant;
	}
	public void setBiClrImportant(byte[] biClrImportant) {
		this.biClrImportant = biClrImportant;
	}

}

package com.pan.entity;

/**
 * @author yp2
 * @date 2015-11-17
 * @description Bmp调色板
 */
public class BmpPalette {
	
	private byte[][] palettes;		//颜色索引映射表

	public byte[][] getPalettes() {
		return palettes;
	}

	public void setPalettes(byte[][] palettes) {
		this.palettes = palettes;
	}
	

}



package com.pan.utils;

/**
 * @author yp2
 * @date 2015-11-18
 * @description 字节操作工具
 */
public class ByteUtil {

	/**
	 * 将byte数组转换为16进制字符串
	 * 
* 实现思路: * 先将byte转换成int,再使用Integer.toHexString(int) * @param data byte数组 * @return */ public static String byteToHex(byte[] data, int start, int end) { StringBuilder builder = new StringBuilder(); for(int i = start; i < end; i++) { int tmp = data[i] & 0xff; String hv = Integer.toHexString(tmp); if(hv.length() < 2) { builder.append("0"); } builder.append(hv); /*builder.append(" ");*/ if(i % 16 == 15) { /*builder.append("\n");*/ } } return builder.toString(); } /** * 将byte数组转换为16进制字符串(该字符串方便查看) * 输出信息版:16个字节一行显示 * @param data * @param start * @param end * @return */ public static String byteToHexforPrint(byte[] data, int start, int end) { StringBuilder builder = new StringBuilder(); for(int i = start; i < end; i++) { int tmp = data[i] & 0xff; String hv = Integer.toHexString(tmp); if(hv.length() < 2) { builder.append("0"); } builder.append(hv); builder.append(" "); if(i % 16 == 15) { builder.append("\n"); } } return builder.toString(); } /** * 十六进制字符串转换为字节数组 * @param hexStr 十六进制字符串 * @return 字节数组 */ public static byte[] hexToByte(String hexStr) { byte[] datas = new byte[(hexStr.length() - 1) / 2 + 1]; hexStr = hexStr.toUpperCase(); int pos = 0; for(int i = 0; i < hexStr.length(); i+=2) { if(i + 1 < hexStr.length()) { datas[pos] = (byte) ((indexOf(hexStr.charAt(i)+"") << 4) + indexOf(hexStr.charAt(i+1)+"")); } pos++; } return datas; } /** * 计算指定字符串(这里要求是字符)的16进制所表示的数字 * @param str * @return */ public static int indexOf(String str) { return "0123456789ABCDEF".indexOf(str); } /** * 计算byte数组所表示的值,字节数组的值以小端表示,低位在低索引上,高位在高索引 *
* 例:data = {1,2},那么结果为: 2 << 8 + 1 = 513 * @param data byte数组 * @return 计算出的值 */ public static long lowByteToLong(byte[] data) { long sum = 0; for(int i = 0; i < data.length; i++) { long value = ((data[i] & 0xff) << (8 * i)); sum += value; } return sum; } /** * 计算byte数组所表示的值,字节数组的值以大端表示,低位在高索引上,高位在低索引 *
* 例:data = {1,2},那么结果为: 1 << 8 + 2 = 258 * @param data byte数组 * @return 计算出的值 */ public static long highByteToLong(byte[] data) { long sum = 0; for(int i = 0; i < data.length; i++) { long value = ((data[i] & 0xff) << (8 * (data.length - i - 1))); sum += value; } return sum; } /** * 计算byte数组所表示的值,字节数组的值以小端表示,低位在低索引上,高位在高索引 *
* 例:data = {1,2},那么结果为: 2 << 8 + 1 = 513 * @param data byte数组 * @return 计算出的值 */ public static int lowByteToInt(byte[] data) { int sum = 0; for(int i = 0; i < data.length; i++) { long value = ((data[i] & 0xff) << (8 * i)); sum += value; } return sum; } /** * 计算byte数组所表示的值,字节数组的值以大端表示,低位在高索引上,高位在低索引 *
* 例:data = {1,2},那么结果为: 1 << 8 + 2 = 258 * @param data byte数组 * @return 计算出的值 */ public static int highByteToInt(byte[] data) { int sum = 0; for(int i = 0; i < data.length; i++) { long value = ((data[i] & 0xff) << (8 * (data.length - i - 1))); sum += value; } return sum; } /** * long值转换为指定长度的小端字节数组 * @param data long值 * @param len 长度 * @return 字节数组,小端形式展示 */ public static byte[] longToLowByte(long data, int len) { byte[] value = new byte[len]; for(int i = 0; i < len; i++) { value[i] = (byte) ((data >> (8 * i )) & 0xff); } return value; } /** * long值转换为指定长度的大端字节数组 * @param data long值 * @param len 长度 * @return 字节数组,大端形式展示 */ public static byte[] longToHighByte(long data, int len) { byte[] value = new byte[len]; for(int i = 0; i < len; i++) { value[i] = (byte) ((data >> (8 * (len - 1 - i) )) & 0xff); } return value; } /** * int值转换为指定长度的小端字节数组 * @param data int值 * @param len 长度 * @return 字节数组,小端形式展示 */ public static byte[] intToLowByte(int data, int len) { byte[] value = new byte[len]; for(int i = 0; i < len; i++) { value[i] = (byte) ((data >> (8 * i )) & 0xff); } return value; } /** * int值转换为指定长度的大端字节数组 * @param data int值 * @param len 长度 * @return 字节数组,大端形式展示 */ public static byte[] intToHighByte(int data, int len) { byte[] value = new byte[len]; for(int i = 0; i < len; i++) { value[i] = (byte) ((data >> (8 * (len - 1 - i) )) & 0xff); } return value; } /** * 计算base的exponent次方 * @param base 基数 * @param exponent 指数 * @return */ public static long power(int base, int exponent) { long sum = 1; for(int i = 0; i < exponent; i++) { sum *= base; } return sum; } public static void main(String[] args) { byte[] data = new byte[]{1,2}; System.out.println(highByteToInt(data)); System.out.println(lowByteToInt(data)); System.out.println(byteToHex(intToHighByte(258, 4), 0, 4)); System.out.println(byteToHex(intToLowByte(258, 4), 0, 4)); } }




package com.pan.utils;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import com.pan.entity.Bmp;
import com.pan.entity.BmpHeader;
import com.pan.entity.BmpInfoHeader;
import com.pan.entity.BmpPalette;

/**
 * @author yp2
 * @date 2015-11-18
 * @description 重构后的Bmp工具
 * 
* 主要做了几件事:
* 1.位图数据可以不存储,在需要写入的时候再去读原文件的位图数据部分
* 2.抽除掉重复功能的代码
*/ public class BmpUtilRefactoring { /** * 读取指定bmp文件的信息到对象中 * @param bmpFile bmp文件路径 * @return 代表Bmp文件信息的对象 */ private static Bmp readBmp(String bmpFile) { Bmp bmp = new Bmp(); File file = new File(bmpFile); InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(file)); in.mark(0); readBmpHeader(bmp, in); long bfOffBits = ByteUtil.lowByteToLong(bmp.getBmpHeader().getBfOffBits()); long biSize = ByteUtil.lowByteToLong(bmp.getBmpInfoHeader().getBiSize()); long biBitCount = ByteUtil.lowByteToLong(bmp.getBmpInfoHeader().getBiBitCount()); int index = (int) (14 + biSize); //重新定位到调色板 in.reset(); in.skip(index); if(bfOffBits - biSize - 14 == 0) { //没有调色板 System.out.println(ByteUtil.lowByteToLong(bmp.getBmpInfoHeader().getBiBitCount()) + "位色无调色板"); } else { //有调色板 byte[][] palettes = new byte[(int) ByteUtil.power(2, (int) biBitCount)][4]; for(int i = 0; i < palettes.length && index < bfOffBits; i++) { in.read(palettes[i], 0, palettes[i].length); index += palettes[i].length; } BmpPalette bmpPalette = new BmpPalette(); bmpPalette.setPalettes(palettes); bmp.setBmpPalette(bmpPalette); } //记录bmp文件位图数据 /* int len = -1; byte[] buf = new byte[1024]; StringBuilder data = new StringBuilder(); while((len = in.read(buf, 0, buf.length)) > 0) { data.append(ByteUtil.byteToHex(buf,0, len)); } bmp.setDatas(ByteUtil.hexToByte(data.toString()));*/ } catch (IOException e) { e.printStackTrace(); } finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } return bmp; } /** * 读取bmp文件输入流的头部信息到Bmp中的头部信息中,要求输入流处于文件的开头 * @param bmp Bmp对象 * @param in bmp文件输入流 * @throws IOException */ private static void readBmpHeader(Bmp bmp, InputStream in) throws IOException { BmpHeader bmpHeader = new BmpHeader(); in.read(bmpHeader.getBfType(), 0, bmpHeader.getBfType().length); in.read(bmpHeader.getBfSize(), 0, bmpHeader.getBfSize().length); in.read(bmpHeader.getBfReserved1(), 0, bmpHeader.getBfReserved1().length); in.read(bmpHeader.getBfReserved2(), 0, bmpHeader.getBfReserved2().length); in.read(bmpHeader.getBfOffBits(), 0, bmpHeader.getBfOffBits().length); bmp.setBmpHeader(bmpHeader); BmpInfoHeader bmpInfoHeader = new BmpInfoHeader(); in.read(bmpInfoHeader.getBiSize(), 0, bmpInfoHeader.getBiSize().length); in.read(bmpInfoHeader.getBiWidth(), 0, bmpInfoHeader.getBiWidth().length); in.read(bmpInfoHeader.getBiHeight(), 0, bmpInfoHeader.getBiHeight().length); in.read(bmpInfoHeader.getBiPlans(), 0, bmpInfoHeader.getBiPlans().length); in.read(bmpInfoHeader.getBiBitCount(), 0, bmpInfoHeader.getBiBitCount().length); in.read(bmpInfoHeader.getBiCompression(), 0, bmpInfoHeader.getBiCompression().length); in.read(bmpInfoHeader.getBiSizeImage(), 0, bmpInfoHeader.getBiSizeImage().length); in.read(bmpInfoHeader.getBiXPelsPerMeter(), 0, bmpInfoHeader.getBiXPelsPerMeter().length); in.read(bmpInfoHeader.getBiYPelsPerMeter(), 0, bmpInfoHeader.getBiYPelsPerMeter().length); in.read(bmpInfoHeader.getBiClrUsed(), 0, bmpInfoHeader.getBiClrUsed().length); in.read(bmpInfoHeader.getBiClrImportant(), 0, bmpInfoHeader.getBiClrImportant().length); bmp.setBmpInfoHeader(bmpInfoHeader); } /** * 写入要隐藏文件的内容和原Bmp文件信息到指定数据文件中 * @param bmp 原Bmp文件信息 * @param inputFileName 要隐藏的文件 * @param outFileName 输出的文件 * @throws IOException */ private static void writeFileToBmp(Bmp bmp, String bmpFileName, String inputFileName, String outFileName) throws IOException { File inputFile = new File(inputFileName); File outFile = new File(outFileName); File bmpFile = new File(bmpFileName); if(!outFile.exists()) { outFile.createNewFile(); } //记录原来bmp文件的数据偏移位置 long oldbfOffBits = ByteUtil.lowByteToLong(bmp.getBmpHeader().getBfOffBits()); //计算出新的数据偏移位置:= 原来的偏移位置 + 要隐藏文件的总字节数 long bfOffBits = inputFile.length() + ByteUtil.lowByteToLong(bmp.getBmpHeader().getBfOffBits()); //设置新的数据偏移位置,以便写入新的文件中 bmp.getBmpHeader().setBfOffBits(ByteUtil.longToLowByte(bfOffBits, 4)); InputStream in = null; InputStream bmpIn = null; OutputStream out = null; try { in = new FileInputStream(inputFile); bmpIn = new BufferedInputStream(new FileInputStream(bmpFile)); out = new FileOutputStream(outFile); //将bmp头部信息写入输入流中 writeBmpHeader(bmp, out); //写入要隐藏的文件内容 int len = -1; byte[] buf = new byte[1024]; while((len = in.read(buf)) > 0) { out.write(buf, 0, len); } //跳过头部和调色板信息 bmpIn.skip(oldbfOffBits); len = -1; //写入原有位图数据 while((len = bmpIn.read(buf)) > 0) { out.write(buf, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { try { in.close(); out.close(); bmpIn.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 将文件内容写入到指定的位图文件内,并改变输出文件名 * @param bmpFileName 位图文件名 * @param inputFileName 要隐藏的文件名 * @param outFileName 输出文件名 * @throws IOException */ public static void writeFileToBmpFile(String bmpFileName, String inputFileName, String outFileName) throws IOException { Bmp bmp = readBmp(bmpFileName); writeFileToBmp(bmp, bmpFileName, inputFileName, outFileName); } /** * 读取bmp文件中隐藏的文件内容到指定的输出文件中去 * @param bmpFileName bmp文件名 * @param outFileName 输出文件名 * @throws IOException */ public static void readFileFromBmpFile(String bmpFileName, String outFileName) throws IOException { File bmpFile = new File(bmpFileName); File outFile = new File(outFileName); Bmp bmp = new Bmp(); if(!outFile.exists()) { outFile.createNewFile(); } InputStream in = null; OutputStream out = null; int len = -1; try { in = new BufferedInputStream(new FileInputStream(bmpFile)); out = new FileOutputStream(outFile); //标记当前输入流位置,方便后面reset跳转到当前输入流读取位置 in.mark(0); //读取输入流中包含的头部信息 readBmpHeader(bmp, in); //数据偏移位置 long bfOffBits = ByteUtil.lowByteToLong(bmp.getBmpHeader().getBfOffBits()); //使用的颜色索引数目 long biClrUsed = ByteUtil.lowByteToLong(bmp.getBmpInfoHeader().getBiClrUsed()); //位图信息头部字节数 long biSize = ByteUtil.lowByteToLong(bmp.getBmpInfoHeader().getBiSize()); //比特/像素 long biBitCount = ByteUtil.lowByteToLong(bmp.getBmpInfoHeader().getBiBitCount()); //重置到mark标记的位置,这里是跳转到输入流的开头 in.reset(); //保存当前文件输入流位置(字节位置) long sumLen = 0; if(biBitCount < 24) { if(biClrUsed == 0) { //索引全部都重要 //跳过输入流中的54 + 调色板所占字节数 个字节,这样其实就跳转到了保存隐藏文件内容的位置 in.skip(14 + biSize + ByteUtil.power(2, (int) biBitCount) * 4); sumLen = 14 + biSize + ByteUtil.power(2, (int) biBitCount) * 4; } else { //部分重要 in.skip(14 + biSize + biClrUsed * 4); sumLen = 14 + biSize + biClrUsed * 4; } } else { //没有调色板 in.skip(14 + biSize); sumLen = 14 + biSize; } byte[] buf = new byte[1024]; while((len = in.read(buf)) > 0) { if((sumLen + len) > bfOffBits) { //如果超过了数据偏移位置,则截取剩余的字节进行保存 out.write(buf, 0, (int) (bfOffBits - sumLen)); break; } else { //没有超过数据偏移位置,则截取读取到的字节 out.write(buf, 0, len); } sumLen += len; } } catch (Exception e) { e.printStackTrace(); in.close(); out.close(); } } /** * 将bmp头部信息和调色板信息写入输入流中 * @param out * @param bmp * @throws IOException */ private static void writeBmpHeader(Bmp bmp, OutputStream out) throws IOException { BmpHeader bmpHeader = bmp.getBmpHeader(); out.write(bmpHeader.getBfType()); out.write(bmpHeader.getBfSize()); out.write(bmpHeader.getBfReserved1()); out.write(bmpHeader.getBfReserved2()); out.write(bmpHeader.getBfOffBits()); BmpInfoHeader bmpInfoHeader = bmp.getBmpInfoHeader(); out.write(bmpInfoHeader.getBiSize()); out.write(bmpInfoHeader.getBiWidth()); out.write(bmpInfoHeader.getBiHeight()); out.write(bmpInfoHeader.getBiPlans()); out.write(bmpInfoHeader.getBiBitCount()); out.write(bmpInfoHeader.getBiCompression()); out.write(bmpInfoHeader.getBiSizeImage()); out.write(bmpInfoHeader.getBiXPelsPerMeter()); out.write(bmpInfoHeader.getBiYPelsPerMeter()); out.write(bmpInfoHeader.getBiClrUsed()); out.write(bmpInfoHeader.getBiClrImportant()); BmpPalette bmpPalette = bmp.getBmpPalette(); if(bmpPalette != null && bmpPalette.getPalettes() != null) { for(int i = 0; i < bmpPalette.getPalettes().length; i++) { out.write(bmpPalette.getPalettes()[i]); } } } }

package com.pan.main;

import java.io.IOException;

import com.pan.utils.BmpUtilRefactoring;

public class Main {

	public static void main(String[] args) throws IOException {
		
		/*1位色*/
		BmpUtilRefactoring.writeFileToBmpFile(Main.class.getClassLoader().getResource("resource/SmallConfetti.bmp").getPath(),
				Main.class.getClassLoader().getResource("resource/SmallConfettiscrect.txt").getPath(),
				Main.class.getClassLoader().getResource("resource/").getPath() + "SmallConfettiout.bmp");
		
		BmpUtilRefactoring.readFileFromBmpFile(Main.class.getClassLoader().getResource("resource/").getPath() + "SmallConfettiout.bmp",
				Main.class.getClassLoader().getResource("resource/").getPath() + "SmallConfettiscrectout.txt");
	
		/*4位色*/
		BmpUtilRefactoring.writeFileToBmpFile(Main.class.getClassLoader().getResource("resource/verisign.bmp").getPath(),
				Main.class.getClassLoader().getResource("resource/verisignscrect.txt").getPath(),
				Main.class.getClassLoader().getResource("resource/").getPath() + "verisignout.bmp");
		
		BmpUtilRefactoring.readFileFromBmpFile(Main.class.getClassLoader().getResource("resource/").getPath() + "verisignout.bmp",
				Main.class.getClassLoader().getResource("resource/").getPath() + "verisignscrectout.txt");
	
		BmpUtilRefactoring.writeFileToBmpFile(Main.class.getClassLoader().getResource("resource/srun.bmp").getPath(),
				Main.class.getClassLoader().getResource("resource/srunscrect.txt").getPath(),
				Main.class.getClassLoader().getResource("resource/").getPath() + "srunout.bmp");
		BmpUtilRefactoring.readFileFromBmpFile(Main.class.getClassLoader().getResource("resource/").getPath() + "srunout.bmp",
				Main.class.getClassLoader().getResource("resource/").getPath() + "srunscrectout.txt");
		
		/*8位色*/
		BmpUtilRefactoring.writeFileToBmpFile(Main.class.getClassLoader().getResource("resource/SplashScreen.bmp").getPath(),
				Main.class.getClassLoader().getResource("resource/SplashScreenscrect.txt").getPath(),
				Main.class.getClassLoader().getResource("resource/").getPath() + "SplashScreenout.bmp");
		
		BmpUtilRefactoring.readFileFromBmpFile(Main.class.getClassLoader().getResource("resource/").getPath() + "SplashScreenout.bmp",
				Main.class.getClassLoader().getResource("resource/").getPath() + "SplashScreenscrectout.txt");
		
		/*24位色*/
		BmpUtilRefactoring.writeFileToBmpFile(Main.class.getClassLoader().getResource("resource/background.bmp").getPath(),
				Main.class.getClassLoader().getResource("resource/backgroundscrect.txt").getPath(),
				Main.class.getClassLoader().getResource("resource/").getPath() + "backgroundout.bmp");
		
		BmpUtilRefactoring.readFileFromBmpFile(Main.class.getClassLoader().getResource("resource/").getPath() + "backgroundout.bmp",
				Main.class.getClassLoader().getResource("resource/").getPath() + "backgroundscrectout.txt");
		
		/*32位色*/
		BmpUtilRefactoring.writeFileToBmpFile(Main.class.getClassLoader().getResource("resource/WindowsMail.bmp").getPath(),
				Main.class.getClassLoader().getResource("resource/WindowsMailscrect.txt").getPath(),
				Main.class.getClassLoader().getResource("resource/").getPath() + "WindowsMailout.bmp");
		
		BmpUtilRefactoring.readFileFromBmpFile(Main.class.getClassLoader().getResource("resource/").getPath() + "WindowsMailout.bmp",
				Main.class.getClassLoader().getResource("resource/").getPath() + "WindowsMailscrectout.txt");
		
		
	}

}

代码下载:搓 http://download.csdn.net/detail/u012009613/9280153

转载请注明出处,谢谢!

你可能感兴趣的:(兴趣编程)