libqrencode生成二维码并保存成bmp图片打开失败问题解决方案

1 篇文章 0 订阅

c++ 使用qrencode库生成二维码的方法如下:

#include "qrencode.h"
#define QT_OUT_FILE     "/root/Application/QRBMP/qrpay.bmp"
// Prescaler (number of pixels in bmp file for each QRCode pixel, on each dimension)
#define OUT_FILE_PIXEL_PRESCALER    4       
// Color of bmp pixels  
#define PIXEL_COLOR_R               0xff        
#define PIXEL_COLOR_G               0
#define PIXEL_COLOR_B               0
#define BI_RGB                      0L

typedef struct
{
    unsigned short bfType;
    unsigned long  bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned long bfOffBits;
} BITMAPFILEHEADER;

typedef struct
{
    unsigned long biSize;
    signed long biWidth;
    signed long biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;
    unsigned long biCompression;
    unsigned long biSizeImage;
    signed long biXPelsPerMeter;
    signed long biYPelsPerMeter;
    unsigned long biClrUsed;
    unsigned long biClrImportant;
} BITMAPINFOHEADER;


int Save_QEImage(char* szSourceSring)
{
    unsigned int unWidth, x, y, l, n, unWidthAdjusted, unDataBytes;
    unsigned char* pRGBData, *pSourceData, *pDestData;
    QRcode* pQRC;
    FILE* f;

    // Compute QRCode
    if  (pQRC = QRcode_encodeString(szSourceSring, 0, QR_ECLEVEL_H, QR_MODE_8, 1))
    {
        //矩阵的维数
        unWidth = pQRC->width;
        unWidthAdjusted = unWidth * OUT_FILE_PIXEL_PRESCALER * 3;
        //每一个维度占的像素的个数(8),每个像素3个字节
        if (unWidthAdjusted % 4)
        {
            unWidthAdjusted = (unWidthAdjusted / 4 + 1) * 4;
        }
        unDataBytes = unWidthAdjusted * unWidth * OUT_FILE_PIXEL_PRESCALER;

        // Allocate pixels buffer
        if (!(pRGBData = (unsigned char*)malloc(unDataBytes)))
        {
            printf("Out of memory");
            return 1;
        }

        // Preset to white
        memset(pRGBData, 0xff, unDataBytes);

        // Prepare bmp headers
        BITMAPFILEHEADER kFileHeader;
        kFileHeader.bfType = 0x4d42;  // "BM"
        kFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + unDataBytes;
        kFileHeader.bfReserved1 = 0;
        kFileHeader.bfReserved2 = 0;
        kFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

        BITMAPINFOHEADER kInfoHeader;
        kInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
        kInfoHeader.biWidth = unWidth * OUT_FILE_PIXEL_PRESCALER;
        kInfoHeader.biHeight = -((int)unWidth * OUT_FILE_PIXEL_PRESCALER);
        kInfoHeader.biPlanes = 1;
        kInfoHeader.biBitCount = 24;
        kInfoHeader.biCompression = BI_RGB;
        kInfoHeader.biSizeImage = 0;
        kInfoHeader.biXPelsPerMeter = 0;
        kInfoHeader.biYPelsPerMeter = 0;
        kInfoHeader.biClrUsed = 0;
        kInfoHeader.biClrImportant = 0;

        // Convert QrCode bits to bmp pixels
        pSourceData = pQRC->data;
        for (y = 0; y < unWidth; y++)
        {
            pDestData = pRGBData + unWidthAdjusted * y * OUT_FILE_PIXEL_PRESCALER;
            for (x = 0; x < unWidth; x++)
            {
                if (*pSourceData & 1)
                {
                    for (l = 0; l < OUT_FILE_PIXEL_PRESCALER; l++)
                    {
                        for (n = 0; n < OUT_FILE_PIXEL_PRESCALER; n++)
                        {
                            *(pDestData + n * 3 + unWidthAdjusted * l) = PIXEL_COLOR_B;
                            *(pDestData + 1 + n * 3 + unWidthAdjusted * l) = PIXEL_COLOR_G;
                            *(pDestData + 2 + n * 3 + unWidthAdjusted * l) = PIXEL_COLOR_R;
                        }
                    }
                }
                pDestData += 3 * OUT_FILE_PIXEL_PRESCALER;
                pSourceData++;
            }
        }

        // Output the bmp file
        //f = fopen(QT_OUT_FILE,"wb");
        f = fopen(QT_OUT_FILE,"ab++");
        if (f != NULL)
        {
            fwrite(&kFileHeader, sizeof(BITMAPFILEHEADER), 1, f);
            fwrite(&kInfoHeader, sizeof(BITMAPINFOHEADER), 1, f);
            fwrite(pRGBData, sizeof(unsigned char), unDataBytes, f);

            fclose(f);
        }
        else
        {
            printf("Unable to open file\n");
            return 1;
        }

        // Free data
        free(pRGBData);
        QRcode_free(pQRC);
    }
    else
    {
        printf("NULL returned");
        return 1;
    }

    return 0;
}

