From 0ba17ace6ff7815763a520e454f3a4918a8fc483 Mon Sep 17 00:00:00 2001 From: Miao_Spring <539943419@qq.com> Date: Tue, 28 Jan 2025 00:36:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E4=BA=8C=E7=BB=B4?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/tools/miaoQRGBCode.vue | 33 +++++++++------------- pages/tools/QRGB/scanner.vue | 47 +++++++++++++++---------------- 2 files changed, 35 insertions(+), 45 deletions(-) diff --git a/components/tools/miaoQRGBCode.vue b/components/tools/miaoQRGBCode.vue index 704a371..745816d 100644 --- a/components/tools/miaoQRGBCode.vue +++ b/components/tools/miaoQRGBCode.vue @@ -9,52 +9,45 @@ import QRCode from 'qrcode'; import { onMounted, ref, watchEffect } from 'vue'; const props = defineProps<{ - value: string + value: string | Uint8Array, + width?: number }>() -const width = ref(600) +const width = ref(props.width ?? 600) const canvasRefRGB = ref() -const generateQRCodeCanvasData = (data: string) => { +const generateQRCodeCanvasData = (data: Uint8Array) => { const canvas = document.createElement('canvas') canvas.width = width.value canvas.height = width.value const ctx = canvas.getContext('2d')! - QRCode.toCanvas(canvas, [{ data: new TextEncoder().encode(data), mode: 'byte' }], { + QRCode.toCanvas(canvas, [{ data, mode: 'byte' }], { width: width.value, }) const imageData = ctx.getImageData(0, 0, width.value, width.value) return imageData } -const paddingData = (data: string) => { - const b64Data = btoa(data) - if (b64Data.length % 3 === 0) { - return b64Data + '012' - } else if (b64Data.length % 3 === 1) { - return b64Data + '01' +const paddingData = (data: Uint8Array) => { + if(data.length % 3 === 0) { + return new Uint8Array([...data, 0, 1, 2]) + } else if(data.length % 3 === 1) { + return new Uint8Array([...data, 0, 1]) } else { - return b64Data + '0' + return new Uint8Array([...data, 0]) } } onMounted(() => { watchEffect(() => { - const padedData = paddingData(props.value) + const u8iData = props.value instanceof Uint8Array ? props.value : new TextEncoder().encode(props.value) + const padedData = paddingData(u8iData) const data = { r: padedData.slice(0, padedData.length / 3), g: padedData.slice(padedData.length / 3, padedData.length / 3 * 2), b: padedData.slice(padedData.length / 3 * 2, padedData.length) } - // console.log({ - // data, - // ECData: { - // r: new TextEncoder().encode(data.r), - // g: new TextEncoder().encode(data.g), - // b: new TextEncoder().encode(data.b) - // } - // }) const imgData = { r: generateQRCodeCanvasData(data.r), g: generateQRCodeCanvasData(data.g), diff --git a/pages/tools/QRGB/scanner.vue b/pages/tools/QRGB/scanner.vue index bb94da9..c2c231f 100644 --- a/pages/tools/QRGB/scanner.vue +++ b/pages/tools/QRGB/scanner.vue @@ -1,11 +1,11 @@ @@ -14,7 +14,7 @@ import jsQR from 'jsqr' import { ref, onMounted, onBeforeUnmount } from 'vue'; const emit = defineEmits<{ - onResult: [value: string] + onResult: [value: Uint8Array] }>() const scannerDisplayRef = ref() @@ -22,27 +22,26 @@ const testCtx = ref() const testCtxR = ref() const testCtxG = ref() const testCtxB = ref() -// const result = reactive([]) const res = ref('') let stream: MediaStream | null = null let timer: any | undefined = undefined -const unpaddingData = (data: string) => { - console.log(data) - let res: string - try { - if (data.endsWith('012')) { - res = atob(data.slice(0, data.length - 3)) - } else if (data.endsWith('01')) { - res = atob(data.slice(0, data.length - 2)) - } else { - res = atob(data.slice(0, data.length - 1)) - } - } catch { - return '' +const u8iEndWith = (data: Uint8Array, target: number[]) => { + for (let i = 0; i < target.length; i++) { + if (data[data.length - 1 - i] !== target[target.length - 1 - i]) return false + } + return true +} + +const unpaddingData = (data: Uint8Array): Uint8Array => { + if(u8iEndWith(data, [0, 1, 2])) { + return data.slice(0, data.length - 3) + } else if (u8iEndWith(data, [0, 1])) { + return data.slice(0, data.length - 2) + } else { + return data.slice(0, data.length - 1) } - return res } const binarization = ( @@ -59,7 +58,7 @@ const binarization = ( } // const scannerResult = new Set() -const getQRDataFromVideoFrame = (videoFrame: VideoFrame): string | undefined => { +const getQRDataFromVideoFrame = (videoFrame: VideoFrame): Uint8Array | undefined => { const canvas = testCtx.value! canvas.width = videoFrame.codedWidth canvas.height = videoFrame.codedHeight @@ -77,8 +76,8 @@ const getQRDataFromVideoFrame = (videoFrame: VideoFrame): string | undefined => for (let i = 0; i < imageData.data.length; i += 4) { const rgba = { r: binarization(imageData.data[i]), - g: binarization(imageData.data[i+1]), - b: binarization(imageData.data[i+2]), + g: binarization(imageData.data[i + 1]), + b: binarization(imageData.data[i + 2]), a: imageData.data[i + 3] } imageDataRGB.r.data[i] = rgba.r @@ -107,11 +106,9 @@ const getQRDataFromVideoFrame = (videoFrame: VideoFrame): string | undefined => const codeR = jsQR(imageDataRGB.r.data, imageDataRGB.r.width, imageDataRGB.r.height) const codeG = jsQR(imageDataRGB.g.data, imageDataRGB.g.width, imageDataRGB.g.height) const codeB = jsQR(imageDataRGB.b.data, imageDataRGB.b.width, imageDataRGB.b.height) - // console.log({ - // codeR, codeG, codeB - // }) if (!codeR || !codeG || !codeB) return undefined - const data = unpaddingData(codeR?.data + codeG?.data + codeB?.data) + const resBuffer = new Uint8Array([...codeR.binaryData, ...codeG.binaryData, ...codeB.binaryData]) + const data = unpaddingData(resBuffer) return data } @@ -126,7 +123,7 @@ const handleTrackProcessor = async (track: MediaStreamTrack) => { const frameFromCamera = result.value as VideoFrame; const data = getQRDataFromVideoFrame(frameFromCamera) if (data) { - res.value = data + res.value = new TextDecoder().decode(data) console.log(data) emit('onResult', data) }