Example of a QR Code Reader in C++

The ZXing library was originally developed for Java and examples for Java pipelines are well understood. It can be a little bit less obvious as to how to do this under C++.

Here are some simple, completely unsupported steps to get QR code decoding in a C++ pipeline. This has been tested under Ubuntu 10.04LTS using the SVN version of ZXing downloaded in May 2012. This is just a simple way to get started, it is NOT necessarily the best way of doing things and is NOT guaranteed to work. Please direct all questions to the ZXing mailing list.

To obtain and build the ZXing library:

  1. Install a Subversion client and Python if you don't already have it (under Ubuntu, “sudo apt-get install subversion python”
  2. Make a directory where you want to check out the ZXing source. In the subsequent discussion we'll assume it's in ~/zxing/
  3. Execute “svn checkout http://zxing.googlecode.com/svn/trunk/
  4. Change to trunk/cpp
  5. Build the C++ library using “python scons/scons.py lib”

Here is an example of a program that can read QR codes. Feel free to use this code however you need to. It isn't an example of good code, it's just intended to get you started. No guarantees that it'll work (although it worked for us!).

test.cpp
#include <iostream>
#include <stdlib.h>
#include <stdint.h>
#include <fstream>
#include <string>
#include <zxing/qrcode/QRCodeReader.h>
#include <zxing/Exception.h>
#include <zxing/common/GlobalHistogramBinarizer.h>
#include <zxing/DecodeHints.h>
#include "BufferBitmapSource.h"
 
using namespace std; 
using namespace zxing; 
using namespace zxing::qrcode;
using namespace qrviddec; 
 
int main(int argc, char ** argv)
{
	try
	{
 
 
		// A buffer containing an image. In your code, this would be an image from your camera. In this 
		// example, it's just an array containing the code for "Hello!". // Convert the buffer to something that the library understands. 
		Ref<LuminanceSource> source (new BufferBitmapSource(width, height, buffer)); 
 
		// Turn it into a binary image. 
		Ref<Binarizer> binarizer (new GlobalHistogramBinarizer(source)); 
		Ref<BinaryBitmap> image(new BinaryBitmap(binarizer));
 
		// Tell the decoder to try as hard as possible. 
		DecodeHints hints(DecodeHints::DEFAULT_HINT); 
		hints.setTryHarder(true); 
 
		// Perform the decoding. 
    QRCodeReader reader;
    Ref<Result> result(reader.decode(image, hints));
 
		// Output the result. 
    cout << result->getText()->getText() << endl;
 
  } 
	catch (zxing::Exception& e) 
	{
    cerr << "Error: " << e.what() << endl;
  }
	return 0; 
}

The matching BufferBitmapSource.cpp/h:

BufferBitmapSource.cpp
#include "BufferBitmapSource.h"
#include <iostream>
 
namespace qrviddec {
 
BufferBitmapSource::BufferBitmapSource(int inWidth, int inHeight, unsigned char * inBuffer) 
{
	width = inWidth; 
	height = inHeight; 
	buffer = inBuffer; 
}
 
BufferBitmapSource::~BufferBitmapSource()
{
}
 
int BufferBitmapSource::getWidth() const
{
	return width; 
}
 
int BufferBitmapSource::getHeight() const
{
	return height; 
}
 
unsigned char * BufferBitmapSource::getRow(int y, unsigned char * row)
{
	if (y < 0 || y >= height) 
	{
		fprintf(stderr, "ERROR, attempted to read row %d of a %d height image.\n", y, height); 
		return NULL; 
	}
	// WARNING: NO ERROR CHECKING! You will want to add some in your code. 
	if (row == NULL) row = new unsigned char[width]; 
	for (int x = 0; x < width; x ++)
	{
		row[x] = buffer[y*width+x]; 
	}
	return row; 
}
 
unsigned char * BufferBitmapSource::getMatrix()
{
	return buffer; 
}
 
}
BufferBitmapSource.cpp
#include <zxing/LuminanceSource.h>
#include <stdio.h>
#include <stdlib.h>
using namespace zxing; 
namespace qrviddec {
 
class BufferBitmapSource : public LuminanceSource {
private:
  int width, height; 
  unsigned char * buffer; 
 
public:
  BufferBitmapSource(int inWidth, int inHeight, unsigned char * inBuffer); 
  ~BufferBitmapSource(); 
 
  int getWidth() const; 
  int getHeight() const; 
  unsigned char* getRow(int y, unsigned char* row); 
  unsigned char* getMatrix(); 
}; 
}

To compile:

g++ BufferBitmapSource.cpp -c -o BufferBitmapSource.o -I ~/zxing/trunk/cpp/core/src
g++ test.cpp -o test -I ~/zxing/trunk/cpp/core/src -L ~/zxing/trunk/cpp/build -lzxing

To run:

./test

And the result should be:

$ ./test
Hello!
$

We hope this helps, good luck!

Back to the RoboCup 2012 QR Code page.
Back to the Safety, Security and Rescue Robotics Summer School page.

robocup2012/qrcode-cppexample.txt · Last modified: 2017/07/13 07:42 (external edit)
 
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki