public static Color blend(Color base, Color mixin) {
    float[] baseC = base.getRGBColorComponents(null);
    float[] mixinC = mixin.getRGBColorComponents(null);

    float red = clamp(baseC[0] + mixinC[0]);
    float green = clamp(baseC[1] + mixinC[1]);
    float blue = clamp(baseC[2] + mixinC[2]);
    return new Color(red, green, blue);
  }
 /**
  * Parse a color given with the cmyk() function.
  *
  * @param value the complete line
  * @return a color if possible
  * @throws PropertyException if the format is wrong.
  */
 private static Color parseAsCMYK(String value) throws PropertyException {
   Color parsedColor;
   int poss = value.indexOf("(");
   int pose = value.indexOf(")");
   if (poss != -1 && pose != -1) {
     value = value.substring(poss + 1, pose);
     String[] args = value.split(",");
     try {
       if (args.length != 4) {
         throw new PropertyException("Invalid number of arguments: cmyk(" + value + ")");
       }
       float cyan = parseComponent1(args[0], value);
       float magenta = parseComponent1(args[1], value);
       float yellow = parseComponent1(args[2], value);
       float black = parseComponent1(args[3], value);
       float[] comps = new float[] {cyan, magenta, yellow, black};
       Color cmykColor = DeviceCMYKColorSpace.createCMYKColor(comps);
       float[] rgbComps = cmykColor.getRGBColorComponents(null);
       parsedColor =
           new ColorWithAlternatives(
               rgbComps[0], rgbComps[1], rgbComps[2], new Color[] {cmykColor});
     } catch (RuntimeException re) {
       throw new PropertyException(re);
     }
   } else {
     throw new PropertyException("Unknown color format: " + value + ". Must be cmyk(c,m,y,k)");
   }
   return parsedColor;
 }
 private static Color toSRGBColor(Color color) {
   float[] comps;
   ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
   comps = color.getRGBColorComponents(null);
   float[] allComps = color.getComponents(null);
   float alpha = allComps[allComps.length - 1]; // Alpha is on last component
   return new Color(sRGB, comps, alpha);
 }
Exemple #4
0
  public static String makeSetRGBColorCommand(Color color) {
    float[] rgbColorComponents = new float[3];
    color.getRGBColorComponents(rgbColorComponents);

    float r = rgbColorComponents[0];
    float g = rgbColorComponents[1];
    float b = rgbColorComponents[2];
    return r + " " + g + " " + b + " setrgbcolor" + "\n";
  }
  /**
   * Draw the label's text. This method assumes that the text renderer context has already been set
   * up.
   *
   * @param textRenderer renderer to use.
   */
  protected void doDrawText(TextRenderer textRenderer) {
    Color color = this.material.getDiffuse();
    Color backgroundColor = this.computeBackgroundColor(color);
    float opacity = (float) this.getOpacity();

    int x = this.screenPoint.x;
    int y = this.screenPoint.y;

    float[] compArray = new float[3];
    if (AVKey.TEXT_EFFECT_SHADOW.equals(this.effect) && backgroundColor != null) {
      backgroundColor.getRGBColorComponents(compArray);

      textRenderer.setColor(compArray[0], compArray[1], compArray[2], opacity);
      this.drawMultiLineText(textRenderer, x + 1, y - 1);
    }

    color.getRGBColorComponents(compArray);
    textRenderer.setColor(compArray[0], compArray[1], compArray[2], opacity);
    this.drawMultiLineText(textRenderer, x, y);
  }
  public static Color average(Color... colors) {
    float[] rgb = new float[3];
    float mult = 1.0f / colors.length;
    for (Color c : colors) {
      float[] cc = c.getRGBColorComponents(null);
      rgb[0] += cc[0] * mult;
      rgb[1] += cc[1] * mult;
      rgb[2] += cc[2] * mult;
    }

    return new Color(rgb[0], rgb[1], rgb[2]);
  }
  /**
   * Set the degree of transparency of the background color.
   *
   * @param transparency The alpha value between 0.0 and 1.0.
   */
  public void setTransparency(float transparency) {
    this.transparency = transparency;

    float[] colorComponents = new float[4];
    colorComponents = color.getRGBColorComponents(colorComponents);

    Color foregroundColor =
        new Color(colorComponents[0], colorComponents[1], colorComponents[2], transparency);
    this.setForeground(foregroundColor);

    repaint();
  }
  /**
   * Convert a RGB Color to it corresponding HSL values.
   *
   * @return an array containing the 3 HSL values.
   */
  public static float[] fromRGB(Color color) {
    //  Get RGB values in the range 0 - 1

    float[] rgb = color.getRGBColorComponents(null);
    float r = rgb[0];
    float g = rgb[1];
    float b = rgb[2];

    //	Minimum and Maximum RGB values are used in the HSL calculations

    float min = Math.min(r, Math.min(g, b));
    float max = Math.max(r, Math.max(g, b));

    //  Calculate the Hue

    float h = 0;

    if (max == min) h = 0;
    else if (max == r) h = ((60 * (g - b) / (max - min)) + 360) % 360;
    else if (max == g) h = (60 * (b - r) / (max - min)) + 120;
    else if (max == b) h = (60 * (r - g) / (max - min)) + 240;

    //  Calculate the Luminance

    float l = (max + min) / 2;
    // System.out.println(max + " : " + min + " : " + l);

    //  Calculate the Saturation

    float s = 0;

    if (max == min) s = 0;
    else if (l <= .5f) s = (max - min) / (max + min);
    else s = (max - min) / (2 - max - min);

    return new float[] {h, s * 100, l * 100};
  }
