Day: January 23, 2013

  • 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 
    
    #if !defined(LEPTONICA_ALLHEADERS_H)
    #   include 
    #endif
    
    #if !defined(LEPTONICA_READBARCODE_H)
    #	include 
    #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.