采用GDI技术生成条形码(Code39)

简介

Ø         Code39介绍

Ø         Code Table

Ø         示例

Code39介绍

1.         Code 39是一种条形码的编码标准。它的码表构成由26个大写英文字母(A-Z)和10个数字符号(0-9)以及7个特殊字符(-.sp*/+%)组成。

2.         一个Code39条码由5个条码区4个空白区成共9个区域组成,每个区域只能是宽或窄,并且9个区域中总有3个宽的,这就是Code39名字的由来。

3.         通常使用*作为编码的起始与结束。并且编码的起始与终止前后需要一段干净的区域(通常比长度大0.1英寸)。

4.         通常使读码枪能顺利识别,其中“窄”条码的最小宽度为7.5mils1 mil=1/1000英寸)或0.19毫米

5.         如果“窄”条码的宽度大于20mils,则“宽“条码的宽度为“窄”条码的2-3倍;如果“窄”条码的宽度小于20mils,则“宽”条码的跨度为“窄”条码的2-2.2倍。

6.         条码的高度至少为条码总宽度的0.15倍或0.25英寸

条码总宽度计算公式

L = (C + 2)(3N + 6)X + (C + 1)I

L条码的总宽度,不包含“干净区域“

C条码中符号的个数

X其中“窄”条码的宽度

N“宽“条码与“窄”条码的比例

I分隔符号的宽度,通常为黑条间所夹的白色区域

Code39 Table

Char.

Pattern
b s b s b s b s b

Char.

Pattern
b s b s b s b s b

Char.

Pattern
b s b s b s b s b

Char.

Pattern
b s b s b s b s b

0

n n n w w n w n n

C

w n w n n w n n n

O

w n n n w n n w n

-

n w n n n n w n w

1

w n n w n n n n w

D

n n n n w w n n w

P

n n w n w n n w n

.

w w n n n n w n n

2

n n w w n n n n w

E

w n n n w w n n n

Q

n n n n n n w w w

SP

n w w n n n w n n

3

w n w w n n n n n

F

n n w n w w n n n

R

w n n n n n w w n

*

n w n n w n w n n

4

n n n w w n n n w

G

n n n n n w w n w

S

n n w n n n w w n

$

n w n w n w n n n

5

w n n w w n n n n

H

w n n n n w w n n

T

n n n n w n w w n

/

n w n w n n n w n

6

n n w w w n n n n

I

n n w n n w w n n

U

w w n n n n n n w

+

n w n n n w n w n

7

n n n w n n w n w

J

n n n n w w w n n

V

n w w n n n n n w

%

n n n w n w n w n

8

w n n w n n w n n

K

w n n n n n n w w

W

w w w n n n n n n

9

n n w w n n w n n

L

n n w n n n n w w

X

n w n n w n n n w

A

w n n n n w n n w

M

w n w n n n n w n

Y

w w n n w n n n n

B

n n w n n w n n w

N

n n n n w n n w w

Z

n w w n w n n n n

(b黑色,s白色,n“窄“,w宽) SP为空格

示例

说明:

       当前条码打印基本都是用条码字库实现的。在实际操作中需要依赖字库,并且发现有的条码识别枪对其生成的条码识别率不高。

示例采用java语言编码实现,其中“宽“与“窄”采用GDI中的像素为单位且已黑白为条码颜色。其中生成一张底色为白色的图片,然后在上面化黑色的条码,然后进行偏移画下一个黑色的条码。生成示例*JOYCODES.COM*

联系方式:[email protected] 转载请注明出处。

package  com.css.aicmap.util.barcode;

import  java.awt.image.BufferedImage;
import  java.awt.Graphics;
import  java.awt.Color;
import  java.awt.geom.AffineTransform;
import  java.awt.image.AffineTransformOp;
import  com.sun.image.codec.jpeg.JPEGImageEncoder;
import  com.sun.image.codec.jpeg.JPEGCodec;
import  java.io.OutputStream;

import  com.sun.image.codec.jpeg.ImageFormatException;
import  java.io.IOException;

/**
 * 符合BarCode 39规范的条码图像生成器
 * 
@author ChenLiang & LiGuang
 
*/

