⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 datamatrixhighlevelencoder.java

📁 生成二维条形码的java程序
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright 2006-2007 Jeremias Maerki.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $Id: DataMatrixHighLevelEncoder.java,v 1.14 2007/07/13 09:57:05 jmaerki Exp $ */

package org.krysalis.barcode4j.impl.datamatrix;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

/**
 * DataMatrix ECC 200 data encoder following the algorithm described in ISO/IEC 16022:200(E) in
 * annex S.
 * 
 * @version $Id: DataMatrixHighLevelEncoder.java,v 1.14 2007/07/13 09:57:05 jmaerki Exp $
 */
public class DataMatrixHighLevelEncoder implements DataMatrixConstants {

    private static final boolean DEBUG = false;
    
    private static final int ASCII_ENCODATION = 0;
    private static final int C40_ENCODATION = 1;
    private static final int TEXT_ENCODATION = 2;
    private static final int X12_ENCODATION = 3;
    private static final int EDIFACT_ENCODATION = 4;
    private static final int BASE256_ENCODATION = 5;

    private static final String[] ENCODATION_NAMES
        = new String[] {"ASCII", "C40", "Text", "ANSI X12", "EDIFACT", "Base 256"};
    
    private static final String DEFAULT_ASCII_ENCODING = "ISO-8859-1";
    
    /**
     * Converts the message to a byte array using the default encoding (cp437) as defined by the
     * specification
     * @param msg the message
     * @return the byte array of the message
     */
    public static byte[] getBytesForMessage(String msg) {
        final String charset = "cp437"; //See 4.4.3 and annex B of ISO/IEC 15438:2001(E)
        try {
            return msg.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new UnsupportedOperationException(
                    "Incompatible JVM! The '" + charset + "' charset is not available!");
        }
    }
    
    private static char randomize253State(char ch, int codewordPosition) {
        int pseudoRandom = ((149 * codewordPosition) % 253) + 1;
        int tempVariable = ch + pseudoRandom;
        if (tempVariable <= 254) {
            return (char)tempVariable;
        } else {
            return (char)(tempVariable - 254);
        }
    }

    private static char randomize255State(char ch, int codewordPosition) {
        int pseudoRandom = ((149 * codewordPosition) % 255) + 1;
        int tempVariable = ch + pseudoRandom;
        if (tempVariable <= 255) {
            return (char)tempVariable;
        } else {
            return (char)(tempVariable - 256);
        }
    }

    /**
     * Performs message encoding of a DataMatrix message using the algorithm described in annex P
     * of ISO/IEC 16022:2000(E).
     * @param msg the message
     * @return the encoded message (the char values range from 0 to 255)
     */
    public static String encodeHighLevel(String msg) {
        return encodeHighLevel(msg, SymbolShapeHint.FORCE_NONE);
    }

    /**
     * Performs message encoding of a DataMatrix message using the algorithm described in annex P
     * of ISO/IEC 16022:2000(E).
     * @param msg the message
     * @param shape requested shape. May be <code>SymbolShapeHint.FORCE_NONE</code>,
     * <code>SymbolShapeHint.FORCE_SQUARE</code> or <code>SymbolShapeHint.FORCE_RECTANGLE</code>.
     * @return the encoded message (the char values range from 0 to 255)
     */
    public static String encodeHighLevel(String msg, SymbolShapeHint shape) {
        //the codewords 0..255 are encoded as Unicode characters
        Encoder[] encoders = new Encoder[] {new ASCIIEncoder(), 
                new C40Encoder(), new TextEncoder(), new X12Encoder(), new EdifactEncoder(),
                new Base256Encoder()}; 
        
        int encodingMode = ASCII_ENCODATION; //Default mode
        EncoderContext context = new EncoderContext(msg, shape);
        
        if (msg.startsWith(MACRO_05_HEADER) && msg.endsWith(MACRO_TRAILER)) {
            context.writeCodeword(MACRO_05);
            context.setSkipAtEnd(2);
            context.pos += MACRO_05_HEADER.length();
        } else if (msg.startsWith(MACRO_06_HEADER) && msg.endsWith(MACRO_TRAILER)) {
            context.writeCodeword(MACRO_06);
            context.setSkipAtEnd(2);
            context.pos += MACRO_06_HEADER.length();
        }
        
        while (context.hasMoreCharacters()) {
            encoders[encodingMode].encode(context);
            if (context.newEncoding >= 0) {
                encodingMode = context.newEncoding;
                context.resetEncoderSignal();
            }
        }
        int len = context.codewords.length();
        context.updateSymbolInfo();
        int capacity = context.symbolInfo.dataCapacity;
        if (len < capacity) {
            if (encodingMode != ASCII_ENCODATION && encodingMode != BASE256_ENCODATION) {
                if (DEBUG) {
                    System.out.println("Unlatch because symbol isn't filled up");
                }
                context.writeCodeword('\u00fe'); //Unlatch (254)
            }
        }
        //Padding
        StringBuffer codewords = context.codewords;
        if (codewords.length() < capacity) {
            codewords.append(DataMatrixConstants.PAD);
        }
        while (codewords.length() < capacity) {
            codewords.append(randomize253State(DataMatrixConstants.PAD, codewords.length() + 1));
        }
        
        return context.codewords.toString();
    }

    public static byte[] encodeMsg(String msg) {
        try {
            return msg.getBytes(DEFAULT_ASCII_ENCODING);
        } catch (UnsupportedEncodingException e) {
            throw new UnsupportedOperationException("Unsupported encoding: " + e.getMessage());
        }
    }
    
    private static class EncoderContext {

