code: def _make_png(data, level=6):
      """Convert numpy array to PNG byte array.
  
      Parameters
      ----------
      data : numpy.ndarray
          Data must be (H, W, 3 | 4) with dtype = np.ubyte (np.uint8)
      level : int
          https://docs.python.org/2/library/zlib.html#zlib.compress
          An integer from 0 to 9 controlling the level of compression:
  
              * 1 is fastest and produces the least compression,
              * 9 is slowest and produces the most.
              * 0 is no compression.
  
          The default value is 6.
  
      Returns
      -------
      png : array
          PNG formatted array
      """
      # Eventually we might want to use ext/png.py for this, but this
      # routine *should* be faster b/c it's specialized for our use case
  
      def mkchunk(data, name):
          if isinstance(data, np.ndarray):
              size = data.nbytes
          else:
              size = len(data)
          chunk = np.empty(size + 12, dtype=np.ubyte)
          chunk.data[0:4] = np.array(size, ">u4").tobytes()
          chunk.data[4:8] = name.encode("ASCII")
          chunk.data[8 : 8 + size] = data
          # and-ing may not be necessary, but is done for safety:
          # https://docs.python.org/3/library/zlib.html#zlib.crc32
          chunk.data[-4:] = np.array(
              zlib.crc32(chunk[4:-4]) & 0xFFFFFFFF, ">u4"
          ).tobytes()
          return chunk
  
      if data.dtype != np.ubyte:
          raise TypeError("data.dtype must be np.ubyte (np.uint8)")
  
      dim = data.shape[2]  # Dimension
      if dim not in (3, 4):
          raise TypeError("data.shape[2] must be in (3, 4)")
  
      # www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html#C.IHDR
      if dim == 4:
          ctyp = 0b0110  # RGBA
      else:
          ctyp = 0b0010  # RGB
  
      # www.libpng.org/pub/png/spec/1.2/PNG-Structure.html
      header = b"\x89PNG\x0d\x0a\x1a\x0a"  # header
  
      h, w = data.shape[:2]
      depth = data.itemsize * 8
      ihdr = struct.pack("!IIBBBBB", w, h, depth, ctyp, 0, 0, 0)
      c1 = mkchunk(ihdr, "IHDR")
  
      # www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html#C.IDAT
      # insert filter byte at each scanline
      idat = np.empty((h, w * dim + 1), dtype=np.ubyte)
      idat[:, 1:] = data.reshape(h, w * dim)
      idat[:, 0] = 0
  
      comp_data = zlib.compress(idat, level)
      c2 = mkchunk(comp_data, "IDAT")
      c3 = mkchunk(np.empty((0,), dtype=np.ubyte), "IEND")
  
      # concatenate
      lh = len(header)
      png = np.empty(
          lh + c1.nbytes + c2.nbytes + c3.nbytes, dtype=np.ubyte
      )
      png.data[:lh] = header
      p = lh
  
      for chunk in (c1, c2, c3):
          png[p : p + len(chunk)] = chunk
          p += chunk.nbytes
  
      return png
  
file_path: vispy/vispy/io/image.py
imports: import struct
  import zlib
  import numpy
label_desc: Use image node_id 1 for calling a global function with example usage: _make_png(data, level) and returns: png, chunk