cairo和pixman库给bmp图片加文字水印

两个步骤

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值