且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在C#中ZXing(QUOT;斑马线")

更新时间:2023-02-15 19:48:01

这取决于你正在使用它什么,当然。即使zxing的Java版本有一些重要的限制和性能问题。例如,它只能找到一个页面上的一个条形码。同时,它采用在页面上定位一维条码的算法不是特别有效(没有关于算法的2-D条形码的想法 - 这是不是对我工作的项目要求的一部分)。这是所有的东西,可以得到解决 - 我在几个月前就开始增强,并能改善显著1-D位置的性能和可靠性,但我们的开发优先级已经改变,所以我没有,因为从那时起它的工作。 p>

至于部分港口C#是好,如果你想回来后有什么区别,我很乐意发表意见。



编辑 - 下面是一些我做的重构:



首先,分解出RowNumberStrategy如下:

 公共接口RowNumberStrategy {
公众诠释getNextRowNumber();

公共类OriginalRowStrategy实现RowNumberStrategy {
INT中间;
布尔tryHarder = FALSE;
INT rowStep;
INT MAXLINES;
INT maxRows进行;

INT X;

公共OriginalRowStrategy(INT maxRows进行,布尔tryHarder){
this.x = 0;
this.maxRows = maxRows进行;
this.middle = maxRows进行>> 1; // 2
鸿沟this.tryHarder = tryHarder;
rowStep = Math.max(1,maxRows进行>>(tryHarder 7:4));
如果(tryHarder){
MAXLINES = maxRows进行; //看整体形象,而不仅仅是中心
}其他{
MAXLINES = 9; //九行间隔1/16与众不同的是大致图像
}
}

公众诠释getNextRowNumber(){
如果(X&GT的中间一半; MAXLINES)
返回-1;

INT rowStepsAboveOrBelow =(X + 1)GT;> 1;
布尔isAbove =(X安培; 0x01)的== 0; //即是X连?
INT ROWNUMBER =中间+ rowStep *(isAbove rowStepsAboveOrBelow:-rowStepsAboveOrBelow);
如果(ROWNUMBER℃,|| ROWNUMBER> = maxRows进行){
//哎呀,如果我们运行了顶部或底部,停止
返回-1;
}

X = X + 1;

返回ROWNUMBER;
}

}

公共类LinearScanRowStrategy实现RowNumberStrategy {
私人最终诠释maxRows进行;
私人诠释currentRow;
公共LinearScanRowStrategy(INT totalRows){
maxRows进行= totalRows;
currentRow = 0;
}

公众诠释getNextRowNumber(){
如果(currentRow> maxRows进行)
返回-1;

返回maxRows进行 - 1 - currentRow ++;
}

}

公共类ProgressiveScanRowStrategy实现RowNumberStrategy {
私人最终诠释maxRows进行;
私人诠释currentStepSize;
私人诠释currentStep;

公共ProgressiveScanRowStrategy(INT totalRows){
maxRows进行= totalRows;
currentStep = 0;
currentStepSize = maxRows进行;
}

公众诠释getNextRowNumber(){
INT nextRow =(currentStep ++)* currentStepSize;
如果(nextRow< maxRows进行)
返回nextRow;

currentStepSize = currentStepSize>> 1;
如果(currentStepSize< = 0)
返回-1;
currentStep = 1;

nextRow = currentStep * currentStepSize;

返回nextRow;
}

}



}

然后doDecode的顶部变成如下:

 私人结果doDecode(MonochromeBitmapSource图像,Hashtable的提示)抛出ReaderException {


INT宽度= image.getWidth();
INT高= image.getHeight();
BitArray行=新BitArray(宽);
布尔tryHarder =提示=空&安培;!&安培; hints.containsKey(DecodeHintType.TRY_HARDER);
RowNumberStrategy rowProvider =新RowNumberStrategy.ProgressiveScanRowStrategy(高度);

INT ROWNUMBER;
,而((ROWNUMBER = rowProvider.getNextRowNumber())!= -1){

}

最终,这应该是东西,可以通过DecodeHintType进行设置,但我们发现,渐进的策略是比旧的战略在任何情况下,我们快可以在它扔(而不是仅仅快一点 - 的更快)


I'm looking for a good open-source library that can find and read a barcode from an image (versus using a barcode scanner). From other questions on Stack Overflow, I've found that ZXing ("Zebra Crossing") is quite good. Though it is made for Java, there is a C# port - however, I believe that it might not be complete. Do you think it is reliable enough to parse a barcode from such a situation, or is some other library better?

EDIT: As Ed pointed out in the comments, I should just try it first. Wow, I did not think of that. :) but I guess my question is whether the partial port is reliable enough - if any of you have used it before, can it scan with proficiency?

