Linux下BMP圖片添加水印
??BMP是英文Bitmap(位圖)的簡寫,它是Windows作業系統中的標準影像檔案格式,能夠被多種Windows應用程式所支持,隨著Windows作業系統的流行與豐富的Windows應用程式的開發,BMP位圖格式理所當然地被廣泛應用,這種格式的特點是包含的影像資訊較豐富,幾乎不進行壓縮,但由此導致了它與生俱來的缺點–占用磁盤空間過大,所以,目前BMP在單機上比較流行,
??給BMP圖片添加水印的方法有很多,本示例采用直接讀寫檔案方式來添加水印,
- 示例效果
原始圖片

運行程式
[xsw@xsw BMP_stady]$ ./a.out
格式:./a.out <1.bmp> <2.bmp>
[xsw@xsw BMP_stady]$ ./a.out watermark.bmp 2.bmp
圖片寬:500
圖片高:312
請輸入水印添加的位置(x:0~500 y:0~312):600 200
[BMP_add_Watermark line 117]超出顯示邊線,請重新輸入
請輸入水印添加的位置(x:0~500 y:0~312):100 100
[xsw@xsw BMP_stady]$

- 程式示例
- 添加水印函式
/**********************添加水印************************************
**形參:
** char *new_bmp ---新生成的圖片
** char *bmp_file ---需要添加水印的圖片
** int num --- 要添加幾個漢字水印
** int size --- 漢字大小(等高寬)
**回傳值:0 成功,其他值---錯誤
*******************************************************************/
int BMP_add_Watermark(char *new_bmp,char *befor_bmp,int num,int size)
{
FILE *fp[2];
fp[0]=fopen(befor_bmp,"rb");
if(fp[0]==NULL)
{
printf("[%s line %d]檔案打開失敗",__FUNCTION__,__LINE__);
return 1;
}
fp[1]=fopen(new_bmp,"w+b");
if(fp[1]==NULL)
{
printf("[%s line %d]檔案打開或創建失敗",__FUNCTION__,__LINE__);
return 2;
}
BMP_HEADER bmp_head;
BMP_INFO bmp_info;
fread(&bmp_head,sizeof(BMP_HEADER),1,fp[0]);//讀取頭資料
fwrite(&bmp_head,sizeof(BMP_HEADER),1,fp[1]);//頭資料寫入到新的檔案中
fread(&bmp_info,sizeof(BMP_INFO),1,fp[0]);//讀取位圖資料
fwrite(&bmp_info,sizeof(BMP_INFO),1,fp[1]);//位圖資料寫入到新的檔案中
if(bmp_head.bfType!=0x4d42)
{
printf("[%s line %d]圖片格式錯誤\n",__FUNCTION__,__LINE__);
return 3;
}
printf("\t圖片寬:%d\n",bmp_info.biWidth);
printf("\t圖片寬:%d\n",bmp_info.biHeight);
int one_line_size=bmp_info.biWidth*3;//一行的位元組數
while(one_line_size%4!=0)one_line_size++;//位元組數不是4的倍數補全
unsigned char one_line_buff[one_line_size];
int i;
/*復制圖片*/
for(i=0;i<bmp_info.biHeight;i++)
{
fread(one_line_buff,one_line_size,1,fp[0]);
fwrite(one_line_buff,one_line_size,1,fp[1]);
}
fclose(fp[0]);//關閉舊檔案
int x,y;
pp:
printf("\n\t請輸入水印添加的位置(x:0~%d y:0~%d):",bmp_info.biWidth,bmp_info.biHeight);
scanf("%d%d",&x,&y);
if(x>bmp_info.biWidth-num*size || y>bmp_info.biHeight-size)
{
printf("\n\t[%s line %d]超出顯示邊線,請重新輸入\n",__FUNCTION__,__LINE__);
goto pp;
}
int j,k;
int y1=y;
unsigned char data=0;
int rgb=0xff0000;//設定水印的顏色
int cnt=0;
for(k=0;k<num;k++)
{
fseek(fp[1],bmp_head.bfOffBits+one_line_size*(bmp_info.biHeight-y)+x*3+k*size*3,SEEK_SET);//偏移到需要添加水印位置
y1=y;
for(i=0;i<size*size/8;i++)
{
data=font_buff[k][i];//取出點陣資料
for(j=0;j<8;j++)
{
if(data&0x80)
{
fwrite(&rgb,3,1,fp[1]);//寫入顏色
}
else
{
fseek(fp[1],3,SEEK_CUR);//保持底色,往后偏移
}
data=data<<1;
}
cnt++;
if(cnt==size/8)//寫完一行,換到下一行
{
cnt=0;
y1++;
fseek(fp[1],bmp_head.bfOffBits+one_line_size*(bmp_info.biHeight-y1)+x*3+k*size*3,SEEK_SET);//偏移到需要添加水印位置
}
}
}
fclose(fp[1]);
return 0;
}
- 主函式
int main(int argc,char **argv)
{
if(argc!=3)
{
printf("格式:./a.out <1.bmp> <2.bmp>\n");
return 0;
}
int stat=0;
char buff[20];
stat=BMP_add_Watermark(argv[1],argv[2],4,24);
if(stat==0)
{
snprintf(buff,sizeof(buff),"eog %s",argv[1]);//字串拼接
system(buff);//創建行程
}
else printf("[%s line %d] err %d\n",__FUNCTION__,__LINE__,stat);
return 0;
}
- BMP格式結構體
#pragma pack(1) /* 必須在結構體定義之前使用,這是為了讓結構體中各成員按1位元組對齊*/
/*圖片頭*/
typedef struct BitMapFileHEADER
{
unsigned short bfType; //保存圖片型別, 'BM'
unsigned long bfSize; //圖片檔案的總大小,以位元組為單位(3-6位元組,低位在前)
unsigned short bfReserved1;//位圖檔案保留字,必須為0(7-8位元組)
unsigned short bfReserved2;//位圖檔案保留字,必須為0(9-10位元組)
unsigned long bfOffBits; //RGB資料偏移地址,位圖資料的起始位置,以相對于位圖(11-14位元組,低位在前)//檔案頭的偏移量表示,以位元組為單位
}BMP_HEADER;
/*圖片資訊*/
typedef struct BitMapFileInfo{
unsigned long biSize; //本結構所占用位元組數(15-18位元組)
unsigned long biWidth; //位圖的寬度,以像素為單位(19-22位元組)
unsigned long biHeight; //位圖的高度,以像素為單位(23-26位元組)
unsigned short biPlanes; //目標設備的級別,必須為1(27-28位元組)
unsigned short biBitCount; //每個像素所需的位數,必須是1(雙色)(29-30位元組),4(16色),8(256色)16(高彩色)或24(真彩色)之一
unsigned long biCompression;//位圖壓縮型別,必須是0(不壓縮),(31-34位元組)
//1(BI_RLE8壓縮型別)或2(BI_RLE4壓縮型別)之一
unsigned long biSizeImage; //位圖的大小(其中包含了為了補齊行數是4的倍數而添加的空位元組),以位元組為單位(35-38位元組)
unsigned long biXPelsPerMeter;//位圖水平解析度,每米像素數(39-42位元組)
unsigned long biYPelsPerMeter;//位圖垂直解析度,每米像素數(43-46位元組)
unsigned long biClrUsed; //位圖實際使用的顏色表中的顏色數(47-50位元組)
unsigned long biClrImportant; //位圖顯示程序中重要的顏色數(51-54位元組)
}BMP_INFO;
- 漢字取模電陣
//牛轉乾坤取模
const unsigned char font_buff[][24*24/8]=
{
{0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x0C,0x00,0x00,0x0C,0x00,0x00,0x08,0x00,0x01,0x88,0x00,0x01,0x88,0x00,0x01,0x8F,0xC0,0x03,0xFC,0x00,0x02,0x08,0x00,0x04,0x08,0x00,0x00,0x08,0x7C,
0x00,0x7F,0xFE,0x3F,0xC8,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x00,0x00},/*"牛",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x81,0x80,0x01,0x01,0x80,0x03,0x01,0x00,0x02,0xE1,0x00,0x1F,0x81,0xF0,0x04,0x0F,0x00,0x05,0x82,0x00,0x09,0x02,0x1C,0x09,0xC7,0xF8,
0x1F,0x3A,0x00,0x01,0x06,0x00,0x01,0xC4,0xE0,0x0F,0x07,0x70,0x39,0x00,0x40,0x01,0x00,0x80,0x01,0x04,0x80,0x01,0x03,0x00,0x01,0x01,0x80,0x01,0x01,0x80,0x00,0x00,0x80,0x00,0x00,0x00},/*"轉",1*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x83,0x00,0x01,0x02,0x00,0x01,0xE6,0x00,0x0F,0x84,0x00,0x01,0x04,0x20,0x02,0x05,0xC0,0x03,0xEA,0x00,0x1C,0x70,0x00,0x19,0x60,0x00,
0x0E,0x41,0x80,0x09,0xCF,0x00,0x0F,0x02,0x00,0x01,0x24,0x00,0x01,0xC4,0x00,0x7F,0x08,0x04,0x21,0x08,0x04,0x01,0x0C,0x04,0x03,0x06,0x3C,0x01,0x03,0xF8,0x00,0x00,0x00,0x00,0x00,0x00},/*"乾",2*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x06,0x01,0x80,0x06,0x01,0x00,0x06,0x01,0x00,0x06,0x01,0x18,0x06,0x01,0xFC,0x06,0x7F,0x0C,0x07,0xA1,0x0C,0x1E,0x33,0xE8,0x06,0x37,0x18,
0x06,0x11,0x18,0x06,0x91,0x10,0x07,0x1F,0xF0,0x1C,0x11,0x00,0x30,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00},/*"坤",3*/
};
- 查看添加水印后的圖片
[xsw@xsw BMP_stady]$ eog watermark.bmp

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/254848.html
標籤:其他
