Leptonica barcode generation

Leptonica provides us with easy way to read barcodes but it does not offer a way to create them(as far as I know). Here is a leptonica function that will allow us to generate CODABAR barcode, in the feature I am planning on adding more type and more options but for now this was all I needed.

Sample Usage

l_int32 res = 300;
l_int32 bar_width = .02 * res;
l_int32 bar_height = .35 * res;
 
// Barcode is bitonal
PIX* barcode= pixCreateBarcodeCodebar("C3853110009C", bar_width, bar_height, 10, 10, 2, 2);
if (barcode == NULL)
{
	printf("\n******** ERROR ***********");
	return;
}
pixWritePng("c:/temp/barcode.png", barcode, 0);

Implementation

/**
 * Barcode Generator
 * @author : greg
 */
#ifndef CREATEBARCODE_H_
#define CREATEBARCODE_H_
 
#include <ctype.h>
 
#if !defined(LEPTONICA_ALLHEADERS_H)
#   include <leptonica/allheaders.h>
#endif
 
#if !defined(LEPTONICA_READBARCODE_H)
#	include <leptonica/readbarcode.h>
#endif
 
/* ----------------------------------------------------------------- *
 * Codabar symbology                         *
 * Data  B  S  B  S  B  S  B   Value
 * 0     0  0  0  0  0  1  1     0
 * 1     0  0  0  0  1  1  0     1
 * 2     0  0  0  1  0  0  1     2
 * @ref http://www.barcodesymbols.com/codabar.htm
 * @ref leptonica/readbarcode.h
 * ----------------------------------------------------------------- */
static const char *CodabarCodes[] =
{ "1111122", "1111221", "1112112", "2211111", "1121121", /* 0: 0 - 4      */
"2111121", "1211112", "1211211", "1221111", "2112111", /* 5: 5 - 9      */
"1112211", "1122111", "2111212", "2121112", "2121211", /* 10: -,$,:,/,. */
"1121212", "1122121", "1212112", "1112122", "1112221" /* 15: +,A,B,C,D */
};
 
int mapCodebarToIndex(const char c)
{
	switch (toupper(c))
	{
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
		return atoi(&c);
	case '-':
		return 10;
	case '$':
		return 11;
	case ':':
		return 12;
	case '/':
		return 13;
	case '.':
		return 14;
	case '+':
		return 15;
	case 'A':
		return 16;
	case 'B':
		return 17;
	case 'C':
	case '*':
		return 18;
	case 'E':
	case 'D':
		return 19;
 
	}
	return 0;
}
 
/**
 * Crate 8 bpp Codebar barcode
 */
PIX* pixCreateBarcodeCodebar(const char* code, l_int32 bar_width, l_int32 bar_height, l_int32 margin_left,
		l_int32 margin_right, l_int32 margin_top, l_int32 margin_bottom)
{
	PROCNAME("pixCreateBarcodeCodebar");
 
	printf("\n Rendering : %s", code);
	//The width ratio between narrow and wide can be chosen between 1:2.25 and 1:3
	l_float32 ratio = 2;
	l_int32 width_wide = bar_width * ratio;
	l_int32 narrow_space = bar_width;
	// Calculate size
	l_int32 size = 0;
	for (int i = 0; code[i] != '\0'; ++i, ++size)
	{
		// NOOP
	}
	// allocate big enough image
	PIX* pix = pixCreate(size * width_wide * 7, bar_height, 1);
	pixSetResolution(pix, 300, 300);
 
	l_int32 xpos = margin_left;
	for (int i = 0; i < size; ++i)
	{
		const char* encoding = CodabarCodes[mapCodebarToIndex(code[i])];
		for (l_uint16 j = 0; j < 7; j++)
		{
			l_int32 renderwidth = bar_width;
			if (encoding[j] == '2')
			{
				renderwidth = width_wide;
			}
			if ((j % 2 == 0))
			{
				for (l_int32 k = 0; k < renderwidth; ++k)
				{
//					pixRenderLineArb(pix, xpos+k, 0, xpos+k, height, 1, 0, 0, 0);
					pixRenderLine(pix, xpos + k, margin_top, xpos + k, bar_height - margin_bottom, 1, L_SET_PIXELS);
				}
			}
			xpos += renderwidth;
		}
 
		// Each character is separated by narrow space
		if (i < size - 1)
			xpos += narrow_space;
	}
 
	// Clip
	BOX* bounds = boxCreate(0, 0, xpos + margin_right, bar_height);
	pix = pixClipRectangle(pix, bounds, NULL);
	boxDestroy(&bounds);
	return pix;
}
 
#endif /* CREATEBARCODE_H_ */

I think I will make this my first GIT project and share it with all, trying to move away from google code.

Leave a Comment

Your email address will not be published. Required fields are marked *