        private String msg;
        private SymbolShapeHint shape;
        private byte[] encodedMsg;
        private StringBuffer codewords;
        private int pos = 0;
        private int newEncoding = -1;
        private DataMatrixSymbolInfo symbolInfo;
        private int skipAtEnd = 0;
        
        public EncoderContext(String msg, SymbolShapeHint shape) {
            this.msg = msg;
            this.shape = shape;
            this.encodedMsg = encodeMsg(msg);
            this.codewords = new StringBuffer(msg.length());
        }
        
        public String getMessage() {
            return this.msg;
        }
        
        public void setSkipAtEnd(int count) {
            this.skipAtEnd = count;
        }

        public char getCurrentChar() {
            return msg.charAt(pos);
        }
        
        public byte getCurrentByte() {
            return encodedMsg[pos];
        }
        
        public char getCurrent() {
            return msg.charAt(pos);
        }
        
        public void writeCodewords(String codewords) {
            this.codewords.append(codewords);
        }
        
        public void writeCodeword(char codeword) {
            this.codewords.append(codeword);
        }
        
        public int getCodewordCount() {
            return this.codewords.length();
        }
        
        public void signalEncoderChange(int encoding) {
            this.newEncoding = encoding;
        }
        
        public void resetEncoderSignal() {
            this.newEncoding = -1;
        }

        public boolean hasMoreCharacters() {
            return pos < getTotalMessageCharCount();
        }

        private int getTotalMessageCharCount() {
            return msg.length() - skipAtEnd;
        }
        
        public int getRemainingCharacters() {
            return getTotalMessageCharCount() - pos;
        }
        
        public void updateSymbolInfo() {
            updateSymbolInfo(getCodewordCount());
        }

        public void updateSymbolInfo(int len) {
            if (this.symbolInfo == null || len > this.symbolInfo.dataCapacity) {
                this.symbolInfo = DataMatrixSymbolInfo.lookup(len, shape);
            }
        }

        public void resetSymbolInfo() {
            this.symbolInfo = null;
        }
    }
    
    private interface Encoder {
        int getEncodingMode();
        void encode(EncoderContext context);
    }
    
    private static class ASCIIEncoder implements Encoder {
        
        public int getEncodingMode() {
            return ASCII_ENCODATION;
        }
        
        public void encode(EncoderContext context) {
            //step B
            int n = determineConsecutiveDigitCount(context.msg, context.pos);
            if (n >= 2) {
                context.writeCodeword(encodeASCIIDigits(context.msg.charAt(context.pos), 
                        context.msg.charAt(context.pos + 1)));
                context.pos += 2;
            } else {
                char c = context.getCurrentChar();
                int newMode = lookAheadTest(context.msg, context.pos, getEncodingMode());
                if (newMode != getEncodingMode()) {
                    switch (newMode) {
                    case BASE256_ENCODATION:
                        context.writeCodeword(LATCH_TO_BASE256);
                        context.signalEncoderChange(BASE256_ENCODATION);
                        return;
                    case C40_ENCODATION:
                        context.writeCodeword(LATCH_TO_C40);
                        context.signalEncoderChange(C40_ENCODATION);
                        return;
                    case X12_ENCODATION:
                        context.writeCodeword(LATCH_TO_ANSIX12);
                        context.signalEncoderChange(X12_ENCODATION);
                        break;
                    case TEXT_ENCODATION:
                        context.writeCodeword(LATCH_TO_TEXT);
                        context.signalEncoderChange(TEXT_ENCODATION);
                        break;
                    case EDIFACT_ENCODATION:
                        context.writeCodeword(LATCH_TO_EDIFACT);
                        context.signalEncoderChange(EDIFACT_ENCODATION);
                        break;
                    default:
                        throw new IllegalStateException("Illegal mode: " + newMode);
                    }
                } else if (isExtendedASCII(c)) {
                    context.writeCodeword(UPPER_SHIFT);
                    context.writeCodeword((char)(c - 128 + 1));
                    context.pos++;
                } else {
                    if (DEBUG) {
                        if (!isASCII7(c)) {
                            throw new IllegalArgumentException("Not an ASCII-7 character");
                        }
                    }
                    context.writeCodeword((char)(c + 1));
                    context.pos++;
                }
                
            }
        }
        
    }
    
    private static class C40Encoder implements Encoder {
        
        public int getEncodingMode() {
            return C40_ENCODATION;
        }
        
        public void encode(EncoderContext context) {
            //step C
            int lastCharSize = -1;
            StringBuffer buffer = new StringBuffer();
            outerloop: while (context.hasMoreCharacters()) {
                char c = context.getCurrentChar();
                context.pos++;

                lastCharSize = encodeChar(c, buffer);
                
                int unwritten = (buffer.length() / 3) * 2;
                
                int curCodewordCount = context.getCodewordCount() + unwritten;
                context.updateSymbolInfo(curCodewordCount);
                int available = context.symbolInfo.dataCapacity - curCodewordCount;
                
                if (!context.hasMoreCharacters()) {
                    //Avoid having a single C40 value in the last triplet
                    StringBuffer removed = new StringBuffer();
                    if ((buffer.length() % 3) == 2) {
                        if (available < 2 || available > 2) {
                            lastCharSize = backtrackOneCharacter(context, buffer, removed,  
                                    lastCharSize);
                        }
                    }
                    while ((buffer.length() % 3) == 1 
                            && ((lastCharSize <= 3 && available != 1) || lastCharSize > 3)) {
                        lastCharSize = backtrackOneCharacter(context, buffer, removed,  
                                lastCharSize);
                    }
                    break outerloop;
                }
                
                int count = buffer.length(); 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -