c语言添加透明水印代码实现
时间: 2023-08-19 14:28:23 浏览: 72
添加透明水印可以使用图像处理技术,具体步骤如下:
1. 读入原始图像和水印图像
2. 将水印图像转换为灰度图像
3. 对水印图像进行二值化处理
4. 对原始图像进行离散余弦变换(DCT)
5. 将二值化后的水印图像嵌入到原始图像的低频区域中
6. 对嵌入了水印的图像进行反离散余弦变换(IDCT)
7. 输出嵌入水印后的图像
下面是一个简单的示例代码,可供参考:
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define BLOCK_SIZE 8 // 块大小
#define ALPHA 0.1 // 水印强度
// 离散余弦变换
void dct(double **block) {
int i, j, k;
double ci, cj, sum;
double tmp[BLOCK_SIZE][BLOCK_SIZE];
for (i = 0; i < BLOCK_SIZE; i++) {
for (j = 0; j < BLOCK_SIZE; j++) {
sum = 0;
for (k = 0; k < BLOCK_SIZE; k++) {
sum += block[i][k] * cos((2 * k + 1) * j * M_PI / (2 * BLOCK_SIZE));
}
tmp[i][j] = sum;
}
}
for (i = 0; i < BLOCK_SIZE; i++) {
for (j = 0; j < BLOCK_SIZE; j++) {
sum = 0;
for (k = 0; k < BLOCK_SIZE; k++) {
sum += cos((2 * i + 1) * k * M_PI / (2 * BLOCK_SIZE)) * tmp[k][j];
}
block[i][j] = sum / BLOCK_SIZE;
}
}
}
// 反离散余弦变换
void idct(double **block) {
int i, j, k;
double ci, cj, sum;
double tmp[BLOCK_SIZE][BLOCK_SIZE];
for (i = 0; i < BLOCK_SIZE; i++) {
for (j = 0; j < BLOCK_SIZE; j++) {
sum = 0;
for (k = 0; k < BLOCK_SIZE; k++) {
sum += block[i][k] * cos((2 * j + 1) * k * M_PI / (2 * BLOCK_SIZE));
}
tmp[i][j] = sum;
}
}
for (i = 0; i < BLOCK_SIZE; i++) {
for (j = 0; j < BLOCK_SIZE; j++) {
sum = 0;
for (k = 0; k < BLOCK_SIZE; k++) {
sum += cos((2 * i + 1) * k * M_PI / (2 * BLOCK_SIZE)) * tmp[k][j];
}
block[i][j] = sum / BLOCK_SIZE;
}
}
}
// 嵌入水印
void embed_watermark(double **block, double **watermark) {
int i, j;
double alpha = ALPHA * sqrt(BLOCK_SIZE); // 水印强度
for (i = 0; i < BLOCK_SIZE; i++) {
for (j = 0; j < BLOCK_SIZE; j++) {
if (i == 0 && j == 0) {
continue; // 跳过DC系数
}
block[i][j] += alpha * watermark[i][j];
}
}
}
// 读取图像
void read_image(const char *filename, double ***image, int *width, int *height) {
FILE *fp;
int i, j;
double **img;
fp = fopen(filename, "rb");
if (fp == NULL) {
fprintf(stderr, "Error: cannot open file '%s'\n", filename);
exit(1);
}
// 读取图像宽度和高度
fread(width, sizeof(int), 1, fp);
fread(height, sizeof(int), 1, fp);
// 分配内存
img = (double **) malloc(*height * sizeof(double *));
for (i = 0; i < *height; i++) {
img[i] = (double *) malloc(*width * sizeof(double));
}
// 读取图像数据
for (i = 0; i < *height; i++) {
for (j = 0; j < *width; j++) {
fread(&img[i][j], sizeof(double), 1, fp);
}
}
fclose(fp);
*image = img;
}
// 写入图像
void write_image(const char *filename, double **image, int width, int height) {
FILE *fp;
int i, j;
fp = fopen(filename, "wb");
if (fp == NULL) {
fprintf(stderr, "Error: cannot open file '%s'\n", filename);
exit(1);
}
// 写入图像宽度和高度
fwrite(&width, sizeof(int), 1, fp);
fwrite(&height, sizeof(int), 1, fp);
// 写入图像数据
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
fwrite(&image[i][j], sizeof(double), 1, fp);
}
}
fclose(fp);
}
// 主函数
int main(int argc, char *argv[]) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <input_image> <watermark_image> <output_image>\n", argv[0]);
exit(1);
}
double **image, **watermark, **block;
int width, height, i, j, k, l;
// 读取原始图像和水印图像
read_image(argv[1], &image, &width, &height);
read_image(argv[2], &watermark, &width, &height);
// 分块处理
for (i = 0; i < height; i += BLOCK_SIZE) {
for (j = 0; j < width; j += BLOCK_SIZE) {
// 提取块
block = (double **) malloc(BLOCK_SIZE * sizeof(double *));
for (k = 0; k < BLOCK_SIZE; k++) {
block[k] = (double *) malloc(BLOCK_SIZE * sizeof(double));
for (l = 0; l < BLOCK_SIZE; l++) {
block[k][l] = image[i + k][j + l];
}
}
// 离散余弦变换
dct(block);
// 嵌入水印
embed_watermark(block, watermark);
// 反离散余弦变换
idct(block);
// 恢复块
for (k = 0; k < BLOCK_SIZE; k++) {
for (l = 0; l < BLOCK_SIZE; l++) {
image[i + k][j + l] = block[k][l];
}
free(block[k]);
}
free(block);
}
}
// 写入输出图像
write_image(argv[3], image, width, height);
// 释放内存
for (i = 0; i < height; i++) {
free(image[i]);
free(watermark[i]);
}
free(image);
free(watermark);
return 0;
}
```
注意:该代码仅供参考,实际使用中还需要进行一些优化和改进,例如调整水印强度、选择更好的水印嵌入方式等。
阅读全文