public static long determineGbPalette(long[] colors) {
    long minCosts = Long.MAX_VALUE;
    long minCostPalette = 0;
    int minCostMethod = -1;

    // Median Cut
    {
      long mcPalette = MedianCut.calculateGbPalette(colors);
      long mcPaletteCost = ColorUtil.getCosts(colors, mcPalette);
      long mcKmPalette = KMeans.kMeans(mcPalette, colors);
      long mcKmPaletteCost = ColorUtil.getCosts(colors, mcKmPalette);
      if (mcKmPaletteCost < minCosts) {
        minCosts = mcKmPaletteCost;
        minCostPalette = mcKmPalette;
        minCostMethod = 2;
      }
      if (mcPaletteCost < minCosts) {
        minCosts = mcPaletteCost;
        minCostPalette = mcPalette;
        minCostMethod = 3;
      }
    }

    // FourPalette
    {
      long fcPalette = FourPalette.calculateGbPalette(colors);
      long fcPaletteCost = ColorUtil.getCosts(colors, fcPalette);
      long fcKmPalette = KMeans.kMeans(fcPalette, colors);
      long fcKmPaletteCost = ColorUtil.getCosts(colors, fcKmPalette);
      if (fcKmPaletteCost < minCosts) {
        minCosts = fcKmPaletteCost;
        minCostPalette = fcKmPalette;
        minCostMethod = 0;
      }
      if (fcPaletteCost < minCosts) {
        minCosts = fcPaletteCost;
        minCostPalette = fcPalette;
        minCostMethod = 1;
      }
    }

    // Random
    Random random = new Random();
    for (int i = 0; i < 100; i++) {
      long rPalette = random.nextLong() & 0x7fff7fff7fff7fffL;
      long rPaletteCost = ColorUtil.getCosts(colors, rPalette);
      long rKmPalette = KMeans.kMeans(rPalette, colors);
      long rKmPaletteCost = ColorUtil.getCosts(colors, rKmPalette);
      if (rKmPaletteCost < minCosts) {
        minCosts = rKmPaletteCost;
        minCostPalette = rKmPalette;
        minCostMethod = 4;
      }
      if (rPaletteCost < minCosts) {
        minCosts = rPaletteCost;
        minCostPalette = rPalette;
        minCostMethod = 5;
      }
    }

    chosenMethodCounter[minCostMethod]++;
    return minCostPalette;
  }