当前位置: 首页 > 工具软件 > Zint > 使用案例 >

Zint生成二维码及png操作

景俊语
2023-12-01
  1. 环境搭建点击查看
  2. 编译demo
  • ubuntu下使用编译

连接动态库编译
gcc -o demo demo.c zint_code.c -lzint
连接静态库编译
gcc -o demo demo.c zint_code.c -static -L. -lzint -lpng16 -lz -lm

  • arm-linux下使用编译

a、把交叉编译链中的libz.a、libm.a拷贝到demo中
b、执行编译命令
arm-oe-linux-gnueabi-gcc -o demo demo.c zint_code.c -static -L. -lzint -lz -lm

  1. Zint生成二维码demo
    demo.c
#include <stdio.h>
#include "zint_code.h"

int main(int argc, char *argv[]){
    int ZintLibRet             = 0; //ret code from zint lib
    ZINT_RET_CODE ZintRet     = 0; //ret code from zint_code api
    char QrcodeData[]         = "https://translate.google.cn/";
    char QrcodeFile[]         = "demo.png"; // Must end in .png, .eps or .svg. //zint lib ask !
    
    //test with inputing qrcode_file name
    ZintRet = Zint_Create_QrCode((uint8_t*)QrcodeData, 0, QrcodeFile, &ZintLibRet);
    if(ZINT_OK != ZintRet){
        Debuging("Create qrcode err, ZintRet = %d, ZintLibRet = %d\n", ZintRet, ZintLibRet);
    }else{
        Debuging("Create qrcode OK ! View qrcode file : %s in cur path. ZintRet = %d, ZintLibRet = %d\n", QrcodeFile, ZintRet, ZintLibRet);
    }
    
    return 0;
}

zint_code.c

#include <string.h>
#include <stdio.h>
#include "zint.h"
#include "zint_code.h"

/****************************************************************************
Descpribe: Create Qrcode API with C Code by calling zint lib.
Input    : pQrCodeData, the qrcode data buf
           QrcodeLen, the len of qrcode data, but it can be 0
           pQrCodeFile, the output file name of qrcode, it can be NULL           
Output   : pZintRet, to store the ret code from linzint. 
Return   : 0 is ok, and other values are fail. See the meanings in enum ZINT_RET_CODE
Notes    : pQrCodeFile, Must end in .png, .eps or .svg. when isn,t NULL string.
****************************************************************************/
ZINT_RET_CODE Zint_Create_QrCode(uint8_t *pQrCodeData, int QrcodeLen, char *pQrCodeFile, int *pZintRet){
    struct zint_symbol *pMySymbol     = NULL;
    int RetCode                     = 0;    
    
    if(!pQrCodeData){ //check input pointer
        return ZINT_ERR_INV_DATA;
    }

    if(QrcodeLen == 0){
        QrcodeLen = strlen((char *)pQrCodeData);
    }
    if(QrcodeLen > QRCODE_MAX_LEN){ //len is too long
        return ZINT_ERR_TOO_LONG;
    }

    if(0 == ZBarcode_ValidID(BARCODE_QRCODE)){
        return ZINT_ERR_INV_CODE_ID;
    }
    
    pMySymbol = ZBarcode_Create();
    if(pMySymbol == NULL){
        return ZINT_ERR_MEMORY;
    }

    if(pQrCodeFile){ //when it's NULL, outfile will be "out.png"
        if(strstr(pQrCodeFile, "png") || (strstr(pQrCodeFile, "eps")) || (strstr(pQrCodeFile, "svg"))){
            strcpy(pMySymbol->outfile, pQrCodeFile);
        }else{
            ZBarcode_Clear(pMySymbol);
            ZBarcode_Delete(pMySymbol); //release memory in zint lib
            return ZINT_ERR_FILE_NAME;
        }
    }
    pMySymbol->symbology     = BARCODE_QRCODE;  	
    pMySymbol->option_1      = 2; //ECC Level.It can be large when ECC Level is larger.(value:1-4)  
    pMySymbol->scale         = 1.2; //contorl qrcode file size, default is 1, used to be 4   
    pMySymbol->border_width = 1; //set white space width around your qrcode and 0 is for nothing 
    
	#if 0 //生成png图片
    RetCode = ZBarcode_Encode_and_Print(pMySymbol, pQrCodeData, QrcodeLen, 0);  
	#else //获取bmp的rgb值
	ZBarcode_Encode_and_Buffer(pMySymbol, pQrCodeData, QrcodeLen, 0);
	unsigned char r, g, b;
    int i = 0;
    for (int row = 0; row < pMySymbol->bitmap_height; ++row) {
        for (int col = 0; col < pMySymbol->bitmap_width; ++col) {
            r = pMySymbol->bitmap[i];
            g = pMySymbol->bitmap[i + 1];
            b = pMySymbol->bitmap[i + 2];

            i += 3;

            if (r == 0 && g == 0 & b == 0){
                printf("■");
            } else {
                printf("□");
            }
        }

        printf(" r:%d, g:%d, b:%d\n", r, g, b);
    }
	#endif
    ZBarcode_Clear(pMySymbol);
    ZBarcode_Delete(pMySymbol); //release memory in zint lib

    if(pZintRet){
        *pZintRet = RetCode; //save ret code from zint lib
    }
    
    return ((0 == RetCode) ? (ZINT_OK) : (ZINT_ERR_LIB_RET));
}

