使用开源Qrencode库生成二维码并植入指定图片中Dev C++实现

项目中需要在每台4G设备上粘贴标签用于登记设备中SIM卡的uid,考虑使用二维码的形式方便后续管理,标签上显示相关的版本信息及uid,最终结果如下:

使用开源Qrencode库生成二维码并植入指定图片中Dev C++实现_第1张图片

  由于用途很单一而且代码简单,准备采用开源的Qrencode库来生成二维码,Qrencode库直接提供了C代码,使用时包含一个头文件即可,也可以将其编译成静态或动态库,但是考虑代码量,没这个必要。最终代码以控制台程序形式运行,所以决定用DevC++实现,开发速度快,效率高。

下载Qrencode库地址为:https://fukuchi.org/works/qrencode/

使用非常简单,下载后解压得到源文件文件夹,在DevC++中建立控制台项目,将其拷贝到项目文件夹下,然后在项目中包含头文件,相关头文件及用途:

#include   //使用输入输出流 
#include "qrencode.h" //Qrencode库头文件 
#include 	  //动态分配内存用 
#include   //使用位图文件头结构体和位图信息头结构体 
#include 	//访问文件用 
#include 		//获取当前运行路径用 

 然后在项目中将Qrencode库中的.c文件加入到项目中。

生产二维码其实就一句代码:pQRC= QRcode_encodeString(instr, 0, QR_ECLEVEL_H, QR_MODE_8, 1);这个函数直接设置要编码的字符串内容,以及对二维码的设置,如版本(即大小等级1~40)、容错等级、模式等,返回的是一个结构体指针,QRcode,

typedef struct {
         int version;         ///< version of the symbol
         int width;           ///< width of the symbol
         unsigned char *data; ///< symbol data
} QRcode;

它的数据data就是二维码的内容,生成的是BIT数据,也就是说1对应深色块,0对应浅色块,每字节对应8个像素数据

为了生产最终图片,使用PS制作了一个BMP图片模板,当然原因是BMP格式是BitMap原始数据格式,使用简单,模板如下,右侧空着预留植入二维码区域:

程序实现:

一、读入图像模板

程序首先读取模板图片,模板放在当前执行文件夹,使用getcwd();获取当前路径,读取图片分四步,读取文件头,读取位图信息头,读取调色板(由于使用灰度图像),读取图像数据:

FILE *f,*df;//输入文件指针和输出文件指针 
	getcwd(path,128); //获取当前运行路径
	strcat(path,"\\template.bmp"); 
	f=fopen(path, "rb");
    if (f!=NULL)
    {
    	fread(&kFileHeader,sizeof(BITMAPFILEHEADER),1,f);
    	fread(&kInfoHeader,sizeof(BITMAPINFOHEADER),1,f);
    	fread(pPalette,1024,1,f);
	}
	cout<<"BitMap Height="<8)//不是灰度图像,退出 
			exit(-1);
	pBitmap2D=new unsigned char*[kInfoHeader.biHeight];  //分配二维数组 
    if (!(pBitmapData = (unsigned char*)malloc(kInfoHeader.biWidth*kInfoHeader.biHeight)))//分配读BMP位图数据 
    if(pBitmapData==NULL)
	{
        cout<<"fail-1"<

这里使用一个pBitmap2D指针将图像序列数据转换成二维数组,便于后续植入二维码数据。

二、生产二维码

由于生成的二维码为基础像素,因此需要放大一定的倍率适应模板图片:

	pQRC= QRcode_encodeString(instr, 0, QR_ECLEVEL_H, QR_MODE_8, 1);//生成二维码数据 
		//计算二维码放大倍率,根据模板放大到430*430左右,如果不能整除,放大倍数加1,否则后续数组越界 
    	scale=430/pQRC->width==430/pQRC->width*pQRC->width?430/pQRC->width:430/pQRC->width+1;
    	unWidth = pQRC->width*scale;//放大到430*430左右 
		unDataBytes=unWidth*unWidth;
    	// Allocate pixels buffer
    
    	if (!(pGayData = (unsigned char*)malloc(unDataBytes)))//分配二维码放大后图像数据区 
    	{
       	 cout<<"fail-2"<

然后转换BIT数据到灰度字节数据:

  	for ( y = 0; y < pQRC->width; y++)
    	{
       		 pDestData = pGayData + unWidth * y * scale;
        	for ( x = 0; x < pQRC->width; x++)
       		 {
           		 if (*pSourceData & 1)
           		 {
                	for (l = 0; l < scale; l++)
               		{
                  	  for (n = 0; n < scale; n++)
	                    {
                       	  //以下三行是设置三基色,三基色都设置为0x00,则生成的二维码图片就是黑色的了,要什么颜色自己调整
                       	 *(pDestData + n + unWidth * l) = 0x00;            
                    	}
                	}
            	}
            	pDestData += scale;
            	pSourceData++;
        	}
    	}

三、合成二维码数据到模板图像

由于数据已经准备好,而且有了二维数组,这个步骤简单:

   	//合成二维码数据到图像数据中,从第25行第600列开始 
    	for ( y = 0; y < unWidth; y++)
    	{
        	for ( x = 0; x < unWidth; x++)	
			{
				pBitmap2D[y+25][x+600]=*(pGayData++);
			}
		}

四、写最终数据到uid命名的文件

		strcpy(filename,".\\");
		strcat(filename,instr);
		strcat(filename,".bmp");
 		df=fopen(filename, "wb");
		if (df!=NULL)
    	{
    		fwrite(&kFileHeader,sizeof(BITMAPFILEHEADER),1,df);
    		fwrite(&kInfoHeader,sizeof(BITMAPINFOHEADER),1,df);
    		fwrite(pPalette,1024,1,df);
    	for(y=kInfoHeader.biHeight;y>0;y--)
    		{
    			fwrite(pBitmap2D[y-1],kInfoHeader.biWidth,1,df);
    		}
 		}
		else
			cout<<"fail"<

最终搞一个循环,就可以连续生成图像了。

 全部代码及图像模板下载地址:https://download.csdn.net/download/weixin_48341920/87062873?spm=1001.2014.3001.5503

你可能感兴趣的:(图形图像,c++,开发语言,算法)