最开始BITMAPFILEHEADER和BITMAPINFOHEADER是引用的window.h里的,二维码生成的图片是可以打开的,由于Android和ios没有这个window库所以手动定义了,然后生成的二维码就打不开了,找了很久的问题,才发现一篇类似博客的细节需要指定BITMAPFILEHEADER和BITMAPINFOHEADER2字节对齐,修改后如下:

#include "qrencode.h"
#define QT_OUT_FILE     "/root/Application/QRBMP/qrpay.bmp"
// Prescaler (number of pixels in bmp file for each QRCode pixel, on each dimension)
#define OUT_FILE_PIXEL_PRESCALER    4       
// Color of bmp pixels  
#define PIXEL_COLOR_R               0xff        
#define PIXEL_COLOR_G               0
#define PIXEL_COLOR_B               0
#define BI_RGB                      0L


#pragma pack(push, 2) //2字节对齐,不然会出问题
typedef struct
{
    unsigned short bfType;
    unsigned long  bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned long bfOffBits;
} BITMAPFILEHEADER;

typedef struct
{
    unsigned long biSize;
    signed long biWidth;
    signed long biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;
    unsigned long biCompression;
    unsigned long biSizeImage;
    signed long biXPelsPerMeter;
    signed long biYPelsPerMeter;
    unsigned long biClrUsed;
    unsigned long biClrImportant;
} BITMAPINFOHEADER;
#pragma pack(pop)


