Need Help With "data = webcamTexture.GetPixels32();"

I’m trying to get this QR reader to work with a UI Raw image but this line keeps throwing me an error:

data = webcamTexture.GetPixels32();

If I use the old on GUI method it works fine but I need it to work with a raw image on a canvas.

/*
* Copyright 2012 ZXing.Net 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.
*/

using System.Threading;

using UnityEngine;
using UnityEngine.UI;

using ZXing;
using ZXing.QrCode;

public class BarcodeCam : MonoBehaviour
{
    // Readout Text
    public Text ReadoutText;
    // Texture for encoding test
    public Texture2D encoded;

    public WebCamTexture camTexture;
    WebCamTexture webcamTexture;

    public RawImage rawimage;
    Color32[] data;

    private Thread qrThread;

    //private Color32[] c;
    public int W, H;

    private Rect screenRect;

    private bool isQuit;

    public string LastResult;
    private bool shouldEncodeNow;

    void OnGUI()
    {
        //GUI.DrawTexture(screenRect, camTexture, ScaleMode.ScaleToFit);
    }

    void OnEnable()
    {
        if (webcamTexture !=null)// camTexture != null)
        {
            //camTexture.Play();
            webcamTexture.Play();
            W = camTexture.width;
            H = camTexture.height;
        }
    }

    void OnDisable()
    {
        if (webcamTexture !=null )// camTexture != null)
        {
            //camTexture.Pause();
            webcamTexture.Pause();
        }
    }

    void OnDestroy()
    {
        qrThread.Abort();
        //camTexture.Stop();
        webcamTexture.Stop();
    }

    // It's better to stop the thread by itself rather than abort it.
    void OnApplicationQuit()
    {
        isQuit = true;
    }

    void Start()
    {
        WebCamTexture webcamTexture = new WebCamTexture();
        rawimage.texture = webcamTexture;
        rawimage.material.mainTexture = webcamTexture;
        webcamTexture.Play();
        data = new Color32[webcamTexture.width * webcamTexture.height];

       
        // ---------------------

        encoded = new Texture2D(256, 256);
        LastResult = "000";
        shouldEncodeNow = true;

        screenRect = new Rect(0, 0, W, H);

        //camTexture = new WebCamTexture();
        webcamTexture = new WebCamTexture();
        //camTexture.requestedHeight = H;//Screen.height; // 480;
        //camTexture.requestedWidth = W;//Screen.width; //640;

        webcamTexture.requestedHeight = H;//Screen.height; // 480;
        webcamTexture.requestedWidth = W;//Screen.width; //640;
        OnEnable();

        qrThread = new Thread(DecodeQR);
        qrThread.Start();
    }

    void Update()
    {
       
        if (data == null)
        {
            //c = camTexture.GetPixels32();
           data = webcamTexture.GetPixels32();

        }

        // encode the last found
        var textForEncoding = LastResult;
        // Display The Results
        ReadoutText.text = LastResult;
        if (shouldEncodeNow &&
            textForEncoding != null)
        {
            var color32 = Encode(textForEncoding, encoded.width, encoded.height);
            encoded.SetPixels32(color32);
            encoded.Apply();
            shouldEncodeNow = false;
        }
    }

    void DecodeQR()
    {
        // create a reader with a custom luminance source
        var barcodeReader = new BarcodeReader { AutoRotate = false, TryHarder = false };

        while (true)
        {
            if (isQuit)
                break;

            try
            {
                // decode the current frame
                var result = barcodeReader.Decode(data, W, H);
                if (result != null)
                {
                    // Display The Results
                    ReadoutText.text = LastResult;
                    LastResult = result.Text;
                    shouldEncodeNow = true;
                    print(result.Text);
                   
                }

                // Sleep a little bit and set the signal to get the next frame
                Thread.Sleep(200);
                data = null;
            }
            catch
            {
            }
        }
    }

    private static Color32[] Encode(string textForEncoding, int width, int height)
    {
        var writer = new BarcodeWriter
        {
            Format = BarcodeFormat.QR_CODE,
            Options = new QrCodeEncodingOptions
            {
                Height = height,
                Width = width
            }
        };
        return writer.Write(textForEncoding);
    }
}

