两个步骤
1,用cairo库来生成一个图片,然后在上面把文字写到图片上
主要用到 cairo_image_curface_surface_create,生成一个空白的图(为了把文字向上写)
cairo_public cairo_surface_t *
cairo_image_surface_create (cairo_format_t format,
int width,
int height);
如果想要添加图片水印,也可以用cairo_image_surface_create_for_data,data就是源format类型的图像数据地址
cairo_public cairo_surface_t *
cairo_image_surface_create_for_data (unsigned char *data,
cairo_format_t format,
int width,
int height,
int stride);
创建完一个cairo surface之后,通过cairo_create来获取cairo_t的结构,类似一个画布,完了就可以往上面写字了
依次是设置字体颜色,透明度,字体格式(宋体之类的),字体大小,要写倾斜字,就提前通过cairo_rotate设置好角度
cairo_move_to,是接下来写字的坐标,cairo_show_text就是要写上的字符串(utf8格式)
cairo_t *cr = cairo_create(surface);
cairo_set_source_rgba(cr, 1.0, 0.0, 1.0, 1.0);
cairo_select_font_face(cr, "serif", 0, 0);
double font_size = 20;
double vSpacing = 50 + font_size;
cairo_set_font_size(cr, font_size);
cairo_save(cr);
double pos_x = 200;
double pos_y = 100;
double y0 = pos_y;
while(pos_x < src_w)
{
y0 = pos_y;
// while(y0 < src_h)
{
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo00");
y0 += vSpacing;
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo11");
y0 += vSpacing;
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo22");
y0 += vSpacing;
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo33");
}
pos_x += 200;
}
cairo_restore(cr);
2,用pixman库将两个图片合并
这里写了一个 add_watermark的函数,实际上是两个pixman_image_t的像素操作
void pixman_image_composite32 (pixman_op_t op,
pixman_image_t *src,
pixman_image_t *mask,
pixman_image_t *dest,
int32_t src_x,
int32_t src_y,
int32_t mask_x,
int32_t mask_y,
int32_t dest_x,
int32_t dest_y,
int32_t width,
int32_t height);
这个函数是把src和dst作用到一起,主要设计像素的位运算,具体请看这里
pixman ROP/alpha blend 线性变换_lidedongsn-CSDN博客
咱们就用简单的PIXMAN_OP_ADD
作用完把dst_image写到bmp,做对比,会发现生成的bmp已经是有水印的了
这里给出原图和效果图
原图
加了水印的图
最后贴上代码
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <pixman.h>
#include <cairo.h>
#pragma pack(2)
typedef struct BITMAPFILEHEADER
{
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
}BITMAPFILEHEADER;
typedef struct BITMAPINFOHEADER
{
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXPelsPerMeter;
uint32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
}BITMAPINFOHEADER;
static void bgra_to_bmp(uint8_t *data, int width, int height, int stride, const char* key)
{
FILE *fp_bmp = NULL;
char bmp_file[200] = "";
sprintf(bmp_file, "%s.bmp", key);
fp_bmp = fopen(bmp_file, "wb+");
if(!fp_bmp)
{
printf("open bmp error-[%s]\n", strerror(errno));
return ;
}
unsigned char header[54] = {
0x42, 0x4d,
0, 0, 0, 0,
0, 0, 0, 0,
54, 0, 0, 0,
40, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 0,
32, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
long file_size = width* height * 4 + 54;
header[2] = (unsigned char)(file_size &0x000000ff);
header[3] = (file_size >> 8) & 0x000000ff;
header[4] = (file_size >> 16) & 0x000000ff;
header[5] = (file_size >> 24) & 0x000000ff;
header[18] = width & 0x000000ff;
header[19] = (width >> 8) &0x000000ff;
header[20] = (width >> 16) &0x000000ff;
header[21] = (width >> 24) &0x000000ff;
header[22] = -height &0x000000ff;
header[23] = (-height >> 8) &0x000000ff;
header[24] = (-height >> 16) &0x000000ff;
header[25] = (-height >> 24) &0x000000ff;
int i = 0, j = 0;
printf("fp_bmp=[%p]-width-height-stride-[%d][%d][%d]\n", fp_bmp, width, height, stride);
if(fp_bmp)
{
fwrite(header, 1, 54, fp_bmp);
for (i = 0; i < height; i++, data += stride) {
uint8_t *now = data;
/*
for (j = 0; j < width; j++) {
fwrite(&now[3], 1, 1, fp_bmp);
fwrite(&now[2], 1, 1, fp_bmp);
fwrite(&now[1], 1, 1, fp_bmp);
fwrite(&now[0], 1, 1, fp_bmp);
now += 4;
}
*/
fwrite(now, 1, stride, fp_bmp);
}
}
fclose(fp_bmp);
}
void add_watermark(pixman_image_t *dst_image, uint8_t *src_data, int src_width, int src_height, int dst_x, int dst_y, int w, int h)
{
int reverse_watermark = 1;
uint8_t *reverse_data = NULL;
pixman_image_t *src_image = NULL;
int stride = (src_width* 4 + 3) / 4 * 4;
if(reverse_watermark)
{
uint8_t *p = src_data + (src_height - 1) * stride;
reverse_data = malloc(src_width * stride);
for(int i = 0; i < src_height; i++)
{
memcpy(reverse_data + i * stride, p, stride);
p -= stride;
}
src_image = pixman_image_create_bits(PIXMAN_b8g8r8a8, src_width, src_height, (uint32_t *)reverse_data, stride);
}
else
{
src_image = pixman_image_create_bits(PIXMAN_b8g8r8a8, src_width, src_height, (uint32_t *)src_data, stride);
}
pixman_image_composite32(PIXMAN_OP_ADD,
src_image, NULL, dst_image,
0, 0, // src
0, 0, // mask
dst_x, dst_y, // dst
w,
h);
if(reverse_data)
free(reverse_data);
}
int main(int argc, char *argv[])
{
BITMAPFILEHEADER bmph2;
BITMAPINFOHEADER infoh2;
// printf("InfoHead=[%d]\n", sizeof(BITMAPFILEHEADER));
// printf("InfoHead=[%d]\n", sizeof(BITMAPINFOHEADER));
FILE *fp2 = fopen("1234.bmp", "rb");
fseek(fp2, 0, SEEK_END);
int len2 = ftell(fp2);
rewind(fp2);
int file_head_len2 = fread(&bmph2, 1, sizeof(BITMAPFILEHEADER), fp2);
// printf("read file head len=[%d]\n", file_head_len2);
int info_head_len2 = fread(&infoh2, 1, sizeof(BITMAPINFOHEADER), fp2);
// printf("read info head len=[%d]\n", info_head_len2);
int width2 = infoh2.biWidth;
int height2 = infoh2.biHeight;
int data_len2 = len2 - file_head_len2 - info_head_len2;
uint8_t *data2 = malloc(sizeof(uint8_t) *(data_len2));
data_len2 = fread(data2, 1, len2 - 54, fp2);
printf("read dst bitmap width-height--[%d][%d]=[%d]-bitcount=[%d]\n", data_len2, width2, height2, infoh2.biBitCount);
int stride2 = (width2 * infoh2.biBitCount/8+3)/4*4;
int src_w = width2;
int src_h = height2;
int src_stride = (src_w * 4 + 3) / 4 * 4;
pixman_image_t *dst_image = pixman_image_create_bits(PIXMAN_b8g8r8a8, width2, height2, (uint32_t *)data2, stride2);
// cairo_surface_t *surface = cairo_image_surface_create_for_data(data2, CAIRO_FORMAT_ARGB32, width2, height2, stride2);
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, src_w, src_h);
cairo_t *cr = cairo_create(surface);
cairo_set_source_rgba(cr, 1.0, 0.0, 1.0, 1.0);
cairo_select_font_face(cr, "serif", 0, 0);
double font_size = 20;
double vSpacing = 50 + font_size;
cairo_set_font_size(cr, font_size);
// cairo_translate(cr, 40, 40);
double angle = (double) M_PI / 4;
cairo_save(cr);
double pos_x = 200;
double pos_y = 100;
double y0 = pos_y;
while(pos_x < src_w)
{
y0 = pos_y;
// while(y0 < src_h)
{
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo00");
y0 += vSpacing;
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo11");
y0 += vSpacing;
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo22");
y0 += vSpacing;
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo33");
}
pos_x += 200;
}
cairo_restore(cr);
cairo_rotate(cr, angle);
pos_x = 200;
pos_y = 100;
y0 = pos_y;
while(pos_x < src_w)
{
y0 = pos_y;
while(y0 < src_h)
{
// y0 += vSpacing;
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo00");
y0 += vSpacing;
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo11");
y0 += vSpacing;
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo22");
y0 += vSpacing;
cairo_move_to(cr, pos_x, y0);
cairo_show_text(cr, "Luobo33");
}
pos_x += 300;
}
unsigned char *argb = cairo_image_surface_get_data(surface);
bgra_to_bmp(argb, src_w, src_h, src_stride, "key");
add_watermark(dst_image, argb, src_w, src_h, 0, 0, src_w, src_h);
FILE *ffp2 = fopen("out2.bmp", "wb+");
infoh2.biHeight = height2;
fwrite(&bmph2, 1, file_head_len2, ffp2);
fwrite(&infoh2, 1, info_head_len2, ffp2);
fwrite(data2, 1, data_len2, ffp2);
fclose(ffp2);
return 0;
}