From: srowen Date: Wed, 16 Jun 2010 21:13:47 +0000 (+0000) Subject: Display possible country origin info on product scan X-Git-Url: http://git.rot13.org/?p=zxing.git;a=commitdiff_plain;h=bbd2b8fa4e0abaacd855b90dcbd8a6c740d7e822 Display possible country origin info on product scan git-svn-id: http://zxing.googlecode.com/svn/trunk@1438 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- diff --git a/android/src/com/google/zxing/client/android/CaptureActivity.java b/android/src/com/google/zxing/client/android/CaptureActivity.java index fbdb29d5..02cb6b06 100755 --- a/android/src/com/google/zxing/client/android/CaptureActivity.java +++ b/android/src/com/google/zxing/client/android/CaptureActivity.java @@ -68,7 +68,6 @@ import java.io.IOException; import java.text.DateFormat; import java.util.Arrays; import java.util.HashSet; -import java.util.Hashtable; import java.util.List; import java.util.Date; import java.util.Map; @@ -132,10 +131,11 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal private static final Set DISPLAYABLE_METADATA_TYPES; static { - DISPLAYABLE_METADATA_TYPES = new HashSet(3); + DISPLAYABLE_METADATA_TYPES = new HashSet(5); DISPLAYABLE_METADATA_TYPES.add(ResultMetadataType.ISSUE_NUMBER); DISPLAYABLE_METADATA_TYPES.add(ResultMetadataType.SUGGESTED_PRICE); DISPLAYABLE_METADATA_TYPES.add(ResultMetadataType.ERROR_CORRECTION_LEVEL); + DISPLAYABLE_METADATA_TYPES.add(ResultMetadataType.POSSIBLE_COUNTRY); } private enum Source { diff --git a/core/src/com/google/zxing/ResultMetadataType.java b/core/src/com/google/zxing/ResultMetadataType.java index 7e47b0e7..33d69d9c 100644 --- a/core/src/com/google/zxing/ResultMetadataType.java +++ b/core/src/com/google/zxing/ResultMetadataType.java @@ -74,6 +74,12 @@ public final class ResultMetadataType { */ public static final ResultMetadataType SUGGESTED_PRICE = new ResultMetadataType("SUGGESTED_PRICE"); + /** + * For some products, the possible country of manufacture as a {@link String} denoting the + * ISO country code. Some map to multiple possible countries, like "US/CA". + */ + public static final ResultMetadataType POSSIBLE_COUNTRY = new ResultMetadataType("POSSIBLE_COUNTRY"); + private final String name; private ResultMetadataType(String name) { diff --git a/core/src/com/google/zxing/oned/EANManufacturerOrgSupport.java b/core/src/com/google/zxing/oned/EANManufacturerOrgSupport.java new file mode 100644 index 00000000..c477ca85 --- /dev/null +++ b/core/src/com/google/zxing/oned/EANManufacturerOrgSupport.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * 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. + */ + +package com.google.zxing.oned; + +import java.util.Vector; + +/** + * Records EAN prefix to GS1 Member Organization, where the member organization + * correlates strongly with a country. This is an imperfect means of identifying + * a country of origin by EAN-13 barcode value. See + * + * http://en.wikipedia.org/wiki/List_of_GS1_country_codes. + * + * @author Sean Owen + */ +final class EANManufacturerOrgSupport { + + private final Vector ranges = new Vector(); + private final Vector countryIdentifiers = new Vector(); + + String lookupCountryIdentifier(String productCode) { + initIfNeeded(); + int prefix = Integer.parseInt(productCode.substring(0, 3)); + int max = ranges.size(); + for (int i = 0; i < max; i++) { + int[] range = (int[]) ranges.elementAt(i); + int start = range[0]; + if (prefix < start) { + return null; + } + int end = range.length == 1 ? start : range[1]; + if (prefix <= end) { + return (String) countryIdentifiers.elementAt(i); + } + } + return null; + } + + private void add(int[] range, String id) { + ranges.addElement(range); + countryIdentifiers.addElement(id); + } + + private synchronized void initIfNeeded() { + if (!ranges.isEmpty()) { + return; + } + add(new int[] {0,19}, "US/CA"); + add(new int[] {30,39}, "US"); + add(new int[] {60,139}, "US/CA"); + add(new int[] {300,379}, "FR"); + add(new int[] {380}, "BG"); + add(new int[] {383}, "SI"); + add(new int[] {385}, "HR"); + add(new int[] {387}, "BA"); + add(new int[] {400,440}, "DE"); + add(new int[] {450,459}, "JP"); + add(new int[] {460,469}, "RU"); + add(new int[] {471}, "TW"); + add(new int[] {474}, "EE"); + add(new int[] {475}, "LV"); + add(new int[] {476}, "AZ"); + add(new int[] {477}, "LT"); + add(new int[] {478}, "UZ"); + add(new int[] {479}, "LK"); + add(new int[] {480}, "PH"); + add(new int[] {481}, "BY"); + add(new int[] {482}, "UA"); + add(new int[] {484}, "MD"); + add(new int[] {485}, "AM"); + add(new int[] {486}, "GE"); + add(new int[] {487}, "KZ"); + add(new int[] {489}, "HK"); + add(new int[] {490,499}, "JP"); + add(new int[] {500,509}, "GB"); + add(new int[] {520}, "GR"); + add(new int[] {528}, "LB"); + add(new int[] {529}, "CY"); + add(new int[] {531}, "MK"); + add(new int[] {535}, "MT"); + add(new int[] {539}, "IE"); + add(new int[] {540,549}, "BE/LU"); + add(new int[] {560}, "PT"); + add(new int[] {569}, "IS"); + add(new int[] {570,579}, "DK"); + add(new int[] {590}, "PL"); + add(new int[] {594}, "RO"); + add(new int[] {599}, "HU"); + add(new int[] {600,601}, "ZA"); + add(new int[] {603}, "GH"); + add(new int[] {608}, "BH"); + add(new int[] {609}, "MU"); + add(new int[] {611}, "MA"); + add(new int[] {613}, "DZ"); + add(new int[] {616}, "KE"); + add(new int[] {618}, "CI"); + add(new int[] {619}, "TN"); + add(new int[] {621}, "SY"); + add(new int[] {622}, "EG"); + add(new int[] {624}, "LY"); + add(new int[] {625}, "JO"); + add(new int[] {626}, "IR"); + add(new int[] {627}, "KW"); + add(new int[] {628}, "SA"); + add(new int[] {629}, "AE"); + add(new int[] {640,649}, "FI"); + add(new int[] {690,695}, "CN"); + add(new int[] {700,709}, "NO"); + add(new int[] {729}, "IL"); + add(new int[] {730,739}, "SE"); + add(new int[] {740}, "GT"); + add(new int[] {741}, "SV"); + add(new int[] {742}, "HN"); + add(new int[] {743}, "NI"); + add(new int[] {744}, "CR"); + add(new int[] {745}, "PA"); + add(new int[] {746}, "DO"); + add(new int[] {750}, "MX"); + add(new int[] {754,755}, "CA"); + add(new int[] {759}, "VE"); + add(new int[] {760,769}, "CH"); + add(new int[] {770}, "CO"); + add(new int[] {773}, "UY"); + add(new int[] {775}, "PE"); + add(new int[] {777}, "BO"); + add(new int[] {779}, "AR"); + add(new int[] {780}, "CL"); + add(new int[] {784}, "PY"); + add(new int[] {785}, "PE"); + add(new int[] {786}, "EC"); + add(new int[] {789,790}, "BR"); + add(new int[] {800,839}, "IT"); + add(new int[] {840,849}, "ES"); + add(new int[] {850}, "CU"); + add(new int[] {858}, "SK"); + add(new int[] {859}, "CZ"); + add(new int[] {860}, "YU"); + add(new int[] {865}, "MN"); + add(new int[] {867}, "KP"); + add(new int[] {868,869}, "TR"); + add(new int[] {870,879}, "NL"); + add(new int[] {880}, "KR"); + add(new int[] {885}, "TH"); + add(new int[] {888}, "SG"); + add(new int[] {890}, "IN"); + add(new int[] {893}, "VN"); + add(new int[] {896}, "PK"); + add(new int[] {899}, "ID"); + add(new int[] {900,919}, "AT"); + add(new int[] {930,939}, "AU"); + add(new int[] {940,949}, "AZ"); + add(new int[] {955}, "MY"); + add(new int[] {958}, "MO"); + } + +} diff --git a/core/src/com/google/zxing/oned/UPCEANExtensionSupport.java b/core/src/com/google/zxing/oned/UPCEANExtensionSupport.java index 3076941f..f883566d 100644 --- a/core/src/com/google/zxing/oned/UPCEANExtensionSupport.java +++ b/core/src/com/google/zxing/oned/UPCEANExtensionSupport.java @@ -30,10 +30,8 @@ final class UPCEANExtensionSupport { private static final int[] CHECK_DIGIT_ENCODINGS = { 0x18, 0x14, 0x12, 0x11, 0x0C, 0x06, 0x03, 0x0A, 0x09, 0x05 }; - private static final int[][] SEPARATOR_PATTERNS = {{1,1}}; private final int[] decodeMiddleCounters = new int[4]; - private final int[] separatorCounters = new int[2]; private final StringBuffer decodeRowStringBuffer = new StringBuffer(); Result decodeRow(BitArray row, int rowOffset) throws NotFoundException { @@ -60,9 +58,6 @@ final class UPCEANExtensionSupport { counters[1] = 0; counters[2] = 0; counters[3] = 0; - int[] separatorCounters = this.separatorCounters; - separatorCounters[0] = 0; - separatorCounters[1] = 0; int end = row.getSize(); int rowOffset = startRange[1]; @@ -78,14 +73,6 @@ final class UPCEANExtensionSupport { lgPatternFound |= 1 << (4 - x); } // Read off separator - /* - try { - UPCEANReader.decodeDigit(row, separatorCounters, rowOffset, SEPARATOR_PATTERNS); - rowOffset += separatorCounters[0] + separatorCounters[1]; - } catch (NotFoundException nfe) { - break; - } - */ while (rowOffset < end && !row.get(rowOffset)) { rowOffset++; } diff --git a/core/src/com/google/zxing/oned/UPCEANReader.java b/core/src/com/google/zxing/oned/UPCEANReader.java index 6036157f..7b4ea5e4 100644 --- a/core/src/com/google/zxing/oned/UPCEANReader.java +++ b/core/src/com/google/zxing/oned/UPCEANReader.java @@ -23,6 +23,7 @@ import com.google.zxing.FormatException; import com.google.zxing.NotFoundException; import com.google.zxing.ReaderException; import com.google.zxing.Result; +import com.google.zxing.ResultMetadataType; import com.google.zxing.ResultPoint; import com.google.zxing.ResultPointCallback; import com.google.zxing.common.BitArray; @@ -93,10 +94,12 @@ public abstract class UPCEANReader extends OneDReader { private final StringBuffer decodeRowStringBuffer; private final UPCEANExtensionSupport extensionReader; + private final EANManufacturerOrgSupport eanManSupport; protected UPCEANReader() { decodeRowStringBuffer = new StringBuffer(20); extensionReader = new UPCEANExtensionSupport(); + eanManSupport = new EANManufacturerOrgSupport(); } static int[] findStartGuardPattern(BitArray row) throws NotFoundException { @@ -174,12 +177,13 @@ public abstract class UPCEANReader extends OneDReader { float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f; float right = (float) (endRange[1] + endRange[0]) / 2.0f; + BarcodeFormat format = getBarcodeFormat(); Result decodeResult = new Result(resultString, null, // no natural byte representation for these barcodes new ResultPoint[]{ new ResultPoint(left, (float) rowNumber), new ResultPoint(right, (float) rowNumber)}, - getBarcodeFormat()); + format); try { Result extensionResult = extensionReader.decodeRow(row, endRange[1]); @@ -187,6 +191,14 @@ public abstract class UPCEANReader extends OneDReader { } catch (ReaderException re) { // continue } + + if (BarcodeFormat.EAN_13.equals(format) || BarcodeFormat.UPC_A.equals(format)) { + String countryID = eanManSupport.lookupCountryIdentifier(resultString); + if (countryID != null) { + decodeResult.putMetadata(ResultMetadataType.POSSIBLE_COUNTRY, countryID); + } + } + return decodeResult; } diff --git a/core/test/src/com/google/zxing/oned/EANManufacturerOrgSupportTest.java b/core/test/src/com/google/zxing/oned/EANManufacturerOrgSupportTest.java new file mode 100644 index 00000000..de5c05f6 --- /dev/null +++ b/core/test/src/com/google/zxing/oned/EANManufacturerOrgSupportTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * 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. + */ + +package com.google.zxing.oned; + +import junit.framework.TestCase; + +/** + * Tests {@link EANManufacturerOrgSupport}. + * + * @author Sean Owen + */ +public final class EANManufacturerOrgSupportTest extends TestCase { + + public void testLookup() { + EANManufacturerOrgSupport support = new EANManufacturerOrgSupport(); + assertNull(support.lookupCountryIdentifier("472000")); + assertEquals("US/CA", support.lookupCountryIdentifier("000000")); + assertEquals("MO", support.lookupCountryIdentifier("958000")); + assertEquals("GB", support.lookupCountryIdentifier("500000")); + assertEquals("GB", support.lookupCountryIdentifier("509000")); + } + +}