Exemple #9
0
 public VLine(double x, double y0, double y1, Color color) {
   this.x = (int) x + 0.5;
   this.y0 = (int) y0 + 0.5;
   this.y1 = (int) y1 + 0.5;
   this.color = color.getRGBColorComponents(null);
 }
  /**
   * Parse a color specified using the fop-rgb-icc() function.
   *
   * @param value the function call
   * @return a color if possible
   * @throws PropertyException if the format is wrong.
   */
  private static Color parseAsFopRgbIcc(FOUserAgent foUserAgent, String value)
      throws PropertyException {
    Color parsedColor;
    int poss = value.indexOf("(");
    int pose = value.indexOf(")");
    if (poss != -1 && pose != -1) {
      String[] args = value.substring(poss + 1, pose).split(",");

      try {
        if (args.length < 5) {
          throw new PropertyException("Too few arguments for rgb-icc() function");
        }

        // Set up fallback sRGB value
        Color sRGB = parseFallback(args, value);

        /* Get and verify ICC profile name */
        String iccProfileName = args[3].trim();
        if (iccProfileName == null || "".equals(iccProfileName)) {
          throw new PropertyException("ICC profile name missing");
        }
        ColorSpace colorSpace = null;
        String iccProfileSrc = null;
        if (isPseudoProfile(iccProfileName)) {
          if (CMYK_PSEUDO_PROFILE.equalsIgnoreCase(iccProfileName)) {
            colorSpace = ColorSpaces.getDeviceCMYKColorSpace();
          } else if (SEPARATION_PSEUDO_PROFILE.equalsIgnoreCase(iccProfileName)) {
            colorSpace = new NamedColorSpace(args[5], sRGB, SEPARATION_PSEUDO_PROFILE, null);
          } else {
            assert false : "Incomplete implementation";
          }
        } else {
          /* Get and verify ICC profile source */
          iccProfileSrc = args[4].trim();
          if (iccProfileSrc == null || "".equals(iccProfileSrc)) {
            throw new PropertyException("ICC profile source missing");
          }
          iccProfileSrc = unescapeString(iccProfileSrc);
        }
        /* ICC profile arguments */
        int componentStart = 4;
        if (colorSpace instanceof NamedColorSpace) {
          componentStart++;
        }
        float[] iccComponents = new float[args.length - componentStart - 1];
        for (int ix = componentStart; ++ix < args.length; ) {
          iccComponents[ix - componentStart - 1] = Float.parseFloat(args[ix].trim());
        }
        if (colorSpace instanceof NamedColorSpace && iccComponents.length == 0) {
          iccComponents = new float[] {1.0f}; // full tint if not specified
        }

        /* Ask FOP factory to get ColorSpace for the specified ICC profile source */
        if (foUserAgent != null && iccProfileSrc != null) {
          RenderingIntent renderingIntent = RenderingIntent.AUTO;
          // TODO connect to fo:color-profile/@rendering-intent
          colorSpace =
              foUserAgent.getColorSpaceCache().get(iccProfileName, iccProfileSrc, renderingIntent);
        }
        if (colorSpace != null) {
          // ColorSpace is available
          if (ColorSpaces.isDeviceColorSpace(colorSpace)) {
            // Device-specific colors are handled differently:
            // sRGB is the primary color with the CMYK as the alternative
            Color deviceColor = new Color(colorSpace, iccComponents, 1.0f);
            float[] rgbComps = sRGB.getRGBColorComponents(null);
            parsedColor =
                new ColorWithAlternatives(
                    rgbComps[0], rgbComps[1], rgbComps[2], new Color[] {deviceColor});
          } else {
            parsedColor = new ColorWithFallback(colorSpace, iccComponents, 1.0f, null, sRGB);
          }
        } else {
          // ICC profile could not be loaded - use rgb replacement values */
          log.warn(
              "Color profile '" + iccProfileSrc + "' not found. Using sRGB replacement values.");
          parsedColor = sRGB;
        }
      } catch (RuntimeException re) {
        throw new PropertyException(re);
      }
    } else {
      throw new PropertyException(
          "Unknown color format: " + value + ". Must be fop-rgb-icc(r,g,b,NCNAME,src,....)");
    }
    return parsedColor;
  }
  public static Color intensify(Color color, Color intensity) {
    float[] c = color.getRGBColorComponents(null);
    float[] i = intensity.getRGBColorComponents(null);

    return new Color(c[0] * i[0], c[1] * i[1], c[2] * i[2]);
  }