int Save_QEImage(char* szSourceSring)
{
    unsigned int unWidth, x, y, l, n, unWidthAdjusted, unDataBytes;
    unsigned char* pRGBData, *pSourceData, *pDestData;
    QRcode* pQRC;
    FILE* f;

    // Compute QRCode
    if  (pQRC = QRcode_encodeString(szSourceSring, 0, QR_ECLEVEL_H, QR_MODE_8, 1))
    {
        //矩阵的维数
        unWidth = pQRC->width;
        unWidthAdjusted = unWidth * OUT_FILE_PIXEL_PRESCALER * 3;
        //每一个维度占的像素的个数(8),每个像素3个字节
        if (unWidthAdjusted % 4)
        {
            unWidthAdjusted = (unWidthAdjusted / 4 + 1) * 4;
        }
        unDataBytes = unWidthAdjusted * unWidth * OUT_FILE_PIXEL_PRESCALER;

        // Allocate pixels buffer
        if (!(pRGBData = (unsigned char*)malloc(unDataBytes)))
        {
            printf("Out of memory");
            return 1;
        }

        // Preset to white
        memset(pRGBData, 0xff, unDataBytes);

        // Prepare bmp headers
        BITMAPFILEHEADER kFileHeader;
        kFileHeader.bfType = 0x4d42;  // "BM"
        kFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + unDataBytes;
        kFileHeader.bfReserved1 = 0;
        kFileHeader.bfReserved2 = 0;
        kFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

        BITMAPINFOHEADER kInfoHeader;
        kInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
        kInfoHeader.biWidth = unWidth * OUT_FILE_PIXEL_PRESCALER;
        kInfoHeader.biHeight = -((int)unWidth * OUT_FILE_PIXEL_PRESCALER);
        kInfoHeader.biPlanes = 1;
        kInfoHeader.biBitCount = 24;
        kInfoHeader.biCompression = BI_RGB;
        kInfoHeader.biSizeImage = 0;
        kInfoHeader.biXPelsPerMeter = 0;
        kInfoHeader.biYPelsPerMeter = 0;
        kInfoHeader.biClrUsed = 0;
        kInfoHeader.biClrImportant = 0;

        // Convert QrCode bits to bmp pixels
        pSourceData = pQRC->data;
        for (y = 0; y < unWidth; y++)
        {
            pDestData = pRGBData + unWidthAdjusted * y * OUT_FILE_PIXEL_PRESCALER;
            for (x = 0; x < unWidth; x++)
            {
                if (*pSourceData & 1)
                {
                    for (l = 0; l < OUT_FILE_PIXEL_PRESCALER; l++)
                    {
                        for (n = 0; n < OUT_FILE_PIXEL_PRESCALER; n++)
                        {
                            *(pDestData + n * 3 + unWidthAdjusted * l) = PIXEL_COLOR_B;
                            *(pDestData + 1 + n * 3 + unWidthAdjusted * l) = PIXEL_COLOR_G;
                            *(pDestData + 2 + n * 3 + unWidthAdjusted * l) = PIXEL_COLOR_R;
                        }
                    }
                }
                pDestData += 3 * OUT_FILE_PIXEL_PRESCALER;
                pSourceData++;
            }
        }

        // Output the bmp file
        //f = fopen(QT_OUT_FILE,"wb");
        f = fopen(QT_OUT_FILE,"ab++");
        if (f != NULL)
        {
            fwrite(&kFileHeader, sizeof(BITMAPFILEHEADER), 1, f);
            fwrite(&kInfoHeader, sizeof(BITMAPINFOHEADER), 1, f);
            fwrite(pRGBData, sizeof(unsigned char), unDataBytes, f);

            fclose(f);
        }
        else
        {
            printf("Unable to open file\n");
            return 1;
        }

        // Free data
        free(pRGBData);
        QRcode_free(pQRC);
    }
    else
    {
        printf("NULL returned");
        return 1;
    }

    return 0;
}

感谢:https://blog.csdn.net/qq_22790049/article/details/78684827

libqrencode是一个C语言编写的库,用于生二维条形码。生的二维码可以通过手机的CCD摄像机轻松扫描出来。该库具有很强的鲁棒性,可以生容量多达7000个数字或4000个字符的二维码。\[1\] 要使用libqrencode生成二维码,你需要以下几个步骤: 1. 下载稳定版本的libqrencode源代码包,可以从http://fukuchi.org/works/qrencode/下载。 2. 解压下载的源代码包,将其中的.h和.c文件拷贝到一个文件夹中,例如命名为libqrencode。 3. 创建一个工程,选择适合你的平台(如OSX或iOS)的应用程序模板。 4. 将libqrencode文件夹中的源代码添加到你的工程中。 5. 根据你的需求,调用libqrencode提供的函数来生成二维码。 这样,你就可以使用libqrencode库来生成二维码了。请注意,具体的实现细节可能因你的开发环境和需求而有所不同。\[2\]\[3\] #### 引用[.reference_title] - *1* *3* [基于libqrencode的二维码生](https://blog.csdn.net/SkyNullCode/article/details/49934699)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [使用libqrencode生成二维码,支持telphone,短信,url等](https://blog.csdn.net/u013295518/article/details/89680310)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值