...

воскресенье, 9 июня 2013 г.

Создание QR-кодов на C/C++

image

Это простой пример использования библиотеки libqrencode от FUKUCHI Kentaro для генерации bmp-файла с QR-кодом для какого-то текста. В интернете полно ссылок на эту библиотеку, но ни одного примера ее использования. libqrencode поддерживает QR Code model 2, описанный в JIS (Japanese Industrial Standards) X0510:2004 или ISO/IEC 18004. В настоящее время не поддерживаются режимы ECI и FNC1 QR Code model 1.


Предисловие




QR-код — это двухмерный код, который может быть считан различными устройствами. Сегодня, практически в каждом смартфоне есть QRCode reader. Этот формат поддерживает разные типы данных: url, контакты и т.д. В примере этой статьи закодирован url, который приведет вас в статью в википедии о QR-кодах. Наиболее используемая библиотека для генерации кодов — libqrencode, но простых примеров ее использования, особенно на С/С++ в сети мало нет. Документация представляет собой просто комментарии в исходном коде. Было написано простое приложение, которое преобразует url в QR-код и сохраняет его в обычном bmp-файле.

Использование кода




Для использования кода, приведенного выше, необходимо скачать библиотеку libqrencode, ссылка на которую есть в самом начале поста и поместить ее исходники (можно в отдельной папке) в папку с проектом. Итак, простое Win32-приложения для конвертации url в QR-код, которое можно использовать в своих проектах:

#include <stdio.h>
#include <tchar.h>
#include <string.h>
#include <errno.h>
#include <conio.h>
#include <ctype.h>
#include <stddef.h>
#include <stdlib.h>
#include <wchar.h>
#include "qrencode.h" //by libqrencode

#define QRCODE_TEXT "http://ru.wikipedia.org/wiki/QR-%EA%EE%E4" // Text to encode into QRCode
#define OUT_FILE "C:/test.bmp" // Output file name
#define OUT_FILE_PIXEL_PRESCALER 8 // Number of pixels in bmp file for each QRCode pixel, on each dimension

#define PIXEL_COLOR_R 0 // Color of bmp pixels
#define PIXEL_COLOR_G 0
#define PIXEL_COLOR_B 0xff

typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef signed long LONG;

#define BI_RGB 0L

#pragma pack(push, 2)

typedef struct
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;

typedef struct
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;

#pragma pack(pop)

int _tmain(int argc, _TCHAR** argv)
{
char* szSourceSring = QRCODE_TEXT;
unsigned int unWidth, x, y, l, n, unWidthAdjusted, unDataBytes;
unsigned char* pRGBData, *pSourceData, *pDestData;
QRcode* pQRC;
FILE* f;

/*
* Создание символа из строки. Библиотека автоматически
* парсит входную строку и кодирует ее в символ QR-кода.
* WARNING: Эта функция THREAD-UNSAFE, когда pthread отключен.
* Параметры:
* string: входная строка; должна завершаться нулем
* version: версия символа; если 0, библиотека выбирает минимальную версию входных данных
* level: уровень коррекции ошибок
* hint: указывает библиотеке на то, как должны кодироваться не алфавитные символы
* QR_MODE_KANJI - иероглифы будут кодироваться как Shif-JIS
* QR_MODE_8 - все не алфавитные символы будут кодироваться как есть. Для UTF-8, выбирайте этот режим
* casesensitive: case-sensitive(1) или нет(0).
* return: экземпляр класса QRcode; при ошибке возвращается NULL и errno устанавливает ошибку
* EINVAL: некорректный входной объект
* ENOMEM: не удается выделить память для входных объектов
* ERANGE: входные данные слишком большие
*/

// Вычисление QRcode
if (pQRC = QRcode_encodeString(szSourceSring, 0, QR_ECLEVEL_H, QR_MODE_8, 1))
{
unWidth = pQRC->width;
unWidthAdjusted = unWidth * OUT_FILE_PIXEL_PRESCALER * 3;
if (unWidthAdjusted % 4)
unWidthAdjusted = (unWidthAdjusted / 4 + 1) * 4;
unDataBytes = unWidthAdjusted * unWidth * OUT_FILE_PIXEL_PRESCALER;

if (!(pRGBData = (unsigned char*)malloc(unDataBytes)))
{
printf("Out of memory");
exit(1);
}

memset(pRGBData, 0xff, unDataBytes);

// Подготовка заголовков bmp
BITMAPFILEHEADER kFileHeader;
kFileHeader.bfType = 0x4d42; // "BM"
kFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nDataBytes;
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;

// Конвертирование битов QrCode в bmp пиксели
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++;
}
}

if (!(fopen_s(&f, OUT_FILE, "wb")))
{
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");
exit(1);
}

free(pRGBData);
QRcode_free(pQRC);
}
else
{
printf("NULL returned");
exit(1);
}

return 0;
}




Изменяя дефайны, можно перекомпилировать программу, для генерации разных url / выходных файлов / размеров пикселей / цветов пикселей.

P.S: Сначала я пытался пользоваться библиотекой, но линковщик не прекращал стрелять ошибками о неразрешенных ссылках, конфликтующих функциях и т.п., поэтому я включил исходный код в проект и скомпилировал все вместе.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


Комментариев нет:

Отправить комментарий