zint_code.h

#ifndef __ZINT_CODE__
#define __ZINT_CODE__

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdint.h>

#define QRCODE_MAX_LEN        500 //max string len for creating qrcode

typedef enum {
    ZINT_OK                 = 0,
    ZINT_ERR_INV_DATA         = -1, //input invalid data
    ZINT_ERR_TOO_LONG         = -2, //len for input data is too long    
    ZINT_ERR_INV_CODE_ID     = -3,//the code type is not supported by zint
    ZINT_ERR_MEMORY         = -4, //malloc memory error in zint lib
    ZINT_ERR_FILE_NAME        = -5, //qrcode file isn'y end in .png, .eps or .svg.
    ZINT_ERR_LIB_RET         = -6, //zint lib ret error, real ret code should be zint api ret code
}ZINT_RET_CODE;

/****************************************************************************
Descpribe: Create Qrcode API with C Code by calling zint lib.
Input    : pQrCodeData, the qrcode data buf
           QrcodeLen, the len of qrcode data, but it can be 0
           pQrCodeFile, the output file name of qrcode, it can be NULL           
Output   : pZintRet, to store the ret code from linzint. 
Return   : 0 is ok, and other values are fail. See the meanings in enum ZINT_RET_CODE
Notes    : pQrCodeFile, Must end in .png, .eps or .svg. when isn,t NULL string.
****************************************************************************/
ZINT_RET_CODE Zint_Create_QrCode(uint8_t *pQrCodeData, int QrcodeLen, char *pQrCodeFile, int *pZintRet);

#define Debuging(fmt, arg...)       printf("[%20s, %4d] "fmt, __FILE__, __LINE__, ##arg)

#ifdef __cplusplus
}
#endif

#endif /* __ZINT_CODE__ */
  1. 读取png原始数据操作
    read-png-data.c
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#include<math.h>
#define SAFE_FREE(x) {free(x);x=NULL;}
#define BUFFER_SIZE 1024*1024
int main(){
	unsigned int offset = 0;
	FILE* sFile = fopen("1.png", "rb");
	FILE* dFile = fopen("d.txt", "w");
	FILE* txtFile = fopen("t.txt", "w");
	unsigned char* buf=(unsigned char*)malloc(BUFFER_SIZE);
	size_t nSize = fread(buf,1,BUFFER_SIZE, sFile);
	
	unsigned char png[]={0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa};
	for(;offset<8;offset++){
		if(buf[offset]!=png[offset]){
			printf("no png\n");
			return 0;
		}
	}
	while(offset<nSize){
		unsigned int dataLen = 0;
		for(unsigned int i=offset+4;offset<i;offset++){
			dataLen+=buf[offset]*pow((double)256, (int)(i-offset-1));
		}
		if(buf[offset] == 'I' && buf[offset+1]=='D' &&buf[offset+2]=='A' &&buf[offset+3]=='T'){
			int count = 0;
			for(int i=0;i<dataLen;i++){
				fprintf(txtFile,"0x%x ",buf[offset+4+i]);
				count++;
			}
			printf("count:%d\n",count);
			fprintf(txtFile,"\n\n\n\n");
		}
		for(char i=0;i<4;i++){
			fprintf(dFile,"%c",buf[offset++]);
		}
		fprintf(dFile,"\n");
		offset+=(dataLen+4);
	}
	fclose(sFile);
	fclose(dFile);
	fclose(txtFile);
	SAFE_FREE(buf);
}

  1. png的读写操作(获取rgb数据)
    png-read-write.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <png.h>
 
 