Took me a little while to get it right, but I also added an electronic beep SFX for each time it scans the QR code

/*
* Copyright 2012 ZXing.Net 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.
*/

using System.Threading;

using UnityEngine;
using UnityEngine.UI;

using ZXing;
using ZXing.QrCode;

public class BarcodeCam : MonoBehaviour
{
    // Audio Beep
    public AudioClip beepClip;
    private AudioSource audioSource;


    // Readout Text
    public Text ReadoutText;
    // Texture for encoding test
    public Texture2D encoded;

    public WebCamTexture camTexture;
    //WebCamTexture webcamTexture;

    public RawImage rawimage;
    private Color32[] data;

    private Thread qrThread;

    public int W, H;

    private Rect screenRect;

    private bool isQuit;

    public string LastResult;
    private bool shouldEncodeNow;

    void OnGUI()
    {
       //GUI.DrawTexture(screenRect, camTexture, ScaleMode.ScaleToFit);
    }

    void OnEnable()
    {
        audioSource = GetComponent<AudioSource>();

        if (camTexture != null)
        {
            camTexture.Play();
            W = camTexture.width;
            H = camTexture.height;
        }
    }

    void OnDisable()
    {
        if (camTexture != null)
        {
            camTexture.Pause();
        }
    }

    void OnDestroy()
    {
        qrThread.Abort();
        camTexture.Stop();
    }

    // It's better to stop the thread by itself rather than abort it.
    void OnApplicationQuit()
    {
        isQuit = true;
    }

    void Start()
    {
       
        ////-----------------------------
        encoded = new Texture2D(256, 256);
        LastResult = "*** READY ***";
        shouldEncodeNow = true;

        screenRect = new Rect(0, 0, W, H);

        rawimage.texture = camTexture = new WebCamTexture();
        camTexture.requestedHeight = H;//Screen.height; // 800;
        camTexture.requestedWidth = W;//Screen.width; //600;

        camTexture.Play();
        //data = new Color32[camTexture.width * camTexture.height];
        data = new Color32[(camTexture.requestedWidth = W) * (camTexture.requestedHeight = H)];

        OnEnable();

        qrThread = new Thread(DecodeQR);
        qrThread.Start();
    }

    void Update()
    {
       
        if (data == null)
        {
            data = camTexture.GetPixels32(data);
            //camTexture.GetPixels32(data);
        }
       


        // encode the last found
        var textForEncoding = LastResult;
        // Display The Results
        ReadoutText.text = LastResult;
       
        if (shouldEncodeNow &&
            textForEncoding != null)
        {
            var color32 = Encode(textForEncoding, encoded.width, encoded.height);
            encoded.SetPixels32(color32);
            encoded.Apply();
            shouldEncodeNow = false;

            // Play Blip
            audioSource.clip = beepClip;
            audioSource.Play();
        }
    }

    void DecodeQR()
    {
        // create a reader with a custom luminance source
        var barcodeReader = new BarcodeReader { AutoRotate = false, TryHarder = false };

        while (true)
        {
            if (isQuit)
                break;

            try
            {
                // decode the current frame
                var result = barcodeReader.Decode(data, W, H);
                if (result != null)
                {
                    // Display The Results
                    ReadoutText.text = LastResult;
                    LastResult = result.Text;
                    shouldEncodeNow = true;
                    print(result.Text);
                   
                }

                // Sleep a little bit and set the signal to get the next frame
                Thread.Sleep(200);
                data = null;
            }
            catch
            {
            }
        }
    }

    private static Color32[] Encode(string textForEncoding, int width, int height)
    {
        var writer = new BarcodeWriter
        {
            Format = BarcodeFormat.QR_CODE,
            Options = new QrCodeEncodingOptions
            {
                Height = height,
                Width = width
            }
        };
        return writer.Write(textForEncoding);
    }
}

But at least I was able to get rid of that On GUI crap :wink:

1 Like