關于bmp文件內部存儲格式參看:http://www.yymcu.com/resource/BMP%CE%C4%BC%FE%B8%F1%CA%BD%B7%D6%CE%F6.htm
以下是轉換的具體java實現,已經通過單元測試,copy之后能直接使用:
public class TransactionBmpTo16Bit{
?private String resFilePath;
?private String desFilePath;
?private Bmp currentBmp = null;
?
?public TransactionBmpTo16Bit(String resFilePath,String desFilePath){
??this.resFilePath = resFilePath;
??this.desFilePath = desFilePath;
?}
?
?/**
? * 把24bit的bmp圖像轉換為16bit的圖像
? *
? * @return
? */
?public boolean transacte(){
??currentBmp = new Bmp();
??try {
???byte[] fileContent = currentBmp.loadBmp(resFilePath);
???Bmp desBmp = new Bmp();
???byte[] changeContent = this.changeContent(fileContent);
???desBmp.setCurrent(changeContent);
???desBmp.save(desFilePath);
??} catch (IOException e) {
???e.printStackTrace();
???return false;
??} catch (BusinessException e) {
???e.printStackTrace();
???return false;
??}
??return true;
?}
?
?/**
? * 獲得新文件的大小
? *
? * @return
? */
?private int getNewFileSize(){
??return? currentBmp.getWeight()*currentBmp.getHight()*2+currentBmp.getDataOffset();
?}
?
?private byte[] changeContent(byte[] current){
??
??int newSize = this.getNewFileSize();
??byte[] newByt = new byte[newSize];
??for(int i=0;i<currentBmp.getDataOffset();i++){
???newByt[i] = current[i];
??}
??/*設置新的位圖大小*/
??byte[] sbt = NumberConversion.intToBytes(newSize,4);
??for(int i=2;i<6;i++){
???newByt[i]=sbt[5-i];
??}
??/*設置新的像素位數*/
??byte[] pixDigit = NumberConversion.intToBytes(16,2);
??newByt[28] = pixDigit[1];
??newByt[29] = pixDigit[0];
??
??
??//TODO 獲得轉化后的數據實現
??int dataSize = newSize-54;
??
??byte[] newData = new byte[dataSize];
??
??byte[][] data = this.getFiltratedArray(current);
??int tt = 0;
??for(int i=0;i<currentBmp.getHight();i++){
???
???for(int j=0;j<currentBmp.getWeight()*3;j++){
????tt+=1;
????if((j+1)%3==0){
?????byte n = (byte) ((((data[i][j-1])>>>5)&0x7)|(data[i][j]&0xF8));
?????byte m = (byte) (((data[i][j-2]>>>3)&0x1F)|((data[i][j-1]&0x1c)<<3));
?????int index = tt/3*2;
?????newData[index-2] = m;
?????newData[index-1] = n;
????}
???}
??}
??for(int i=54;i<newSize;i++){
???newByt[i] = newData[i-54];
??}
??return newByt;
?}
?
?/**
? * 過濾bmp補位的數據
? * @return
? */
?private byte[][] getFiltratedArray(byte[] current){
??
??int residue = (this.currentBmp.getWeight()*3)%4;
??int skip = 0;
??if(residue!=0) skip = 4-residue;
??
??byte[][] array = new byte[this.currentBmp.getHight()][this.currentBmp.getWeight()*3];
??
??int scale = this.currentBmp.getDataOffset();
??
??for(int i=0;i<this.currentBmp.getHight();i++){
//???scale += i*hight;
???for(int j=0;j<this.currentBmp.getWeight()*3;j++){
????
????array[i][j] = current[scale];
????scale += 1;
???}
//???System.out.println("scale="+scale);
???scale+=skip;
//???System.out.println("scale1="+scale);
??}
??return array;
??
?}
?
}
<!----------------------------------------------------
public class Bmp {
?
?protected final Log logger = LogFactory.getLog(getClass());
?
?public final static int BITMAPFILEHEADER_SIZE = 14;
?
?public final static int BITMAPINFOHEADER_SIZE = 40;
?/*文件大小*/
?private int size;
?/*文件寬度*/
?private int weight;
?/*文件高度*/
?private int hight;
?/*數據偏移量*/
?private int dataOffset;
?private byte[] current;
?private String filePath;
?
/*get(),set()方法考慮到節省篇幅,請自行設置*/
?public Bmp(){
??
?}
?
?/**
? * 加載bmp文件
? *
? * @param filePath
? * @return
? * @throws IOException
? * @throws BusinessException
? */
?public byte[] loadBmp(String filePath) throws IOException, BusinessException{
??
??this.filePath = filePath;
??this.setParam();
??
??return current;
?}
?
?/**
? * 保存bmp文件
? *
? * @param desPath
? * @throws BusinessException
? * @throws IOException
? */
?public void save(String desPath) throws BusinessException, IOException{
??if(current==null){
???throw new BusinessException("",null);
??}
??
??FileOutputStream fos = new FileOutputStream(desPath);
??fos.write(current,0,current.length);
??fos.flush();
??fos.close();
?}
?
?private void setParam() throws IOException, BusinessException{
??
??/*判斷源文件是否是bmp格式,后綴可以是.bmp、.dib、.rle*/
??if(!filePath.contains(".bmp")){
???throw new BusinessException("",null);
??}
??
??FileInputStream? fis = new FileInputStream(filePath);
??/*bmp文件頭存儲*/
??byte[] fh = new byte[BITMAPFILEHEADER_SIZE];
??fis.read(fh,0,BITMAPFILEHEADER_SIZE);
??/*文件頭信息存儲*/
??byte[] hi = new byte[BITMAPINFOHEADER_SIZE];
??fis.read(hi,0,BITMAPINFOHEADER_SIZE);
??
??/*設置文件長度*/
??this.size = (((int)fh[5]&0xff)<<24)
??????? ????| (((int)fh[4]&0xff)<<16)
??????? ?????| (((int)fh[3]&0xff)<<8)
??????? ??????| (int)fh[2]&0xff;
??/*設置文件寬度*/
??this.weight = (((int)hi[7]&0xff)<<24)
??????? ????| (((int)hi[6]&0xff)<<16)
??????? ?????| (((int)hi[5]&0xff)<<8)
??????? ??????| (int)hi[4]&0xff;
??/*設置文件高度*/
??this.hight = (((int)hi[11]&0xff)<<24)
??????| (((int)hi[10]&0xff)<<16)
???????| (((int)hi[9]&0xff)<<8)
????????| (int)hi[8]&0xff;
??/*設置位圖數據陣列起始偏移量*/
??this.dataOffset = (((int)fh[13]&0xff)<<24)
???????? ????| (((int)fh[12]&0xff)<<16)
???????? ?????| (((int)fh[11]&0xff)<<8)
???????? ??????| (int)fh[10]&0xff;
?
??fis.close();
??loadAll();
?}
?
?private void loadAll() throws IOException{
??
??FileInputStream? fis = new FileInputStream(filePath);
??current = new byte[size];
??
??fis.read(current,0,size);
??
??fis.close();
?}
}
<!----------------------------------
public class NumberConversion {
?
?/**
? * 整形轉化為二進制字節
? *
? * @param number??需要轉化的數字
? * @param bytes???字節數
? * @return
? */
?public static byte[] intToBytes(int number,int digit){
??
??byte[] byts = new byte[digit];
//??int mask=0xff;
??int basic = 8*(digit-1);
??for(int i=0;i<digit;i++){
???byts[i] = (byte)(number>>>(basic-i*8));
??}
??
??return byts;
??
?}
?
?/**
? *
? * @param bytes
? * @return
? */
?public static int bytesToInt(byte[] b){
??
??int mask=0xff;
??int temp=0;
??int res=0;
??
??for(int i=0;i<4;i++){
???????? res<<=8;
???????? temp=b[i]&mask;
???????? res|=temp;
??}
??return res;
?}
}