docs: def write_pam(matrix, version, out, scale=1, border=None, color='#000',
                background='#fff'):
      """\
      Serializes the matrix as `PAM <http://netpbm.sourceforge.net/doc/pam.html>`_
      image.
  
      :param matrix: The matrix to serialize.
      :param int version: The (Micro) QR code version
      :param out: Filename or a file-like object supporting to write binary data.
      :param scale: Indicates the size of a single module (default: 1 which
              corresponds to 1 x 1 pixel per module).
      :param int border: Integer indicating the size of the quiet zone.
              If set to ``None`` (default), the recommended border size
              will be used (``4`` for QR Codes, ``2`` for a Micro QR Codes).
      :param color: Color of the modules (default: black). The
              color can be provided as ``(R, G, B)`` tuple, as web color name
              (like "red") or in hexadecimal format (``#RGB`` or ``#RRGGBB``).
      :param background: Optional background color (default: white).
              See `color` for valid values. In addition, ``None`` is
              accepted which indicates a transparent background.
      """
      def invert_row_bits(row):
          """\
          Inverts the row bits 0 -> 1, 1 -> 0
          """
          return bytearray([b ^ 0x1 for b in row])
  
      def row_to_color_values(row, colours):
          return b''.join([colours[b] for b in row])
  
      if not color:
          raise ValueError('Invalid stroke color "{0}"'.format(color))
      row_iter = matrix_iter(matrix, version, scale, border)
      width, height = get_symbol_size(version, scale=scale, border=border)
      depth, maxval, tuple_type = 1, 1, 'BLACKANDWHITE'
      transparency = False
      stroke_color = colors.color_to_rgb_or_rgba(color, alpha_float=False)
      bg_color = colors.color_to_rgb_or_rgba(background, alpha_float=False) if background is not None else None
      colored_stroke = not (colors.color_is_black(stroke_color) or colors.color_is_white(stroke_color))
      if bg_color is None:
          tuple_type = 'GRAYSCALE_ALPHA' if not colored_stroke else 'RGB_ALPHA'
          transparency = True
          bg_color = colors.invert_color(stroke_color[:3])
          bg_color += (0,)
          if len(stroke_color) != 4:
              stroke_color += (255,)
      elif colored_stroke or not (colors.color_is_black(bg_color) or colors.color_is_white(bg_color)):
          tuple_type = 'RGB'
      is_rgb = tuple_type.startswith('RGB')
      colours = None
      if not is_rgb and transparency:
          depth = 2
          colours = (b'\x01\x00', b'\x00\x01')
      elif is_rgb:
          maxval = max(chain(stroke_color, bg_color))
          depth = 3 if not transparency else 4
          fmt = '>{0}B'.format(depth).encode('ascii')
          colours=(pack(fmt, *bg_color), pack(fmt, *stroke_color))
      row_filter = invert_row_bits if colours is None else partial(row_to_color_values, colours=colours)
      with writable(out, 'wb') as f:
          write = f.write
          write('P7\n'
                '# Created by {0}\n'
                'WIDTH {1}\n'
                'HEIGHT {2}\n'
                'DEPTH {3}\n'
                'MAXVAL {4}\n'
                'TUPLTYPE {5}\n'
                'ENDHDR\n'.format(CREATOR, width, height, depth, maxval, tuple_type).encode('ascii'))
          for row in row_iter:
              write(row_filter(row))