首先要實現這個功能,你必須知道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工具
轉載請註明出處,謝謝!優化