This depends on what you are using it for, of course. Even the Java version of zxing has some important limitations and performance issues. For example, it can only find one barcode on a page. Also, the algorithms it uses for locating 1-D barcode on the page are not particularly efficient (no idea about the algorithms for 2-D barcodes - that wasn't part of the requirements on the project I was working on). This is all stuff that can be addressed - I started an enhancement a few months ago and was able to significantly improve 1-D location performance and reliability, but our dev priorities have shifted so I haven't worked on it since then.

As for whether the partial port to C# is good, if you want to post back with what the differences are, I'd be happy to comment.

EDIT - here is some of the refactoring that I did:

First, factor out RowNumberStrategy as follows:

public interface RowNumberStrategy {
public int getNextRowNumber();

public class OriginalRowStrategy implements RowNumberStrategy{
    int middle;
    boolean tryHarder = false;
    int rowStep;
    int maxLines;
    int maxRows;

    int x;

    public OriginalRowStrategy(int maxRows, boolean tryHarder) {
        this.x = 0;
        this.maxRows = maxRows;
        this.middle = maxRows >> 1; // divide by 2
        this.tryHarder = tryHarder;
        rowStep = Math.max(1, maxRows >> (tryHarder ? 7 : 4));
        if (tryHarder) {
          maxLines = maxRows; // Look at the whole image, not just the center
        } else {
          maxLines = 9; // Nine rows spaced 1/16 apart is roughly the middle half of the image
        }
    }

    public int getNextRowNumber() {
        if (x > maxLines)
            return -1;

        int rowStepsAboveOrBelow = (x + 1) >> 1;
        boolean isAbove = (x & 0x01) == 0; // i.e. is x even?
        int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);
        if (rowNumber < 0 || rowNumber >= maxRows) {
          // Oops, if we run off the top or bottom, stop
          return -1;
        }

        x = x + 1;

        return rowNumber;
    }

}

public class LinearScanRowStrategy implements RowNumberStrategy{
    private final int maxRows;
    private int currentRow;
    public LinearScanRowStrategy(int totalRows) {
        maxRows = totalRows;
        currentRow = 0;
    }

    public int getNextRowNumber() {
        if (currentRow > maxRows)
            return -1;

        return maxRows - 1 - currentRow++;
    }

}

public class ProgressiveScanRowStrategy implements RowNumberStrategy{
    private final int maxRows;
    private int currentStepSize;
    private int currentStep;

    public ProgressiveScanRowStrategy(int totalRows) {
        maxRows = totalRows;
        currentStep = 0;
        currentStepSize = maxRows;
    }

    public int getNextRowNumber() {
        int nextRow = (currentStep++) * currentStepSize;
        if (nextRow < maxRows)
            return nextRow;

        currentStepSize = currentStepSize >> 1;
        if (currentStepSize <= 0)
            return -1;
        currentStep = 1;

        nextRow = currentStep * currentStepSize;

        return nextRow;
    }

}



}

then the top part of doDecode becomes as follows:

private Result doDecode(MonochromeBitmapSource image, Hashtable hints) throws ReaderException {


int width = image.getWidth();
int height = image.getHeight();
BitArray row = new BitArray(width);
boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
RowNumberStrategy rowProvider = new RowNumberStrategy.ProgressiveScanRowStrategy(height);  

int rowNumber;
while ((rowNumber = rowProvider.getNextRowNumber()) != -1){
...
}

ultimately, this should be something that can be set via a DecodeHintType, but we've found that the progressive strategy is faster than the old strategy in every case we could throw at it (and not just a little faster - much faster).