Extract data from a QR code in Elixir

by Atul Bhosale,

After I had finished working on writing a QR code generator using Elixir for one of our clients, there was a requirement to extract the data from a QR code and storing it. This post is about how I learned to extract the data from a QR code in Elixir.

I came across zbar while searching for a tool to read a QR code. Since I will be using this tool to read the QR code image I will have to use System.cmd() in my code to run the zbar binary.

	defmodule Sample do
	  def qr_string(image_path) do
	    System.cmd("zbarimg", [image_path], stderr_to_stdout: true)
	  end
	end

When the stderr_to_stdout option is set to true, the error details will be included in the tuple returned by Sysmtem.cmd.

I generated a QR code with Hello world as the data.

screenshot1

When I run the above code I get the following:

screenshot1

I just need the QR data i.e. Hello world in this case, but it returns a tuple with first value as string & second as 0. I was curious to know why 0 is returned.

I tried scanning an invalid QR code image like the Codemancers logo.

screenshot1
screenshot1

Notice that now it returns 4. For invalid or non-QR code images, the zbarimg library will return 4.

what about an invalid file type?

screenshot1

We can extract the data for 0, return "No QR code present" for 4 and return "Invalid file" for anything else.

    defmodule Sample

      require Logger

      def qr_string(image_path) do
        case System.cmd("zbarimg", [image_path], stderr_to_stdout: true) do
          {data, 0} ->
            data

          {data, 4} ->
            raise Logger.info("No QR code present. msg: #{data}")

          {data, _} ->
            raise Logger.info("Invalid file. msg: #{data}")
        end
      end
    end

We still need to extract the QR code data from the string.

screenshot1

We can split the string & find the data.

screenshot1

I came across <> operator which can be used for string pattern matching, using which I could find the data in the string.

screenshot1

The existing code can be updated to:

    case System.cmd("zbarimg", [image_path], stderr_to_stdout: true) do

      {data, 0} ->
        "QR-Code:" <> result =
          data
          |> String.split("\n")
          |> List.first()

        result

      {data, 4} ->
        raise Logger.info("No QR code present. msg: #{data}")

      {data, _} ->
        raise Logger.info("Invalid file. msg: #{data}")
    end

I was able to extract the QR code data from a QR code image. Following is the screenshot of the data extracted from a QR code image.

screenshot1

Update: I received a recommendation about parsing QR code data from Antonin Kral, which is as follows:

In case the data stored in QR code consists of multiple lines, its recommended to use --xml option while using zbarimg

screenshot1

The Elixir code will be:

    args = ["--xml", image_path]
    System.cmd("zbarimg", args, stderr_to_stdout: true)

Note: In our client's requirement, the QR code data didn't span multiple lines hence I haven't used --xml option in my examples.

More articles

Understanding the Rails Asset Pipeline

A comprehensive guide to understanding the Rails Asset Pipeline, its features, and its role in modern web development.

Read more

Next.js 15

Explore the caching strategy updates introduced in Next.js 15

Read more

Ready to Build Something Amazing?

Codemancers can bring your vision to life and help you achieve your goals