Exemple #12
0
  /**
   * Create a Plot2DViewer
   *
   * @param D the data matrix
   * @param W the top TWO components for projection
   * @param MU the means of sample data
   * @param labels the labels of sample data
   * @param Zjk the Posterior probabilities of all samples belong to current cluster
   * @param displaySetting the display setting of parameteres
   * @param expdata the struct to contain all the analysis results
   */
  public Plot2DViewer(
      double[][] D,
      double[][] W,
      double[] MU,
      int[] labels,
      double[] Zjk,
      DisplayParam displaySetting,
      ExperimentData expdata) {
    int N = D.length;
    int P = W.length;
    int Q = 2;

    this.Zjk = copy(Zjk);
    expData = expdata;
    plotPanel = new Plot2DPanel();
    displayThreshold = displaySetting.thresholdZjk;

    double X[][];
    int LABELS3[];
    Color color;

    // The following defines the number of colour gradations. Could increase this
    // for 32k or 16M colour screens
    int COL_STEP = 16;

    double THRESHOLD = 1 / (2 * (double) COL_STEP);

    double sortedZjk[] = new double[N];
    int new_order[] = new int[N];

    if (displaySetting.vl3 == 0) {
      displaySetting.blob_size = 2;
    }

    double R[];
    R = divide(displaySetting.R, max(max(displaySetting.R)));

    // load cols.mat;
    // [cols_m cols_n] = size(cols);
    // cols  = cols/255;
    // colsw = ones(cols_m,3)-cols*0.75;
    // colsw(5,:) = [0.75 0.75 0.75];
    // symv = FONT_SYMBOLS;
    // sym  = setstr(symv);

    // THRESHOLD = 1/(2*COL_STEP);
    double[][] X1 = new double[N][2];
    double[][] tmp1 = new double[N][P];
    double[][] tmp2 = new double[N][P];
    double[][] tmp3 = new double[N][P];

    double[][] v1 = new double[N][1];
    double[][] v2 = new double[1][P];

    //  X1 = (D-ones(n,1)*MU) * W ;
    for (int i = 0; i < N; i++) {
      v1[i][0] = 1;
    }
    for (int j = 0; j < P; j++) {
      v2[0][j] = MU[j];
    }
    tmp1 = times(v1, v2);
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < P; j++) {
        tmp1[i][j] = D[i][j] - tmp1[i][j];
      }
    }

    if (displaySetting.vl1 == 3) { // display with labels, and `depth coloring'
      X1 = times(tmp1, W);

      // sort Zjk ascendingly
      /*sortedZjk = copy(Zjk);
      csort(N, sortedZjk, new_order, 'a');

      // sort data points based on Zjk
      int size = 0;
      for (int i = 0; i < N; i++) {
      	if (sortedZjk[i] >= displaySetting.thresholdZjk) {
      		size ++;
      	}
      }
      X = new double[size][2];
      LABELS3 = new int[size];
      int j = 0;
      for (int i=0; i< N; i++) {
      	if (sortedZjk[i] >= displaySetting.thresholdZjk) {
      		X[j] = X1[new_order[i]];
      		LABELS3[j] = labels[new_order[i]];
      		j++;
      	}
      }*/

      sortedZjk = copy(Zjk);
      for (int i = 0; i < N; i++) {
        if (sortedZjk[i] < displaySetting.thresholdZjk) {
          sortedZjk[i] = -1;
        }
      }
      X = copy(X1);
      LABELS3 = new int[N];
      LABELS3 = labels;
      // Common.printMatrix(size, 2, X);

    } else {

      // X = (D-ones(n,1)*MU).*(ones(p,1)*Zjk')' * W ;
      double[][] v3 = new double[P][1];
      for (int j = 0; j < P; j++) {
        v3[j][0] = 1;
      }
      double[][] v4 = new double[1][N];
      for (int i = 0; i < N; i++) {
        v4[0][i] = Zjk[i];
      }
      tmp2 = transpose(times(v3, transpose(v4)));
      for (int i = 0; i < N; i++) {
        for (int j = 0; j < P; j++) {
          tmp3[i][j] = tmp1[i][j] * tmp2[i][j];
        }
      }
      X = new double[N][2];
      X = times(tmp3, W);
      LABELS3 = new int[N];
      LABELS3 = labels;
    }

    if (displaySetting.blob_size > 0) {
      // sort R ascendingly
      int R_id[] = new int[N];
      int first = 0;
      csort(N, R, R_id, 'a');
      for (int i = 0; i < N; i++) {
        if (R[i] > THRESHOLD) {
          first = i;
          break;
        }
      }
      // Common.printMatrix(N, 2, X);

      for (int i = first; i < N; i++) {

        if (sortedZjk[i] != -1) {

          color = COLORLIST[LABELS3[i] - 1];
          if (displaySetting.vl1 != 9) {
            double d[][] = new double[1][];
            d[0] = X[i];
            int id = ((DefaultSample) expData.sampleNames.get(i)).getIndex();
            Integer integerObject = new Integer(id);
            plotPanel.addPlot("SCATTER", integerObject.toString(), color, d);
          }

          // with labels, and `depth coloring'
          // change the color of points according to its posterior probabilities
          if (displaySetting.vl1 == 3) {
            double zzjjkk;
            float cols[] = new float[3];

            if (sortedZjk[i] < 0.08) {
              zzjjkk = 0.08;
            } else {
              zzjjkk = sortedZjk[i];
            }
            if (displaySetting.flag_tc == 0) {
              color.getRGBColorComponents(cols);
            } else {
              for (int j = 0; j < 3; j++) cols[j] = displaySetting.p_color[j];
            }
            for (int j = 0; j < 3; j++) {
              cols[j] = cols[j] + (1 - cols[j]) * (1 - (float) zzjjkk);
              // System.out.print("  " + cols[j]);
            }
            // System.out.print("\n");
            Color newColor = new Color(cols[0], cols[1], cols[2]);
            int plotIndex = plotPanel.plotCanvas.plots.size() - 1;
            plotPanel.changePlotColor(plotIndex, newColor);
          }
        }
      }
    }

    plotPanel.removePlotToolBar();
    // plotPanel.addQuantiletoPlot(0, 0, 0.5);
    // plotPanel.setLegendOrientation(PlotPanel.SOUTH);
    plotPanel.plotCanvas.addMouseListener(this);
    add(plotPanel);
  }
