当前位置: 代码网 > it编程>编程语言>Javascript > JavaScript实现读取条码中的二进制数据

JavaScript实现读取条码中的二进制数据

2024年05月18日 Javascript 我要评论
条码是一种以机器可读的可视形式表示数据的方法。条码种类繁多,主要分为一维码和二维码。我们可以从条码获取二进制数据,并通过不同方法去读码。例如,在ean-13中,位于其右边的代码1110010代表数字0

条码是一种以机器可读的可视形式表示数据的方法。条码种类繁多,主要分为一维码和二维码。

我们可以从条码获取二进制数据,并通过不同方法去读码。例如,在ean-13中,位于其右边的代码1110010代表数字0。而qr码,它是二维的,可以存储更多的数据,有几种表示数据的模式:

输入模式模式标识最大字符数允许的字符,默认编码
仅数字17,0890、1、2、3、4、5、6、7、8、9
字母与数字24,2960-9、a-z(仅限大写)、空格、$、%、*、+、-、..、/、:
二进制/字节42,953iso/iec 8859-1
日语汉字/假名81,817shift jis x 0208
结构化追加3无限没有限定

ps:结构化追加(structured append)是一种将数据分到多个条码的模式。

在本文中,我们将创建一个用于读取条码二进制数据的javascript库,并重点处理qr码,因为这种码型有多种模式。

dynamsoft barcode reader会被用于读取条码。

新建项目

使用vite创建一个新的typescript项目:

npm create vite@latest barcodedatareader -- --template vanilla-ts

编写定义

为读取条码的二进制数据定义几个接口和一个枚举。

定义barcodedetail接口:

export interface barcodedetail {
  mode?:number; //the data encoding mode
  model?:number; //number of models
  errorcorrectionlevel?:number;
  columns?:number; //the column count
  rows?:number; //the row count
  page?:number; //position of the particular code in structured append codes
  totalpage?:number; //total number of structured append codes
  paritydata?:number; //a value obtained by xoring byte by byte the ascii/jis values of all the original input data before division into symbol blocks.
  version?:number; //the version of the code.
}

定义barcode接口:

export interface barcode {
  bytes:uint8array;
  details:barcodedetail;
  barcodetype?:string;
}

二进制数据存储为uint8array

定义readingresult接口:

export interface readingresult {
  text?:string;
  img?:htmlimageelement;
  blob?:blob;
}

我们可以得到纯文本、html图像元素或blob这三种类型的结果。

类型需要在datatype中指定。

export enum datatype {
  text = 0,
  image = 1,
  unknown = 2
}

创建一个读取二进制数据的类

使用以下模板创建一个新的barcodedatareader.ts文件:

export class barcodedatareader{
  async read(barcodes:barcode[],datatype:datatype):promise<readingresult[]>{
    if (barcodes.length == 0) {
      throw new error("no barcodes given");
    }
    let results:readingresult[] = [];
    return results;
  }
}

根据不同模式读取二进制数据。

async read(barcodes:barcode[],datatype:datatype):promise<readingresult[]>{
  if (barcodes.length == 0) {
    throw new error("no barcodes given");
  }
  let results:readingresult[] = [];
  const mode = barcodes[0].details.mode;
  if (mode == 1) {
    results = this.readnumericbarcodes(barcodes);
  }else if (mode == 2) {
    results = this.readalphanumericbarcodes(barcodes);
  }else if (mode == 4) {
    results = await this.readbyteencodingbarcodes(barcodes,datatype);
  }else if (mode == 8) {
    results = this.readkanjibarcodes(barcodes);
  }else if (mode == 3) {
    results = await this.readstructuredappendbarcodes(barcodes,datatype);
  }else {
    results = await this.readbyteencodingbarcodes(barcodes,datatype.text);
  }
  return results;
}

实现对数字、字母与数字和日文汉字模式的读取。这三种模式的数据都是纯文本,它们可以共享类似的逻辑。

private readalphanumericbarcodes(barcodes:barcode[]):readingresult[]{
  return this.decodetext(barcodes,"ascii");
}

private readnumericbarcodes(barcodes:barcode[]):readingresult[]{
  return this.decodetext(barcodes,"ascii");
}

private readkanjibarcodes(barcodes:barcode[]):readingresult[]{
  return this.decodetext(barcodes,"shift-jis");
}

private decodetext(barcodes:barcode[],encoding:string){
  let results:readingresult[] = [];
  for (let index = 0; index < barcodes.length; index++) {
    const barcode = barcodes[index];
    const decoder = new textdecoder(encoding);
    const text = decoder.decode(barcode.bytes);
    let result = {
      text:text
    }
    results.push(result);
  }
  return results;
}

以字节模式读取数据。

由于字节模式下的数据类型未知,我们需要根据用户指定的数据类型获取读取结果。

如果数据类型是文本,我们需要检测编码。这里使用chardet库进行检测。

