首先要实现这个功能,你必须知道bmp位图文件的格式,这里我就很少说了,请看:http://www.cnblogs.com/xiehy/archive/2011/06/07/2074405.htmlhtml
接下来主要讲解实现的思路和源码:java
实现思路:
根据bmp的文件的格式(记录了文件大小,文件数据的位置等信息)和读取文件内容的方式(只读取指定偏移点的数据),
可得出:当咱们改变数据偏移点的值和文件的大小,将要隐藏的文件内容保存在头部到偏移点的区域便可。
实现步骤:
一、解析整个文件的格式信息
二、获取偏移点位置
三、定位到调色板结束位置,将文件数据插入到调色板结束位置后面
四、修改偏移位置,加上要隐藏文件的大小
五、从新写入文件中
读取文件步骤:
一、解析bmp文件格式
二、获取偏移位置end和比特/像素和颜色索引数目
三、定位到调色板的结束位置,即数据的开始位置start
四、读取start到end之间的数据到文件中,即为原来文件的内容
根据上述实现步骤,初步的实现已完成,后期完善某些不足之处,例读取位图信息时使用byte数组存储,
这样若是文件过大,可能会溢出
优化:
一、基本类型的字节的优化,避免强制转换
二、位图数据能够不存储,在须要写入的时候再去读原文件的位图数据部分
三、调色板数据在这个方法里也能够不存储,但其实不会很大,因此也没多大关系,可作可不作
四、抽除掉重复功能的代码
思考:
能够直接将文件数据写入到位图数据的最后面?
能够,这个更加的简单
实现步骤:
一、解析总的文件大小
二、读取bmp全部的数据到新的文件中
三、读取将要隐藏的文件的内容,写入到新的文件中
读取文件内容步骤:
一、解析出原来bmp文件的大小
二、将输入流读取位置跳到bmp文件尾
三、读取输入流中剩下的内容,写入到其它文件中便可
这种实现方式的关键在于解析bmp格式中记录的bmp文件的大小,其它什么都不须要获取,数据的隐藏性较差数组
重要源码:app
- package com.pan.entity;
-
- public class Bmp {
-
- private BmpHeader bmpHeader;
- private BmpInfoHeader bmpInfoHeader;
- private BmpPalette bmpPalette;
-
- 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;
-
- public class BmpHeader {
-
-
- private byte[] bfType;
-
- private byte[] bfSize;
-
- private byte[] bfReserved1;
-
- private byte[] bfReserved2;
-
- 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;
-
- public class BmpPalette {
-
- private byte[][] palettes;
-
- public byte[][] getPalettes() {
- return palettes;
- }
-
- public void setPalettes(byte[][] palettes) {
- this.palettes = palettes;
- }
-
-
- }
- package com.pan.utils;
-
- public class ByteUtil {
-
-
- 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);
-
- if(i % 16 == 15) {
-
- }
- }
- return builder.toString();
- }
-
-
- 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();
- }
-
-
- 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;
- }
-
-
- public static int indexOf(String str) {
- return "0123456789ABCDEF".indexOf(str);
- }
-
-
- 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;
- }
-
-
- 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;
- }
-
-
- 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;
- }
-
-
- 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;
- }
-
-
- 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;
- }
-
-
- 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;
- }
-
-
- 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;
- }
-
-
- 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;
- }
-
-
- 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;
-
- public class BmpUtilRefactoring {
-
-
- 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);
- }
-
-
-
-
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- return bmp;
- }
-
-
- 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);
- }
-
-
- 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();
- }
-
- 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);
-
- 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();
- }
- }
- }
-
-
- public static void writeFileToBmpFile(String bmpFileName, String inputFileName, String outFileName) throws IOException {
- Bmp bmp = readBmp(bmpFileName);
- writeFileToBmp(bmp, bmpFileName, inputFileName, outFileName);
- }
-
-
- 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);
-
- 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());
-
- in.reset();
-
- long sumLen = 0;
- if(biBitCount < 24) {
- if(biClrUsed == 0) {
-
-
- 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();
- }
- }
-
-
- 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 {
-
-
- 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");
-
-
- 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");
-
-
- 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");
-
-
- 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");
-
-
- 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工具
转载请注明出处,谢谢!优化