Zxing Crop video to scan barcode

412 Views Asked by At

I create a project to scan a barcode, but on mobil or webCam the frame is too big. I want crop it. I read lot of thing about, apparently already implemented function... but I don't

<!DOCTYPE html>

<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@("@")quasar/extras/material-icons/material-icons.css">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/ionicons@("@")4.0.0/dist/css/ionicons.min.css" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/animate.css@("@")3.5.2/animate.min.css" />

<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/quasar.min.css" />

<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/quasar.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/icon-set/ionicons-v4.umd.prod.js"></script>

<script type="text/javascript" src="https://unpkg.com/@("@")zxing/library@latest/umd/index.min.js"></script>
</head>
<body>
<script>
    function cropping(canvas) {
        const cameraCanvasImageWidth = canvas.width;
        const cameraCanvasImageHeight = canvas.height;
        const videoElementHeight = (document.querySelector('zxing-scanner video')).offsetHeight;
        const videoElementWidth = (document.querySelector('zxing-scanner video')).offsetWidth;
        let factor = 1;
        if (videoElementWidth > videoElementHeight) {
            factor = cameraCanvasImageWidth / videoElementWidth;
        } else {
            factor = cameraCanvasImageHeight / videoElementHeight;
        }

        const width = Math.floor((this.squareShape ? 250 : 450) * factor);
        const height = Math.floor((this.squareShape ? 250 : 200) * factor);

        const left = (cameraCanvasImageWidth - width) / 2;
        const top = (cameraCanvasImageHeight - height) / 2;

        const croppedCanvas = document.createElement('canvas');
        croppedCanvas.width = width;
        croppedCanvas.height = height;
        const croppedCanvasContext = croppedCanvas.getContext('2d');
        croppedCanvasContext.rect(0, 0, width, height);
        croppedCanvasContext.fillStyle = 'white';
        croppedCanvasContext.fill();
        croppedCanvasContext.drawImage(canvas, left, top, width, height, 0, 0, width, height);

        // These lines can be used to show the cropped part of the image stream that is used
        // to find the code and check if the highlighted area matches the cropped image
        document.getElementById('croppedSvg').innerHTML = '';
        const span = document.createElement('span');
        span.textContent = `${cameraCanvasImageWidth} x ${cameraCanvasImageHeight} | ${videoElementWidth} x ${videoElementHeight}`;
        span.style.position = 'absolute';
        span.style.right = `0`;
        span.style.color = 'white';
        span.style.display = 'block';
        document.getElementById('croppedSvg').appendChild(span);
        croppedCanvas.style.marginTop = '20px';
        croppedCanvas.style.transform = `scale(1)`;
        croppedCanvas.style.transformOrigin = `right top`;
        document.getElementById('croppedSvg').appendChild(croppedCanvas);

        let luminanceSource = new HTMLCanvasElementLuminanceSource(croppedCanvas); // .invert() to support inverted codes

        const hybridBinarizer = new HybridBinarizer(luminanceSource);

        return new BinaryBitmap(hybridBinarizer);
    };
    var mixin = {
        data: function () {
            return {
                selectedDeviceId: '', lstcams: [], result: '', codeReader: null
            };
        },
        methods: {
            openWebCam: function () {
                const hints = new Map();
                const enabledFormats = [
                    // ...ALL_FORMATS_WHICH_YOU_WANT_TO_ENABLE https://github.com/zxing-js/library/blob/master/src/core/BarcodeFormat.ts
                    ZXing.BarcodeFormat.CODE_39,ZXing.BarcodeFormat.EAN_13
                ];
                hints.set(ZXing.DecodeHintType.POSSIBLE_FORMATS, enabledFormats);
                this.codeReader = new ZXing.BrowserMultiFormatReader(hints);
                //this.codeReader.createBinaryBitmapFromCanvas = cropping();
                this.codeReader.listVideoInputDevices()
                    .then((videoInputDevices) => {
                        this.selectedDeviceId = videoInputDevices[0].deviceId;
                        if (videoInputDevices.length >= 1) { videoInputDevices.forEach((element) => { this.lstcams.push({ libelle: element.label, id: element.deviceId }); }); }
                    })
                    .catch((err) => {
                        //console.error(err)
                    });
                this.codeReader.decodeFromVideoDevice(this.selectedDeviceId, 'video', (result, err) => {
                    if (result && this.result.indexOf(result.text) == -1) { this.result += result.text + "\n"; }
                    if (err && !(err instanceof ZXing.NotFoundException)) this.result = err;
                });
            },
            CloseWebCam: function () { this.codeReader.reset(); this.result = '';  },
            
        }
    };

</script>
<div id="q-app">
    <div>
        <q-btn color="primary" flat label="Scanne" padding="xs" v-on:click="openWebCam()"></q-btn>
        <q-btn color="secondary" flat label="Arrêt" padding="xs" v-on:click="CloseWebCam()"></q-btn>
    </div>
    <div class="row">
        <div class="col-xs-12 col-md-6">
            <video id="video" style="border: 1px solid gray; min-height: 100%; min-width: 100%; width: auto; height: auto; margin: 0; padding: 0;" willreadfrequently="true"></video>
        </div>
    </div>
    <q-input class="col-xs-12 col-md-6" type="textarea" dense v-model="result" label="Résultat *">
        <template v-if="result" v-slot:append tabindex="-1">
            <q-icon name="cancel" v-on:click.stop="result = '' " class="cursor-pointer" />
        </template>
    </q-input>

</div>
<script>
    const app = Vue.createApp({ mixins: [mixin] });
    app.use(Quasar, {
        framework: {
            cssAddon: true,
            plugins: ['Notify', 'LocalStorage', 'SessionStorage'],
            config: {
                notify: {
                    position: 'top-right',
                    timeout: 2500,
                    textColor: 'white',
                    actions: [{ icon: 'close', color: 'white' }]
                }
            }
        }
    });
    app.mount('#q-app')
</script>

I see a crop function in zxing js file but don't know how to call it I read too this link but I don't see how to adpate it. Perhaps I take a bad way ??

Thanks for your help

0

There are 0 best solutions below