libqrencode在生成编码后,如何生成二维码图片。可以通过libpng来生成二维码图片文件。但在在网络通信中,先生成二维码图片文件,再读取文件数据,发送出去,这是一种可行的方法。
但是有没有一种生成二维码图片数据是存放在内存中,而不是以文件形式呢?如果有,这样就不需要生成二维码图片文件后,再次读取文件数据,就可以省略这一步了。
在libpng库 中是可以自己定义写操作的。主要是通过函数png_set_write_fn,关键是需要自己定义写处理函数及相关的数据结构
1、定义数据结构
#define MAX_DATA_LEN 1024
typedef struct BinData
{
char data[MAX_DATA_LEN];
int len;
}BinData;
2、定义写处理函数
static void write_function(png_structp pp, png_bytep data, png_size_t size)
{
BinData *p = (BinData*)png_get_io_ptr(pp);
char *p_data = p->data + p->len;
memcpy(p_data, data, size);
p->len += size;
}
3、测试代码如下(其它还是使用libqrencode中的qrenc.c,只是修改writepng函数)
static int writePNG(QRcode *qrcode, BinData* bindatap) { png_structp png_ptr; png_infop info_ptr; png_colorp palette; png_byte alpha_values[2]; unsigned char *row, *p, *q; int x, y, xx, yy, bit; int realwidth; realwidth = (qrcode->width + margin * 2) * size; row = (unsigned char *)malloc((realwidth + 7) / 8); if(row == NULL) { fprintf(stderr, "Failed to allocate memory.\n"); exit(EXIT_FAILURE); } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(png_ptr == NULL) { fprintf(stderr, "Failed to initialize PNG writer.\n"); exit(EXIT_FAILURE); } info_ptr = png_create_info_struct(png_ptr); if(info_ptr == NULL) { fprintf(stderr, "Failed to initialize PNG write.\n"); exit(EXIT_FAILURE); } if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fprintf(stderr, "Failed to write PNG image.\n"); exit(EXIT_FAILURE); } palette = (png_colorp) malloc(sizeof(png_color) * 2); if(palette == NULL) { fprintf(stderr, "Failed to allocate memory.\n"); exit(EXIT_FAILURE); } palette[0].red = fg_color[0]; palette[0].green = fg_color[1]; palette[0].blue = fg_color[2]; palette[1].red = bg_color[0]; palette[1].green = bg_color[1]; palette[1].blue = bg_color[2]; alpha_values[0] = fg_color[3]; alpha_values[1] = bg_color[3]; png_set_PLTE(png_ptr, info_ptr, palette, 2); png_set_tRNS(png_ptr, info_ptr, alpha_values, 2, NULL); png_set_write_fn(png_ptr, bindatap, write_function, NULL); png_set_IHDR(png_ptr, info_ptr, realwidth, realwidth, 1, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_pHYs(png_ptr, info_ptr, dpi * INCHES_PER_METER, dpi * INCHES_PER_METER, PNG_RESOLUTION_METER); png_write_info(png_ptr, info_ptr); /* top margin */ memset(row, 0xff, (realwidth + 7) / 8); for(y=0; y<margin * size; y++) { png_write_row(png_ptr, row); } /* data */ p = qrcode->data; for(y=0; y<qrcode->width; y++) { bit = 7; memset(row, 0xff, (realwidth + 7) / 8); q = row; q += margin * size / 8; bit = 7 - (margin * size % 8); for(x=0; x<qrcode->width; x++) { for(xx=0; xx<size; xx++) { *q ^= (*p & 1) << bit; bit--; if(bit < 0) { q++; bit = 7; } } p++; } for(yy=0; yy<size; yy++) { png_write_row(png_ptr, row); } } /* bottom margin */ memset(row, 0xff, (realwidth + 7) / 8); for(y=0; y<margin * size; y++) { png_write_row(png_ptr, row); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); free(row); free(palette); return 0; }