BMP文件中每個像素使用RGB來表示, LSB(Least Significant Bit)最低有效位對應每個顏色的最低位。顏色的範圍是0-255,人眼分辨不出+1/-1的變化。
相關知識點:
1. BMP文件格式;
1. node.js文件;
2.node.js的Buffer;
直接上代碼!
爲BMP文件添加信息的函數:
/**
* fileInput:需要寫入信息的BMP文件;
* fileOutput:寫好信息後的BMP文件;
* content:需要寫入的信息;
*/
exports.addWaterMark = function ( fileInput,fileOutput,content ){
//先檢查下是否是個文件
fs.stat( fileInput,function(err,stats) {
if (err) {
console.log(err.toString());
return;
} else {
if ( !stats.isFile() ) {
console.log( fileInput + ' is not a file!');
return;
}
}
});
//沒有信息的話就直接回去了
if( content.length==0 )
return;
//讀文件並且向裏面添加內容,addMark函數在後面
fs.readFile( fileInput,function (err,data){
if( err )
{
console.log(err.toString());
return;
}
addMark(data,content,fileOutput);
} );
};
//添加信息的函數
//data--文件內容,這個就是fs.readFile那個回調函數的data
//content--文件內容;
//fileOutput-輸出文件
function addMark(data,content,fileOutput){
//檢查文件標誌‘BM’--BMP文件標誌
if( data[0]!=0x42 | data[1]!=0x4D )
return;
let i,j,ch1,ch2,index,bitLength;
let startIndex = 54;//BMP文件的圖像數據是從第54Byte開始的
//添加標誌信息(010101),有這個的話表示這個文件已經被寫入過信息了
data[startIndex] = data[startIndex] & 0b1110;
data[startIndex+1] = data[startIndex+1] | 0b0001;
data[startIndex+2] = data[startIndex+2] & 0b1110;
data[startIndex+3] = data[startIndex+3] | 0b0001;
data[startIndex+4] = data[startIndex+4] & 0b1110;
data[startIndex+5] = data[startIndex+5] | 0b0001;
//使用Buffer
let buf = Buffer.from( content,'utf-8' );
//計算並存儲內容長度信息--32位
index = startIndex + 6;
bitLength = 8*buf.length;
for( i=0;i<32;i++ )
{
data[index] = data[index] & 0b1110;
data[index] = data[index] | ( (bitLength>>i) & 0x0001 );
index++;
}
//添加內容
index = startIndex + 38;
for( i=0;i<buf.length;i++ )
{
ch1 = buf[i];
for( j=0;j<8;j++ )
{
ch2 = data[index];
ch2 = ( ch2 & 0b1110 );//set last bit to 0
data[index] = ( ch2 + ((ch1>>j) & 0x01) );
index++;
}
}
if( fs.existsSync(fileOutput) )
fs.unlinkSync( fileOutput );
//寫入BMP文件
fs.writeFile( fileOutput,data,function (err){
if( err )
console.log(err);
});
};
從BMP獲取寫入的內容:
//fileInput:BMP文件
exports.getWaterMark = function ( fileInput ) {
let content;
//check file is a file
fs.stat( fileInput,function(err,stats) {
if (err) {
console.log(err.toString());
return;
} else {
if ( !stats.isFile() ) {
console.log( fileInput + ' is not a file!');
return;
}
}
});
//調用getMark函數,並得到寫入的內容,getMark函數在下面
return getMark( fs.readFileSync(fileInput) );
};
//data--文件內容, fs.readFileSync(fileInput)讀出來的文件數據
function getMark(data){
if( data[0]!=0x42 | data[1]!=0x4D )
return;
let i,j,index,bitLength,byteLength;
let content;
//檢查是否被標記過(010101)
let startIndex = 54;
if( ( (data[startIndex] & 0x01)==0 ) &&
( (data[startIndex+1] & 0x01)==1 ) &&
( (data[startIndex+2] & 0x01)==0 ) &&
( (data[startIndex+3] & 0x01)==1 ) &&
( (data[startIndex+4] & 0x01)==0 ) &&
( (data[startIndex+5] & 0x01)==1 ) )
{
//獲取內容的長度
index = startIndex + 6;
bitLength = 0;
for( i=0;i<32;i++ )
{
bitLength = bitLength | (((data[index] & 0b0001))<<i);
index++;
}
//獲取內容
byteLength = bitLength/8;
index = startIndex + 38;
let buf = Buffer.alloc( byteLength );
for( i=0;i<byteLength;i++ )
{
for( j=0;j<8;j++ )
{
buf[i] = buf[i] | (( data[index] & 0x01 )<<j );
index++;
}
}
content = buf.toString('utf-8');
}
return content;
};