#define PNG_BYTES_TO_CHECK	8
#define HAVE_ALPHA			1
#define NOT_HAVE_ALPHA		0
 
typedef struct _pic_data pic_data;
struct _pic_data {
	int width, height; 	//长宽
	int bit_depth; 	   	//位深度
	int alpha_flag;		//是否有透明通道
	unsigned char *rgba;//实际rgb数据
};
 
int check_is_png(FILE **fp, const char *filename) //检查是否png文件
{
	char checkheader[PNG_BYTES_TO_CHECK]; //查询是否png头
	*fp = fopen(filename, "rb");
	if (*fp == NULL) {
		printf("open failed ...1\n");
		return -1;
	}
	if (fread(checkheader, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) //读取png文件长度错误直接退出
		return 0;
	return png_sig_cmp(checkheader, 0, PNG_BYTES_TO_CHECK); //0正确, 非0错误
}
 
int decode_png(const char *filename, pic_data *out) //取出png文件中的rgb数据
{
	png_structp png_ptr; //png文件句柄
	png_infop	info_ptr;//png图像信息句柄
	int ret;
	FILE *fp;
	if (check_is_png(&fp, filename) != 0) {
		printf("file is not png ...\n");
		return -1;
	}
	printf("launcher[%s] ...\n", PNG_LIBPNG_VER_STRING); //打印当前libpng版本号
 
	//1: 初始化libpng的数据结构 :png_ptr, info_ptr
	png_ptr  = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 
	info_ptr = png_create_info_struct(png_ptr);
 
	//2: 设置错误的返回点
	setjmp(png_jmpbuf(png_ptr));
	rewind(fp); //等价fseek(fp, 0, SEEK_SET);
 
	//3: 把png结构体和文件流io进行绑定 
	png_init_io(png_ptr, fp);
	//4:读取png文件信息以及强转转换成RGBA:8888数据格式
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0); //读取文件信息
	int channels, color_type; 
	channels 	= png_get_channels(png_ptr, info_ptr); //通道数量
	color_type 	= png_get_color_type(png_ptr, info_ptr);//颜色类型
	out->bit_depth = png_get_bit_depth(png_ptr, info_ptr);//位深度	
	out->width 	 = png_get_image_width(png_ptr, info_ptr);//宽
	out->height  = png_get_image_height(png_ptr, info_ptr);//高
	
	//if(color_type == PNG_COLOR_TYPE_PALETTE)
	//	png_set_palette_to_rgb(png_ptr);//要求转换索引颜色到RGB
	//if(color_type == PNG_COLOR_TYPE_GRAY && out->bit_depth < 8)
	//	png_set_expand_gray_1_2_4_to_8(png_ptr);//要求位深度强制8bit
	//if(out->bit_depth == 16)
	//	png_set_strip_16(png_ptr);//要求位深度强制8bit
	//if(png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS))
	//	png_set_tRNS_to_alpha(png_ptr);
	//if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
	//	png_set_gray_to_rgb(png_ptr);//灰度必须转换成RG
	printf("channels = %d color_type = %d bit_depth = %d width = %d height = %d ...\n",
			channels, color_type, out->bit_depth, out->width, out->height);
 
	int i, j, k;
	int size, pos = 0;
	int temp;
	
	//5: 读取实际的rgb数据
	png_bytepp row_pointers; //实际存储rgb数据的buf
	row_pointers = png_get_rows(png_ptr, info_ptr); //也可以分别每一行获取png_get_rowbytes();
	size = out->width * out->height; //申请内存先计算空间
	if (channels == 4 || color_type == PNG_COLOR_TYPE_RGB_ALPHA) { //判断是24位还是32位
		out->alpha_flag = HAVE_ALPHA; //记录是否有透明通道
		size *= (sizeof(unsigned char) * 4); //size = out->width * out->height * channel
		out->rgba = (png_bytep)malloc(size);
		if (NULL == out->rgba) {
			printf("malloc rgba faile ...\n");
			png_destroy_read_struct(&png_ptr, &info_ptr, 0);
			fclose(fp);
			return -1;
		}
		//从row_pointers里读出实际的rgb数据出来
		temp = channels - 1;
		for (i = 0; i < out->height; i++) 
			for (j = 0; j < out->width * 4; j += 4) 
				for (k = temp; k >= 0; k--)
					out->rgba[pos++] = row_pointers[i][j + k];
	} else if (channels == 3 || color_type == PNG_COLOR_TYPE_RGB) { //判断颜色深度是24位还是32位
		out->alpha_flag = NOT_HAVE_ALPHA;
		size *= (sizeof(unsigned char) * 3);
		out->rgba = (png_bytep)malloc(size);
		if (NULL == out->rgba) {
			printf("malloc rgba faile ...\n");
			png_destroy_read_struct(&png_ptr, &info_ptr, 0);
			fclose(fp);
			return -1;
		}
		//从row_pointers里读出实际的rgb数据
		temp = (3 * out->width);
		for (i = 0; i < out->height; i ++) {
			for (j = 0; j < temp; j += 3) {
				out->rgba[pos++] = row_pointers[i][j+2];
				out->rgba[pos++] = row_pointers[i][j+1];
				out->rgba[pos++] = row_pointers[i][j+0];
			}
		}
	} else return -1; 
	//6:销毁内存
	png_destroy_read_struct(&png_ptr, &info_ptr, 0);
	fclose(fp);
	//此时, 我们的out->rgba里面已经存储有实际的rgb数据了
	//处理完成以后free(out->rgba)
	return 0;
}
 