private async readbyteencodingbarcodes(barcodes:barcode[],datatype:datatype):promise<readingresult[]>{
  let results:readingresult[] = [];
  for (let index = 0; index < barcodes.length; index++) {
    const barcode = barcodes[index];
    let result:readingresult = await this.getresultbasedondatatype(barcode.bytes,datatype);
    results.push(result);
  }
  return results;
}

async getresultbasedondatatype(data:uint8array,datatype:datatype) {
  let result:readingresult;
  if (datatype == datatype.text) {
    const charset = chardet.analyse(data);
    const decoder = new textdecoder(charset[0].name);
    const text = decoder.decode(data);
    result = {
      text:text
    }
  }else if (datatype == datatype.image) {
    const img = await this.getimagefromuint8array(data);
    result = {
      img:img
    }
  }else{
    result = {
      blob:this.getblobfromuint8array(data)
    }
  }
  return result;
}

getblobfromuint8array(data:uint8array) {
  return new blob([data]);
}
getimagefromuint8array(data:uint8array):promise<htmlimageelement>{
  return new promise<htmlimageelement>((resolve, reject) => {
    const img = document.createelement("img");  
    const blob = this.getblobfromuint8array(data);
    img.onload = function(){
      resolve(img);
    }
    img.onerror = function(error) {
      console.error(error);
      reject(error);
    }
    img.src = url.createobjecturl(blob);
    console.log(img.src)
  })
}

以结构化追加模式读取数据。

需要根据页码对条码进行排序,将多个码的数据合并成一个unit8array,然后得到结果。

private async readstructuredappendbarcodes(barcodes:barcode[],datatype:datatype):promise<readingresult[]>{
  let results:readingresult[] = [];
  barcodes.sort((a, b) => (a.details.page ?? 0) - (b.details.page ?? 0))
  let concateddata:uint8array = new uint8array();
  for (let index = 0; index < barcodes.length; index++) {
    const barcode = barcodes[index];
    let merged = new uint8array(barcode.bytes.length + concateddata.length);
    merged.set(concateddata);
    merged.set(barcode.bytes, concateddata.length);
    concateddata = merged;
  }
  let result = await this.getresultbasedondatatype(concateddata,datatype);
  results.push(result);
  return results;
}

读取测试

然后,我们可以更新index.html,使用dynamsoft barcode reader读取qr码,并使用我们编写的库读取二进制数据。

以下是基本代码:

let router = await dynamsoft.cvr.capturevisionrouter.createinstance();
//read barcodes from an image
let result = await router.capture(document.getelementbyid("image"),"readbarcodes_balance");
let datatype = document.getelementbyid("datatypeselect").selectedindex;
let barcodes = [];
for (let index = 0; index < result.items.length; index++) {
  const item = result.items[index];
  if (item.type === dynamsoft.core.enumcapturedresultitemtype.crit_barcode) {
    let data = new uint8array(item.bytes.length);
    data.set(item.bytes);
    let barcode = {
      bytes:data,
      details:item.details
    }
    barcodes.push(barcode);
  }
}

let results = await datareader.read(barcodes,datatype)
console.log(results);

可以访问在线演示进行试用。

如果手头没有二维码,可以使用此文中的二维码和二维码生成器。

下面是读取两个二维码的测试截图,一张图片被编码在这两个二维码中:

打包为库

为了便于使用,我们可以将其作为库发布到npm上。

安装devdependencies

npm install -d @types/node vite-plugin-dts

创建一个新的vite.config.ts文件:

// vite.config.ts
import { resolve } from 'path';
import { defineconfig } from 'vite';
import dts from 'vite-plugin-dts';
// https://vitejs.dev/guide/build.html#library-mode
export default defineconfig({
  build: {
    lib: {
      entry: resolve(__dirname, 'src/index.ts'),
      name: 'barcode-data-reader',
      filename: 'barcode-data-reader',
    },
  },
  plugins: [dts()],
});

将我们的包的入口点添加到package.json

{
  "main": "./dist/barcode-data-reader.umd.cjs",
  "module": "./dist/barcode-data-reader.js",
  "types": "./dist/index.d.ts",
  "exports": {
    "import": {
      "types": "./dist/index.d.ts",
      "default": "./dist/barcode-data-reader.js"
    },
    "require": {
      "types": "./dist/index.d.ts",
      "default": "./dist/barcode-data-reader.umd.cjs"
    }
  },
  "files": [
    "dist/*.css",
    "dist/*.js",
    "dist/*.cjs",
    "dist/*.d.ts"
  ]
}

运行npm run build。然后,我们可以在dist文件夹中看到打包好的文件。

源代码

欢迎下载源代码并尝试使用:

github.com/tony-xlh/barcode-data-reader

以上就是javascript实现读取条码中的二进制数据的详细内容,更多关于javascript读取条码二进制数据的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com