docs: def extract_colors(
          filename_or_img, min_saturation=config.MIN_SATURATION,
          min_distance=config.MIN_DISTANCE, max_colors=config.MAX_COLORS,
          min_prominence=config.MIN_PROMINENCE, n_quantized=config.N_QUANTIZED):
      """
      Determine what the major colors are in the given image.
      """
      if Image.isImageType(filename_or_img):
          im = filename_or_img
      else:
          im = Image.open(filename_or_img)
  
      # get point color count
      if im.mode != 'RGB':
          im = im.convert('RGB')
      im = autocrop(im, config.WHITE)  # assume white box
      im = im.convert(
          'P', palette=Image.ADAPTIVE, colors=n_quantized).convert('RGB')
      dist = Counter({color: count for count, color
                      in im.getcolors(n_quantized)})
      n_pixels = mul(*im.size)
  
      # aggregate colors
      to_canonical = {config.WHITE: config.WHITE, config.BLACK: config.BLACK}
      aggregated = Counter({config.WHITE: 0, config.BLACK: 0})
      sorted_cols = sorted(dist.items(), key=itemgetter(1), reverse=True)
      for c, n in sorted_cols:
          if c in aggregated:
              # exact match!
              aggregated[c] += n
          else:
              d, nearest = min((distance(c, alt), alt) for alt in aggregated)
              if d < min_distance:
                  # nearby match
                  aggregated[nearest] += n
                  to_canonical[c] = nearest
              else:
                  # no nearby match
                  aggregated[c] = n
                  to_canonical[c] = c
  
      # order by prominence
      colors = sorted(
          [Color(c, n / float(n_pixels)) for c, n in aggregated.items()],
          key=attrgetter('prominence'), reverse=True)
  
      colors, bg_color = detect_background(im, colors, to_canonical)
  
      # keep any color which meets the minimum saturation
      sat_colors = [c for c in colors if meets_min_saturation(c, min_saturation)]
      if bg_color and not meets_min_saturation(bg_color, min_saturation):
          bg_color = None
      if sat_colors:
          colors = sat_colors
      else:
          # keep at least one color
          colors = colors[:1]
  
      # keep any color within 10% of the majority color
      color_list = []
      color_count = 0
  
      for color in colors:
          if color.prominence >= colors[0].prominence * min_prominence:
              color_list.append(color)
              color_count += 1
  
          if color_count >= max_colors:
              break
  
      return Palette(color_list, bg_color)