xdola
xdola

Reputation: 567

ZPL: how to print in grayscale

I've a ZQ520 printer and I started learning ZPL from here.

I need to print some information in different style, to highlight important data. The problem is that I can't find the instruction to print in grayscale.

I'm searching something like this:

^XA ^FO50,50^ADN,18,10^FDBlack text^FS ^FO50,100^ADN,18,10^GS25^FDGrayscale text^FS ^XZ

Where ^GS means Gray Scale and not Graphic Symbol.

Upvotes: 0

Views: 2258

Answers (2)

mischl
mischl

Reputation: 33

ZPL does not offer a possibility to print in grayscale, this can only be reached by controlling the density of black pixels. for that, Dither is a method, especially the Flyod-Steinberg algorithm.

the necessary steps are:

  1. read in an image (grayscale or color)
  2. convert it to grayscale
  3. dither it to black and white only (number of colours, nc = 2)
  4. save it as image-2

here is the working python example:

# original script: https://scipython.com/blog/floyd-steinberg-dithering/

import numpy as np
from PIL import Image  # Pillow: https://pillow.readthedocs.io/en/stable/index.html
from os import path

folder = 'C:\\Users\\ml\\Desktop\\fs'
file = 'logo.png'
img_name = path.join(folder, file)

# Read in the image, convert to 8-bit greyscale.
img = Image.open(img_name)  # https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html
img = img.convert('L')  # https://pillow.readthedocs.io/en/stable/handbook/concepts.html#concept-modes
width, height = img.size

def get_new_val(old_val, nc):
    """
    Get the "closest" colour to old_val in the range [0,1] per channel divided
    into nc values.

    """

    return np.round(old_val * (nc - 1)) / (nc - 1)


def fs_dither(img, nc):
    """
    Floyd-Steinberg dither the image img into a palette with nc colours per
    channel.

    """

    arr = np.array(img, dtype=float) / 255

    for ir in range(height):
        for ic in range(width):
            # NB need to copy here for RGB arrays otherwise err will be (0,0,0)!
            old_val = arr[ir, ic].copy()
            new_val = get_new_val(old_val, nc)
            arr[ir, ic] = new_val
            err = old_val - new_val
            # In this simple example, we will just ignore the border pixels.
            if ic < width - 1:
                arr[ir, ic+1] += err * 7/16
            if ir < height - 1:
                if ic > 0:
                    arr[ir+1, ic-1] += err * 3/16
                arr[ir+1, ic] += err * 5/16
                if ic < width - 1:
                    arr[ir+1, ic+1] += err / 16

    carr = np.array(arr/np.max(arr, axis=(0,1)) * 255, dtype=np.uint8)
    return Image.fromarray(carr)


nc = 2  # two colours: black and white
dim = fs_dither(img, nc)
dim.save(path.join(folder, file.replace(".", "-{}.")).format(nc))  ## add a -2 to the file name

the script is maintained on github.
there is also an online work bench available to test it.

Upvotes: 0

banno
banno

Reputation: 1544

The ZQ520 does not support grayscale. If you are printing from a mobile device your best bet is to create a graphic with the gray text. You can then use the Zebra SDK to convert the bitmap to a form. The SDK will dither the image making it appear grayscale on the printer.

Upvotes: 0

Related Questions