int RotationRight90(unsigned char * src, int srcW, int srcH, int channel) //顺时针旋转90度
{
	unsigned char * tempSrc = NULL; //临时的buf用来记录原始的图像(未旋转之前的图像)
	int mSize = srcW * srcH * sizeof(char) * channel;
	int i = 0;
	int j = 0;
	int k = 0;
	int l = 3;
	int desW = 0;
	int desH = 0;
 
	desW = srcH;
	desH = srcW;
 
	tempSrc = (unsigned char *)malloc(sizeof(char) * srcW * srcH * channel);
	memcpy(tempSrc, src, mSize); //拷贝原始图像至tempbuf
	for(i = 0; i < desH; i ++)
	{
		for(j = 0; j < desW; j ++)
		{
			for(k = 0; k < channel; k ++)
			{
				src[(i * desW + j) * channel + k] = tempSrc[((srcH - 1 - j) * srcW + i) * channel + k]; //替换像素
			}
		}
	}
	free(tempSrc);
	return 0;
}
 
int write_png_file(const char *filename , pic_data *out) //生成一个新的png图像
{
	png_structp png_ptr;
	png_infop 	info_ptr;
	png_byte color_type;
	png_bytep * row_pointers;
	FILE *fp = fopen(filename, "wb");
	if (NULL == fp) {
		printf("open failed ...2\n");
		return -1;
	}
	//1: 初始化libpng结构体  
	png_ptr	= png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (!png_ptr) {
		printf("png_create_write_struct failed ...\n");
		return -1;
	}
	//2: 初始化png_infop结构体 , 
	//此结构体包含了图像的各种信息如尺寸,像素位深, 颜色类型等等
	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		printf("png_create_info_struct failed ...\n");
		return -1;
	}
	//3: 设置错误返回点
	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("error during init_io ...\n");
		return -1;
	}
	//4:绑定文件IO到Png结构体
	png_init_io(png_ptr, fp);
	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("error during init_io ...\n");
		return -1;
	}
	if (out->alpha_flag == HAVE_ALPHA) color_type = PNG_COLOR_TYPE_RGB_ALPHA;
	else color_type = PNG_COLOR_TYPE_RGB;
	//5:设置以及写入头部信息到Png文件
	png_set_IHDR(png_ptr, info_ptr, out->width, out->height, out->bit_depth,
	color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
	png_write_info(png_ptr, info_ptr);
	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("error during init_io ...\n");
		return -1;
	}
	int channels, temp;
	int i, j, pos = 0;
	if (out->alpha_flag == HAVE_ALPHA) {
		channels = 4;
		temp = (4 * out->width);
		printf("have alpha ...\n");
	} else {
		channels = 3;
		temp = (3 * out->width);
		printf("not have alpha ...\n");
	}
	// 顺时针旋转90度 , 旋转完了一定要把width 和height调换 不然得到的图像是花的  旋转三次就是逆时针旋转一次
	//RotationRight90(out->rgba, out->width, out->height, channels);
	//RotationRight90(out->rgba, out->height, out->width, channels);
	//RotationRight90(out->rgba, out->width, out->height, channels);
	row_pointers = (png_bytep*)malloc(out->height * sizeof(png_bytep));
	for (i = 0; i < out->height; i++) {
		row_pointers[i] = (png_bytep)malloc(temp* sizeof(unsigned char));
		for (j = 0; j < temp; j += channels) {
			if (channels == 4) {
				row_pointers[i][j+3] = out->rgba[pos++];
				row_pointers[i][j+2] = out->rgba[pos++];
				row_pointers[i][j+1] = out->rgba[pos++];
				row_pointers[i][j+0] = out->rgba[pos++];
			} else {
				row_pointers[i][j+2] = out->rgba[pos++];
				row_pointers[i][j+1] = out->rgba[pos++];
				row_pointers[i][j+0] = out->rgba[pos++];
			}
		}
	}
	//6: 写入rgb数据到Png文件
	png_write_image(png_ptr, (png_bytepp)row_pointers);
	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("error during init_io ...\n");
		return -1;
	}
	//7: 写入尾部信息
	png_write_end(png_ptr, NULL);
	//8:释放内存 ,销毁png结构体
	for (i = 0; i < out->height; i ++)
		free(row_pointers[i]);
	free(row_pointers);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	fclose(fp);
	return 0;
}
 