public   class  BarCode39ImageBuilder
{
    
private static final int rate = 3//条码宽条与窄条宽度之比

    
private int m_nNarrowWidth; //窄条的宽度像素数
    private int m_nImageHeight; //条码的高度像素数
    private boolean m_bRotato;    //输出的图像是否需要先旋转

    
/**
     * 根据strCodes传入的字符串,生成符合BarCode 39规范的JPEG输出流;
     * 
@param nNarrowWidth 
     * 
@param nImageHeight 
     
*/

    
public BarCode39ImageBuilder(int nNarrowWidth, int nImageHeight)
    
{
        m_nNarrowWidth 
= nNarrowWidth;
        m_nImageHeight 
= nImageHeight;
        m_bRotato 
= false;
    }


    
/**
     * 构造函数,默认窄条宽为4像素,条码高度是100像素;
     
*/

    
public BarCode39ImageBuilder()
    
{
        
this(4100);
    }


    
/**
     * 设置是否需要将结果图像在输出之前进行旋转;系统默认是不旋转
     * 
@param b    true:旋转,false:不旋转
     
*/

    
public void setRotato(boolean b)
    
{
        m_bRotato 
= b;
    }


    
/**
     * 生成相应的Bar Code图像,格式以jpeg格式的输出流;
     * 
@param strCodes    要生成条码的字符串,注意该字符串需要包含首尾的两个星号
     * 
@param out        接结果的输出流
     * 
@throws IOException 
     * 
@throws ImageFormatException 
     * 
@throws IOException
     
*/

    
public void genImage(String strCodes, OutputStream out) throws ImageFormatException, IOException
    
{
        
if (null==strCodes || null==out || 0==strCodes.length())
            
return;
        
        
int nImageWidth = (strCodes.length() * (3 * rate + 7* m_nNarrowWidth);

        BufferedImage bi 
= new BufferedImage(nImageWidth, m_nImageHeight, BufferedImage.TYPE_INT_RGB);
        Graphics g 
= bi.getGraphics();

        g.setColor(Color.WHITE);
        g.fillRect(
00, nImageWidth, m_nImageHeight);

        g.setColor(Color.BLACK);
        
int startx = 0;
        
for (int i = 0; i < strCodes.length(); i++)
            startx 
= drawOneChar(g, startx, strCodes.charAt(i));

        
if (m_bRotato)
            bi 
= flipX2Y(bi);

        JPEGImageEncoder encoder 
= JPEGCodec.createJPEGEncoder(out);
        encoder.encode(bi);
    }


    
/**
     * 辅助方法,绘制一个字符
     * 
@param g        画布
     * 
@param x        起始位置
     * 
@param ch    要绘制的字符
     * 
@return        下一个要绘制字符的位置
     
*/

    
private int drawOneChar(Graphics g, int x, char ch)
    
{
        
short sCode = getCharCode(ch);
        
for (int i = 0; i < 9; i++)
        
{
            
int width = m_nNarrowWidth;

            
if (((0x100 >>> i) & sCode) != 0)
                width 
*= rate;

            
if ((i & 0x1== 0)
                g.fillRect(x, 
0, width, m_nImageHeight);

            x 
+= width;
        }

        
return x + m_nNarrowWidth;
    }


    
/**
     * 图像翻转,即X与Y方向互换
     * 
@param in    源图像
     * 
@return        翻转后的图像
     
*/

    
private BufferedImage flipX2Y(BufferedImage in)
    
{
        BufferedImage out 
= new BufferedImage(in.getHeight(), in.getWidth(), in.getType());
        
//请查看JDK
        AffineTransform affineTransform = new AffineTransform(011000);
        AffineTransformOp affineTransformOp 
= new AffineTransformOp(affineTransform,
                AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
        
return affineTransformOp.filter(in, out);
    }


    
//    原来旋转的版本,仅供参考
    
//    private BufferedImage rotate(BufferedImage in)
    
//    {
    
//        int width = in.getWidth();
    
//        int height = in.getHeight();
    
//        BufferedImage out = new BufferedImage(height, width, in.getType());
    
//
    
//        AffineTransform affineTransform = AffineTransform.getRotateInstance(Math.toRadians(90));
    
//        affineTransform.translate(0, -height);
    
//                
    
//        AffineTransformOp affineTransformOp = new AffineTransformOp(affineTransform,
    
//                AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
    
//        affineTransformOp.filter(in, out);
    
//        return out;
    
//    }

    
//Code39符号表
    private static final char[] m_chars = '0''1''2''3''4''5''6''7''8''9''A''B''C''D',
            
'E''F''G''H''I''J''K''L''M''N''O''P''Q''R''S''T''U''V''W''X',
            
'Y''Z''-''.'' ''*''$''/''+''%' }
;
    
//Code39符号所对应的码表,16进制编码 n为0 w为1
    private static final short[] m_codes = 0x340x1210x610x1600x310x1300x700x250x1240x64,
            
0x1090x490x1480x190x1180x580xd0x10c0x4c0x1c0x1030x430x1420x130x1120x52,
            
0x70x1060x460x160x1810xc10x1c00x910x1900xd00x850x1840xc40x940xa80xa2,
            
0x8a0x2a }
;
    
/**
     * 通过码表符号获得码表字符
     * 
@param ch 码表符号
     * 
@return 码表值
     
*/

    
private static short getCharCode(char ch)
    
{
        
for (int i = 0; i < m_chars.length; i++)
        
{
            
if (ch == m_chars[i])
                
return m_codes[i];
        }

        
return 0;
    }

}

你可能感兴趣的:(code)