Exemple #13
0
  public BufferedImage getBufferedImage(int type, Color c) {

    BufferedImage image = null;
    float[] colComp = new float[3];
    c.getRGBColorComponents(colComp);
    double red = (double) colComp[0];
    double green = (double) colComp[1];
    double blue = (double) colComp[2];
    // System.out.println("blue, green, red = "+ blue +", " + green + ", " + red);

    double x = 0.0;
    double x2;
    switch (type) {
      case ScalarImage.TYPE_BYTE_RANDOM:
        {
          int numCol = 256;
          byte[] bBuf = new byte[numCol * 3];
          blue *= 255 * 4.;
          green *= 255 * 4.;
          red *= 255 * 4.;
          double delta = 1.0 / (double) (numCol + 1);
          int j = 0;
          for (int i = 0; i < numCol; i++) {
            if (i % 5 == 0) x = 0.7 * Math.random() + 0.3 * x;
            x2 = x * x;
            bBuf[j++] = (byte) clamp((510 - red) * x2 + (red - 255) * x);
            bBuf[j++] = (byte) clamp((510 - green) * x2 + (green - 255) * x);
            bBuf[j++] = (byte) clamp((510 - blue) * x2 + (blue - 255) * x);
            // x += delta;
          }
          IndexColorModel cm = new IndexColorModel(8, numCol, bBuf, 0, false);
          // image = new
          // BufferedImage(width,height,BufferedImage.TYPE_BYTE_INDEXED,cm);
          byte[] idxBuffer = new byte[size];
          for (int i = 0; i < size; i++) {
            idxBuffer[i] = (byte) (clamp(f[i] * 255.));
          }
          DataBufferByte dataBuffer = new DataBufferByte(idxBuffer, size);
          int idxOffset[] = {0};
          int idxBits[] = {8};
          try {
            ComponentSampleModel idxSampleModel =
                new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 1, width, idxOffset);
            WritableRaster rasterIdx =
                java.awt.image.Raster.createWritableRaster(
                    idxSampleModel, dataBuffer, new Point(0, 0));
            image = new BufferedImage(cm, rasterIdx, false, null);
          } catch (Exception e) {
            System.out.println("Exception caught while acquiring image:");
            System.out.println(e.getMessage());
          }
        }
        break;
      case BufferedImage.TYPE_BYTE_INDEXED:
        {
          int numCol = 256;
          byte[] bBuf = new byte[numCol * 3];
          blue *= 255 * 4.;
          green *= 255 * 4.;
          red *= 255 * 4.;
          double delta = 1.0 / (double) (numCol + 1);
          int j = 0;
          for (int i = 0; i < numCol; i++) {
            x2 = x * x;
            bBuf[j++] = (byte) clamp((510 - red) * x2 + (red - 255) * x);
            bBuf[j++] = (byte) clamp((510 - green) * x2 + (green - 255) * x);
            bBuf[j++] = (byte) clamp((510 - blue) * x2 + (blue - 255) * x);
            x += delta;
          }
          IndexColorModel cm = new IndexColorModel(8, numCol, bBuf, 0, false);
          // image = new
          // BufferedImage(width,height,BufferedImage.TYPE_BYTE_INDEXED,cm);
          byte[] idxBuffer = new byte[size];
          for (int i = 0; i < size; i++) {
            idxBuffer[i] = (byte) (clamp(f[i] * 255.));
          }
          DataBufferByte dataBuffer = new DataBufferByte(idxBuffer, size);
          int idxOffset[] = {0};
          int idxBits[] = {8};
          try {
            ComponentSampleModel idxSampleModel =
                new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 1, width, idxOffset);
            WritableRaster rasterIdx =
                java.awt.image.Raster.createWritableRaster(
                    idxSampleModel, dataBuffer, new Point(0, 0));
            image = new BufferedImage(cm, rasterIdx, false, null);
          } catch (Exception e) {
            System.out.println("Exception caught while acquiring image:");
            System.out.println(e.getMessage());
          }
        }
        break;
      case BufferedImage.TYPE_BYTE_GRAY:
        break;
      case BufferedImage.TYPE_3BYTE_BGR:
      default:
        byte[] byteBuffer = new byte[size * 3];
        blue *= 255 * 4.;
        green *= 255 * 4.;
        red *= 255 * 4.;

        int j = 0;
        for (int i = 0; i < size; i++) {
          x = f[i];
          x2 = x * x;
          /*
          byteBuffer[j++] = (byte)clamp( ( 2 * 255 - 4 * red ) * x * x + ( 4 * red - 255 ) * x);
          byteBuffer[j++] = (byte)clamp( ( 2 * 255 - 4 * green ) * x * x + ( 4 * green - 255 ) * x);
          byteBuffer[j++] = (byte)clamp( ( 2 * 255 - 4 * blue ) * x * x + ( 4 * blue - 255 ) * x);
          */
          byteBuffer[j++] = (byte) clamp((510 - red) * x2 + (red - 255) * x);
          byteBuffer[j++] = (byte) clamp((510 - green) * x2 + (green - 255) * x);
          byteBuffer[j++] = (byte) clamp((510 - blue) * x2 + (blue - 255) * x);
        }
        DataBufferByte dataBuffer = new DataBufferByte(byteBuffer, size * 3);
        int componentOffset[] = {0, 1, 2};
        int componentBits[] = {8, 8, 8};
        try {
          WritableRaster raster =
              java.awt.image.Raster.createWritableRaster(
                  new PixelInterleavedSampleModel(
                      DataBuffer.TYPE_BYTE, width, height, 3, width * 3, componentOffset),
                  dataBuffer,
                  new Point(0, 0));
          image =
              new BufferedImage(
                  new ComponentColorModel(
                      ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB),
                      componentBits,
                      false,
                      false,
                      ColorModel.OPAQUE,
                      DataBuffer.TYPE_BYTE),
                  raster,
                  false,
                  null);

        } catch (Exception e) {
          System.out.println("Exception caught while acquiring image:");
          System.out.println(e.getMessage());
        }
        break;
    }
    return image;
  }
  // Rendering
  public void draw(DrawContext dc) {
    GL gl = dc.getGL();

    boolean attribsPushed = false;
    boolean modelviewPushed = false;
    boolean projectionPushed = false;

    try {
      gl.glPushAttrib(
          GL.GL_DEPTH_BUFFER_BIT
              | GL.GL_COLOR_BUFFER_BIT
              | GL.GL_ENABLE_BIT
              | GL.GL_TEXTURE_BIT
              | GL.GL_TRANSFORM_BIT
              | GL.GL_VIEWPORT_BIT
              | GL.GL_CURRENT_BIT);
      attribsPushed = true;

      gl.glDisable(GL.GL_TEXTURE_2D); // no textures

      gl.glEnable(GL.GL_BLEND);
      gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
      gl.glDisable(GL.GL_DEPTH_TEST);

      double width = this.size.width;
      double height = this.size.height;

      // Load a parallel projection with xy dimensions (viewportWidth, viewportHeight)
      // into the GL projection matrix.
      java.awt.Rectangle viewport = dc.getView().getViewport();
      gl.glMatrixMode(javax.media.opengl.GL.GL_PROJECTION);
      gl.glPushMatrix();
      projectionPushed = true;
      gl.glLoadIdentity();
      double maxwh = width > height ? width : height;
      gl.glOrtho(0d, viewport.width, 0d, viewport.height, -0.6 * maxwh, 0.6 * maxwh);

      gl.glMatrixMode(GL.GL_MODELVIEW);
      gl.glPushMatrix();
      modelviewPushed = true;
      gl.glLoadIdentity();

      // Scale to a width x height space
      // located at the proper position on screen
      double scale = this.computeScale(viewport);
      Vec4 locationSW = this.computeLocation(viewport, scale);
      gl.glTranslated(locationSW.x(), locationSW.y(), locationSW.z());
      gl.glScaled(scale, scale, 1);

      // Compute scale size in real world
      Position referencePosition = dc.getViewportCenterPosition();
      if (referencePosition != null) {
        Vec4 groundTarget = dc.getGlobe().computePointFromPosition(referencePosition);
        Double distance = dc.getView().getEyePoint().distanceTo3(groundTarget);
        this.pixelSize = dc.getView().computePixelSizeAtDistance(distance);
        Double scaleSize = this.pixelSize * width * scale; // meter
        String unitLabel = "m";
        if (this.unit.equals(UNIT_METRIC)) {
          if (scaleSize > 10000) {
            scaleSize /= 1000;
            unitLabel = "Km";
          }
        } else if (this.unit.equals(UNIT_IMPERIAL)) {
          scaleSize *= 3.280839895; // feet
          unitLabel = "ft";
          if (scaleSize > 5280) {
            scaleSize /= 5280;
            unitLabel = "mile(s)";
          }
        }

        // Rounded division size
        int pot = (int) Math.floor(Math.log10(scaleSize));
        if (!Double.isNaN(pot)) {
          int digit = Integer.parseInt(String.format("%.0f", scaleSize).substring(0, 1));
          double divSize = digit * Math.pow(10, pot);
          if (digit >= 5) divSize = 5 * Math.pow(10, pot);
          else if (digit >= 2) divSize = 2 * Math.pow(10, pot);
          double divWidth = width * divSize / scaleSize;

          // Draw scale
          if (!dc.isPickingMode()) {
            // Set color using current layer opacity
            Color backColor = this.getBackgroundColor(this.color);
            float[] colorRGB = backColor.getRGBColorComponents(null);
            gl.glColor4d(
                colorRGB[0],
                colorRGB[1],
                colorRGB[2],
                (double) backColor.getAlpha() / 255d * this.getOpacity());
            gl.glTranslated((width - divWidth) / 2, 0d, 0d);
            this.drawScale(dc, divWidth, height);

            colorRGB = this.color.getRGBColorComponents(null);
            gl.glColor4d(colorRGB[0], colorRGB[1], colorRGB[2], this.getOpacity());
            gl.glTranslated(-1d / scale, 1d / scale, 0d);
            this.drawScale(dc, divWidth, height);

            // Draw label
            String label = String.format("%.0f ", divSize) + unitLabel;
            gl.glLoadIdentity();
            gl.glDisable(GL.GL_CULL_FACE);
            drawLabel(
                dc,
                label,
                locationSW.add3(
                    new Vec4(divWidth * scale / 2 + (width - divWidth) / 2, height * scale, 0)));
          } else {
            // Picking
            this.pickSupport.clearPickList();
            this.pickSupport.beginPicking(dc);
            // Draw unique color across the map
            Color color = dc.getUniquePickColor();
            int colorCode = color.getRGB();
            // Add our object(s) to the pickable list
            this.pickSupport.addPickableObject(colorCode, this, referencePosition, false);
            gl.glColor3ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue());
            gl.glTranslated((width - divWidth) / 2, 0d, 0d);
            this.drawRectangle(dc, divWidth, height);
            // Done picking
            this.pickSupport.endPicking(dc);
            this.pickSupport.resolvePick(dc, dc.getPickPoint(), this);
          }
        }
      }
    } finally {
      if (projectionPushed) {
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glPopMatrix();
      }
      if (modelviewPushed) {
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glPopMatrix();
      }
      if (attribsPushed) gl.glPopAttrib();
    }
  }