int main(int argc, char **argv)
{
	pic_data out;
	decode_png("1.png", &out);
	write_png_file("2.png", &out);
	free(out.rgba);
	return 0;
}

  1. png的rgb转为565
    rgb-to-565.c
#include <stdio.h>
int main(int argc, char *argv[])
{
	unsigned short R=0xFF;
	unsigned short G=0xFF;
	unsigned short B=0xFF;
	unsigned short buf = 0;
#if 0
	//swap != 0 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit  BUT the 2  color bytes are swapped*/
	R = (R & 0XF8) << 8;
	buf = buf | R;
	printf("buf=%#x\n",buf);
	G = (G & 0X7E) << 4;
	buf = buf | G;
	printf("buf=%#x\n",buf);
	B = (B & 0X1F);
	buf = buf | B;
	printf("buf=%#x\n",buf);
#else	
	//swap /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/
	unsigned short T = 0;
	R = (R & 0XF8) << 8;
	buf = buf | R;
	printf("buf=%#x\n",buf);

	G = (G & 0X7E) << 4;
	buf = buf | G;
	printf("buf=%#x\n",buf);

	B = (B & 0X1F);
	buf = buf | B;
	
	T = buf >> 8;
	buf = (buf << 8) | T;
	printf("buf=%#x\n",buf);
#endif
	return 0;
}

 类似资料: