七仔的博客

七仔的博客GithubPages分博

0%

C语言打水印

c语言实现打水印,合成两张图片,去除水印图片的黑色,将剩下的像素添加到原图片上

C语言打水印

一、预览

1.准备两张图片

准备两张图片

2.合成结果

合成结果

二、代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>

unsigned char *pBmpBuf;//读入图像数据的指针
int bmpWidth;//图像的宽
int bmpHeight;//图像的高
RGBQUAD *pColorTable;//颜色表指针
int biBitCount;//图像类型,每像素位数
char readPath1[] = "D:/project/devcpp/img/input1.BMP";
char readPath2[]="D:/project/devcpp/img/input2.BMP";//读入指定BMP文件进内存
char writePath[]="D:/project/devcpp/img/output.BMP";

//读取图片
int readBmp(char *bmpName){
FILE *fp=fopen(bmpName,"rb");//二进制读方式打开指定的图像文件
if(fp==0){
printf("打水印失败\n");
return 0;
}

fseek(fp, sizeof(BITMAPFILEHEADER),0);//跳过位图文件头结构BITMAPFILEHEADER
BITMAPINFOHEADER head; //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
fread(&head, sizeof(BITMAPINFOHEADER), 1,fp);

bmpWidth = head.biWidth;
bmpHeight = head.biHeight;
biBitCount = head.biBitCount;//获取图像宽、高、每像素所占位数等信息
int lineByte=(bmpWidth * biBitCount/8+3)/4*4;//定义变量,计算图像每行像素所占的字节数(必须是4的倍数)

if(biBitCount==8){//灰度图像有颜色表,且颜色表表项为256
pColorTable=malloc(sizeof(RGBQUAD)*256); //申请颜色表所需要的空间,读颜色表进内存
fread(pColorTable,sizeof(RGBQUAD),256,fp);
}
pBmpBuf=malloc(sizeof(unsigned char)*lineByte * bmpHeight);//申请位图数据所需要的空间,读位图数据进内存
fread(pBmpBuf,1,lineByte * bmpHeight,fp);
fclose(fp);//关闭文件
return 1;
}

//保存图片
int saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height, int biBitCount, RGBQUAD *pColorTable){
if(!imgBuf)//如果位图数据指针为0,则没有数据传入,函数返回
return 0;
int colorTablesize=0;//颜色表大小,以字节为单位,灰度图像颜色表为1024字节,彩色图像颜色表大小为0
if(biBitCount==8)
colorTablesize=1024;
int lineByte=(width * biBitCount/8+3)/4*4;//待存储图像数据每行字节数为4的倍数
FILE *fp=fopen(bmpName,"wb");//以二进制写的方式打开文件
if(fp==0){
printf("!!!!\n");
return 0;
}

BITMAPFILEHEADER fileHead;//申请位图文件头结构变量,填写文件头信息
fileHead.bfType = 0x4D42;//bmp类型
fileHead.bfSize= sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTablesize+lineByte*height;//bfSize是图像文件4个组成部分之和
fileHead.bfReserved1 = 0;
fileHead.bfReserved2 = 0;
fileHead.bfOffBits=54+colorTablesize;//bfOffBits是图像文件前3个部分所需空间之和
fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);//写文件头进文件

BITMAPINFOHEADER head; //申请位图信息头结构变量,填写信息头信息
head.biBitCount=biBitCount;
head.biClrImportant=0;
head.biClrUsed=0;
head.biCompression=0;
head.biHeight=height;
head.biPlanes=1;
head.biSize=40;
head.biSizeImage=lineByte*height;
head.biWidth=width;
head.biXPelsPerMeter=0;
head.biYPelsPerMeter=0;
fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);//写位图信息头进内存

if(biBitCount==8)//如果灰度图像,有颜色表,写入文件
fwrite(pColorTable, sizeof(RGBQUAD),256, fp);
fwrite(imgBuf, height*lineByte, 1, fp);//写位图数据进文件
fclose(fp);//关闭文件
return 1;
}


int main(){
int o=0;//RGB计数器
printf("BMP文件录入位置:\n%s\n%s\n\n",readPath1,readPath2);
readBmp(readPath1);
unsigned char *pBmpBuf1=pBmpBuf;;//读入图像数据的指针
int bmpWidth1=bmpWidth;//图像的宽
int bmpHeight1=bmpHeight;//图像的高
RGBQUAD *pColorTable1=pColorTable;//颜色表指针
int biBitCount1=biBitCount;//图像类型,每像素位数
readBmp(readPath2);
unsigned char *pBmpBuf2=pBmpBuf;;//读入图像数据的指针
int bmpWidth2=bmpWidth;//图像的宽
int bmpHeight2=bmpHeight;//图像的高
RGBQUAD *pColorTable2=pColorTable;//颜色表指针
int biBitCount2=biBitCount;//图像类型,每像素位数
printf("第一张BMP:%d位 第二张BMP:%d位\n",biBitCount1,biBitCount2);

//循环变量,图像的坐标
int i,j;
//每行字节数
int lineByte1=(bmpWidth1*biBitCount1/8+3)/4*4;
int lineByte2=(bmpWidth2*biBitCount2/8+3)/4*4;
//循环变量,针对彩色图像,遍历每像素的三个分量
int k;
if(biBitCount1==8 && biBitCount2==8){//对于灰度图像
for(i=0;i<bmpHeight2;i++){
for(j=0;j<bmpWidth2;j++){
if(*(pBmpBuf2+i*lineByte2+j)!=0){
*(pBmpBuf1+i*lineByte1+j)=*(pBmpBuf2+i*lineByte2+j);
}
}
}
}
else if(biBitCount1==24 && biBitCount2==24){//彩色图像
for(i=0;i<bmpHeight2;i++){
for(j=0;j<bmpWidth2;j++){
for(k=0,o=0;k<3;k++){
if(*(pBmpBuf2+i*lineByte2+j*3+k)>5){//每像素RGB三个分量分别置0才变
o++;
}
if(o==3){
*(pBmpBuf1+i*lineByte1+j*3+0)=*(pBmpBuf2+i*lineByte2+j*3+0);
*(pBmpBuf1+i*lineByte1+j*3+1)=*(pBmpBuf2+i*lineByte2+j*3+1);
*(pBmpBuf1+i*lineByte1+j*3+2)=*(pBmpBuf2+i*lineByte2+j*3+2);
}
}
}
}
}

if(saveBmp(writePath, pBmpBuf1, bmpWidth1, bmpHeight1, biBitCount1, pColorTable1)){
printf("打水印成功\n\n");
printf("BMP文件保存位置:\n%s\n",writePath);
}
else{
printf("打水印失败");
}
//清除缓冲区,pBmpBuf和pColorTable是全局变量,在文件读入时申请的空间
free(pBmpBuf1);
free(pBmpBuf2);
if(biBitCount1==8)
free(pColorTable1);
if(biBitCount2==8)
free(pColorTable2);
return 0;
}

此为博主副博客,留言请去主博客,转载请注明出处:https://www.baby7blog.com/myBlog/2.html

欢迎关注我的其它发布渠道