QRCodeを生成し、ImageMagickとzbarを使ってQRCodeから内容を読み取る。
6889 ワード
#include <iostream>
#include <qrencode.h>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <wand/MagickWand.h>
#include <zbar.h>
using namespace std;
using namespace zbar;
//#define QRCODE_TEXT "http://www.ultramundum.org/index.htm"; // Text to encode into QRCode
#define QRCODE_TEXT " 。Hello, QR Code!"; // Text to encode into QRCode
#define OUT_FILE "./test.bmp" // Output file name
#define OUT_FILE_PIXEL_PRESCALER 8 // Prescaler (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 int DWORD;
typedef signed int LONG;
#define BI_RGB 0L
//!!!imported for create bmp image!!!
#pragma pack(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()
void CreateQRCodeImage();
void readQRCodeImageInfo();
int main() {
CreateQRCodeImage();
readQRCodeImageInfo();
return 0;
}
void CreateQRCodeImage() {
const char* szSourceSring = QRCODE_TEXT;
unsigned int unWidth, x, y, l, n, unWidthAdjusted, unDataBytes;
unsigned char* pRGBData, *pSourceData, *pDestData;
QRcode* pQRC;
FILE* f;
if ((pQRC = QRcode_encodeString(szSourceSring, 0, QR_ECLEVEL_H, QR_MODE_8, 1)) != NULL)
{
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;
// Allocate pixels buffer
if (!(pRGBData = (unsigned char*)malloc(unDataBytes)))
{
printf("Out of memory");
exit(-1);
}
// Preset to white
memset(pRGBData, 0xff, unDataBytes);
// Prepare bmp headers
BITMAPFILEHEADER kFileHeader = {0};
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
if ((f = fopen(OUT_FILE, "wb")) != 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");
exit(-1);
}
// Free data
free(pRGBData);
QRcode_free(pQRC);
}
else {
printf("QRcode_encodeString failed
");
exit(-1);
}
}
void readQRCodeImageInfo() {
#define ThrowWandException(wand) \
{ \
char \
*description; \
\
ExceptionType \
severity; \
\
description=MagickGetException(wand,&severity); \
(void) fprintf(stdout,"%s %s %lu %s
",GetMagickModule(),description); \
description=(char *) MagickRelinquishMemory(description); \
exit(-1); \
}
MagickBooleanType status;
MagickWand *magick_wand;
MagickWandGenesis();
magick_wand=NewMagickWand();
status=MagickReadImage(magick_wand,"./test.bmp");
if (status == MagickFalse)
ThrowWandException(magick_wand);
size_t width, height;
width = MagickGetImageWidth(magick_wand);
height = MagickGetImageHeight(magick_wand);
if (status == MagickFalse) {
ThrowWandException(magick_wand);
}
else {
printf("width=%d, height=%d
", width, height);
}
void *pixel = malloc(width*height);
//get gray pixel
status = MagickExportImagePixels(magick_wand, 0, 0, width, height, "I", CharPixel, pixel);
if (status == MagickFalse)
ThrowWandException(magick_wand);
zbar_image_scanner_t *scanner = zbar_image_scanner_create();
/* configure the reader */
zbar_image_scanner_set_config(scanner, ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
/*
size_t blobSize;
unsigned char *blob = MagickGetImagesBlob(magick_wand, &blobSize);
printf("blob size = %d
", blobSize);
*/
/* wrap image data */
zbar_image_t *image = zbar_image_create();
zbar_image_set_format(image, *(int*)"Y800");
zbar_image_set_size(image, width, height);
zbar_image_set_data(image, pixel, width*height, zbar_image_free_data);
/* scan the image for barcodes */
int n = zbar_scan_image(scanner, image); //n == 0 is failed
if (n > 0) {
/* extract results */
const zbar_symbol_t *symbol = zbar_image_first_symbol(image);
for(; symbol; symbol = zbar_symbol_next(symbol))
{
/* do something useful with results */
zbar_symbol_type_t typ = zbar_symbol_get_type(symbol);
const char *data = zbar_symbol_get_data(symbol);
printf("decoded %s symbol \"%s\"
", zbar_get_symbol_name(typ), data);
}
}
else {
printf("zbar_scan_image return %d, failed
", n);
}
free(pixel);
magick_wand=DestroyMagickWand(magick_wand);
MagickWandTerminus();
}