@Override
  public void render(int xScreen, int yScreen, float partialTicks) {
    if (data == null) data = ExtendedPlayerData.get(player);
    if (data == null) return;
    if (data.player != player) {
      data = ExtendedPlayerData.get(player);
    }
    if (data == null) return;
    FontRenderer fr = TessUtil.getFontRenderer();
    if (UtilM.isNull(player, fr)) return;
    if (handAlpha > 0 && UtilM.isItemInStack(MItems.theHand, player.getCurrentEquippedItem())) {
      float HandAlpha = PartialTicksUtil.calculatePos(lastHandAlpha, handAlpha);
      int slot = player.inventory.currentItem;
      OpenGLM.pushMatrix();

      int posId = 0;
      for (int b = 0; b < HandPosition.values().length; b++) {
        if (HandPosition.values()[b].equals(TheHandHandler.getActivePosition(player))) {
          posId = b;
          continue;
        }
      }
      int a1 = -1, a2 = -1, a3 = -1;
      if (posId == 1) {
        a1 = posId - 1;
        a2 = posId;
        a3 = posId + 1;
      } else if (posId == 0) {
        a1 = 2;
        a2 = posId;
        a3 = posId + 1;
      } else {
        a1 = 1;
        a2 = posId;
        a3 = 0;
      }
      String up = "string " + a1, now = "string " + a2, down = "string " + a3;

      GL11U.setUpOpaqueRendering(1);
      OpenGLM.translate(slot * 20 + xScreen / 2 - 95, yScreen - 38, 0);

      OpenGLM.translate(0, -HandAlpha * 20 + 20, 0);
      OpenGLM.translate(13, 0, 0);
      OpenGLM.scale(HandAlpha, HandAlpha, HandAlpha);
      OpenGLM.rotate(HandAlpha * 90 - 90, 0, 0, 1);
      OpenGLM.translate(-13, 0, 0);

      OpenGLM.translate(-10 + HandAlpha * 10, 0, 0);
      fr.drawStringWithShadow(up, 0, -9, Color.WHITE.hashCode());
      OpenGLM.translate(10 - HandAlpha * 10, 0, 0);
      fr.drawStringWithShadow(now, 0, 0, Color.WHITE.hashCode());
      OpenGLM.translate(10 - HandAlpha * 10, 0, 0);
      fr.drawStringWithShadow(down, 0, 9, Color.WHITE.hashCode());

      GL11U.endOpaqueRendering();
      OpenGLM.popMatrix();
    }
  }
 @Override
 protected void paintComponent(Graphics g) {
   // Draw Background.
   if (isEnabled()) {
     g.setColor(mouseStatus.getColor());
   } else {
     g.setColor(Color.WHITE.darker());
   }
   switch (btnStyle) {
     case Corner:
       g.drawRoundRect(
           0, 0, this.getWidth() - 1, this.getHeight() - 1, CORNER_ANGLE, CORNER_ANGLE);
       g.fillRoundRect(
           0, 0, this.getWidth() - 1, this.getHeight() - 1, CORNER_ANGLE, CORNER_ANGLE);
       break;
     case Rectangle:
       g.drawRect(0, 0, this.getWidth(), this.getHeight());
       g.fillRect(0, 0, this.getWidth(), this.getHeight());
       break;
     case Rectangle3D:
       g.fill3DRect(0, 0, this.getWidth(), this.getHeight(), true);
       break;
     default:
       break;
   }
 }
Beispiel #3
0
 // Bild mit Weiss fühlen
 public void fillWhite() {
   for (int y = 0; y < this.h; y++) {
     for (int x = 0; x < this.w; x++) {
       this.setRGB(x, y, Color.WHITE.getRGB());
     }
   }
 }
  public static void main(String[] args) throws Exception {
    BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
    Graphics2D g = image.createGraphics();

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g.setPaint(Color.WHITE);
    g.fill(new Rectangle(image.getWidth(), image.getHeight()));
    g.scale(.9, .9);
    g.setPaint(Color.BLACK);
    g.setStroke(new BasicStroke(0.5f));
    g.draw(new Ellipse2D.Double(25, 25, 150, 150));

    // To visually check it
    // ImageIO.write(image, "PNG", new File(args[0]));

    boolean nonWhitePixelFound = false;
    for (int x = 100; x < 200; ++x) {
      if (image.getRGB(x, 90) != Color.WHITE.getRGB()) {
        nonWhitePixelFound = true;
        break;
      }
    }
    if (!nonWhitePixelFound) {
      throw new RuntimeException("A circle is rendered like a 'C' shape.");
    }
  }
Beispiel #5
0
 /**
  * Donne le nom de fichier de la piéce
  *
  * @return Nom du fichier contenant la piéce
  */
 @Override
 public String getFilename() {
   if (color.getRGB() == Color.WHITE.getRGB()) {
     return "7a.gif";
   } else {
     return "0a.gif";
   }
 }
Beispiel #6
0
 // Bildfarben invertieren
 public void invert() {
   for (int y = 0; y < this.h; y++) {
     for (int x = 0; x < this.w; x++) {
       if (isActive(x, y)) this.setRGB(x, y, Color.WHITE.getRGB());
       else this.setRGB(x, y, Color.BLACK.getRGB());
     }
   }
 }
 @Override
 public void setBackground(Color c) {
   if (txt_box == null)
     return; // WORKAROUND.OSX: OSX LookAndFeel calls setBackground during ctor of Mem_html;
   // DATE:2015-05-11
   if (c.getRGB() == Color.BLACK.getRGB()) txt_box.setCaretColor(Color.WHITE);
   else if (c.getRGB() == Color.WHITE.getRGB()) txt_box.setCaretColor(Color.BLACK);
   super.setBackground(c);
 }
/**
 * Class to store mouse start location when dragging, and to deselect any selected components when
 * the mouse is pressed
 *
 * @author Alex Billingsley
 */
public class MseSelectListener extends MouseAdapter {

  private Point xy1;
  public static final Color DESELECT = new Color(Color.WHITE.getRGB());
  public static final Color SELECT = new Color(Color.LIGHT_GRAY.getRGB());

  /** Creates a new instance of MouseSelectionListener */
  public MseSelectListener() {}

  public void mousePressed(MouseEvent e) {
    xy1 = new Point(e.getX(), e.getY());
    JPanel layer = (JPanel) e.getComponent();
    deSelect(layer);
  }

  public static void deSelect(JPanel layer) {

    Component[] components = layer.getComponents();
    int i = 0;
    while (i < components.length) {

      if (components[i].getClass().getName().equals("javax.swing.JLabel")) {
        if (components[i].getBackground().equals(SELECT)) {
          JLabel temp = (JLabel) components[i];
          temp.setOpaque(false);
          components[i].setBackground(DESELECT);
        }
      }

      if (components[i].getClass().getName().equals("Display.TextBox")) {
        if (components[i].getBackground().equals(SELECT)) {
          components[i].setBackground(DESELECT);
        }
      }

      // If panel is selected, de-select all components nested on panel
      if (components[i].getClass().getName().equals("javax.swing.JPanel")) {
        if (components[i].getBackground().equals(SELECT)) {
          components[i].setBackground(DESELECT);
        }
        deSelect((JPanel) components[i]);
      }

      i++;
    }
  }

  /**
   * Getter for property xy1.
   *
   * @return Value of property xy1.
   */
  public Point getXy1() {
    return this.xy1;
  }
}
  private void assertBlank(RenderManager renderManagerInternal) {
    BufferedImage image = renderManagerInternal.getRenderExecutor().getContext().getImage();
    for (int x = 0; x < image.getWidth(); x++) {
      for (int y = 0; y < image.getHeight(); y++) {

        if (image.getRGB(x, y) != Color.WHITE.getRGB()) {
          fail("Image is not blank when it should be"); // $NON-NLS-1$
        }
      }
    }
  }
 private static BufferedImage createAlphaBackground(int width, int height) {
   BufferedImage background = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
   DataBufferInt dataBuffer = (DataBufferInt) background.getRaster().getDataBuffer();
   int[] data = dataBuffer.getData();
   int gray = Color.LIGHT_GRAY.getRGB();
   int white = Color.WHITE.getRGB();
   for (int i = 0; i < data.length; i++) {
     int x = i % width;
     int y = i / width;
     data[i] = ((x / 4) % 2 == (y / 4) % 2) ? gray : white;
   }
   return background;
 }
Beispiel #11
0
  /**
   * Start the mosaic generation, called from GUI.
   *
   * @param image Image to apply mosaic to.
   * @param density Magnitude of density of points in distribution.
   * @param type Type of distribution, Random or Uniform.
   * @param pointsOnly Whether to show only distribution points.
   */
  public void start(BufferedImage image, int density, String type, boolean pointsOnly) {

    // numPoints calculations are based on the idea of the fractional area
    // the fractional area is the theoretical area surrounding a uniform
    // distribution of points in the area of the image. The number represents
    // dividing the area of the image by the number of points distributed
    // in the area. By dividing area by the fractional area, you get the number
    // of points needed to achieve that density. fractional area ranges from
    // ~250 to 2500
    double fractionalArea = 0;
    if (density >= 1 && density <= 5) {
      fractionalArea = 2500 - (FRAC_AREA_STEP * (density - 1));
    } else {
      fractionalArea = DEFAULT_FRAC_AREA;
    }

    if (type.equalsIgnoreCase("RANDOM")) {
      // determine number of points as whole area / frac area

      int numPoints = (int) (image.getWidth() * image.getHeight() / fractionalArea);
      PlotTree tree = new RandomPlot(numPoints, image.getWidth(), image.getHeight());
      tesselation = new Tesselation(image, tree);

      // in the case of the poisson disc distribution, we want to determine density
      // as the distance between points. this is approximated by taking the square root
      // of the fractionalArea, because that approximates the distance between points
      // in a hypothetical distribution. The full transformation is:
      // numPoints = sqrt(w*h)/sqrt(w*h/fracArea)
      // numPoints^2 = w*h/(w*h/fracArea)
      // numPoints^2 = fracArea
      // numPoints = sqrt(fracArea)
    } else if (type.equalsIgnoreCase("UNIFORM")) {
      int numPoints = (int) Math.sqrt(fractionalArea);
      PlotTree tree = new PoissonPlot(numPoints, image.getWidth(), image.getHeight());
      tesselation = new Tesselation(image, tree);
    }

    tesselation.createDistribution();

    // Apply the distribution data either as a mosaic or points
    if (pointsOnly) {
      tesselation.drawPoints(Color.WHITE.getRGB());
    } else {
      tesselation.applyMosaic();
    }

    // free up resources and reset for another run
    // cleanUp();

  }
 protected void paintComponent(Graphics g) {
   super.paintComponent(g);
   Graphics2D g2 = (Graphics2D) g.create();
   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
   Color dark = new Color(1.0F, 1.0F, 1.0F, 0.0F);
   Color light = new Color(1.0F, 1.0F, 1.0F, 0.18F);
   GradientPaint paint = new GradientPaint(0.0F, 0.0F, light, 0.0F, getHeight(), dark);
   g2.setPaint(paint);
   g2.fillRoundRect(0, 0, getWidth() - 2, getHeight() - 2, 20, 20);
   g2.setStroke(new BasicStroke(1.4F));
   g2.setColor(Color.WHITE.brighter());
   g2.drawRoundRect(0, 0, getWidth() - 2, getHeight() - 2, 20, 20);
   g2.dispose();
 }
Beispiel #13
0
  public void encode(String str, String path, int width, int height) {
    try {
      Map hints = new HashMap();
      hints.put(EncodeHintType.MARGIN, 0);
      // hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
      hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
      hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
      BitMatrix byteMatrix =
          new MultiFormatWriter().encode(str, BarcodeFormat.QR_CODE, width, height, hints);

      /** tianboalei 2015-1-22 去掉生成二维码时周围的白圈 */
      // 1
      int[] rec = byteMatrix.getEnclosingRectangle();
      int resWidth = rec[2] + 1;
      int resHeight = rec[3] + 1;
      BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
      resMatrix.clear();
      for (int i = 0; i < resWidth; i++) {
        for (int j = 0; j < resHeight; j++) {
          if (byteMatrix.get(i + rec[0], j + rec[1])) {
            resMatrix.set(i, j);
          }
        }
      }
      // 2
      int widthT = resMatrix.getWidth();
      int heightT = resMatrix.getHeight();
      BufferedImage image = new BufferedImage(widthT, heightT, BufferedImage.TYPE_INT_ARGB);
      for (int x = 0; x < widthT; x++) {
        for (int y = 0; y < heightT; y++) {
          image.setRGB(
              x, y, resMatrix.get(x, y) == true ? Color.BLACK.getRGB() : Color.WHITE.getRGB());
        }
      }
      /** 去掉二维码周围白圈结束 */
      File file = new File(path);
      writeToFile(resMatrix, "png", file);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
Beispiel #14
0
  /**
   * Overrides the Runnable run method. Checks an image to see if it contains a Sign Language letter
   * and identifies the letter if true.
   */
  @Override
  public void run() {
    Random r = new Random();
    int currentResult = this.result;

    while (true) {

      /*
       * This is the normal sleep that relaxes the CPU a bit and
       * lets other threads run fluently.
       */
      try {
        Thread.sleep(100);
      } catch (InterruptedException ex) {
        ex.printStackTrace();
      }

      while (this.algorithmRunning) {

        if (this.capturedImageChanged) {
          synchronized (this.lockObject) {
            this.capturedImageChanged = false;
          }

          /*
           * This is where the Algorithm method will be called (possibly other classes involded).
           * For now, instead a simple sleep will be called as simulation.
           *
           *   try {
           *       Thread.sleep(5000);
           *   } catch (InterruptedException ex) {
           *       ex.printStackTrace();
           *   }
           */

          /*
           * Let's see.
           * Processing and information aquiring part.
           */
          if (this.siblingEye == null) {
            continue;
          }
          BufferedImage capturedIm = this.siblingEye.getImage();
          // System.out.format("Brain: capIm's with is %d and height is %d\n",
          // capturedIm.getWidth(), capturedIm.getHeight());
          if (capturedIm == null) {
            continue;
          }
          double ar =
              (double) (EyeWebcam.HAND_CUT_X2 - EyeWebcam.HAND_CUT_X1)
                  / (EyeWebcam.HAND_CUT_Y2 - EyeWebcam.HAND_CUT_Y1);
          // System.out.format("Brain: aspect ratio = %.2f\n", ar);
          int camImWidth, camImHeight;
          int cutX1 = EyeWebcam.HAND_CUT_X1;
          int cutX2 = EyeWebcam.HAND_CUT_X2;
          int cutY1 = EyeWebcam.HAND_CUT_Y1;
          int cutY2 = EyeWebcam.HAND_CUT_Y2;
          if (ar < DBImage.DB_IMAGE_ASPECT_RATIO) {
            camImWidth = (int) Math.round(DBImage.DB_IMAGE_HEIGHT * ar);
            camImHeight = DBImage.DB_IMAGE_HEIGHT;
            double cutHeight =
                (EyeWebcam.HAND_CUT_Y2
                        - EyeWebcam.HAND_CUT_Y1
                        - (EyeWebcam.HAND_CUT_X2 - EyeWebcam.HAND_CUT_X1)
                            / DBImage.DB_IMAGE_ASPECT_RATIO)
                    / 2;
            cutY1 = (int) (EyeWebcam.HAND_CUT_Y1 + cutHeight);
            cutY2 = (int) (EyeWebcam.HAND_CUT_Y2 - cutHeight);
          } else {
            camImWidth = DBImage.DB_IMAGE_WIDTH;
            camImHeight = (int) Math.round(DBImage.DB_IMAGE_WIDTH / ar);
            double cutWidth =
                (EyeWebcam.HAND_CUT_X2
                        - EyeWebcam.HAND_CUT_X1
                        - (EyeWebcam.HAND_CUT_Y2 - EyeWebcam.HAND_CUT_Y1)
                            * DBImage.DB_IMAGE_ASPECT_RATIO)
                    / 2;
            cutX1 = (int) (EyeWebcam.HAND_CUT_X1 + cutWidth);
            cutX2 = (int) (EyeWebcam.HAND_CUT_X2 - cutWidth);
          }
          // System.out.format("Brain: camImWidth = %d, camImHeight = %d\n", camImWidth,
          // camImHeight);
          // System.out.format("Brain: cutX2 = %d, cutX1 = %d, cutY2 = %d, cutY1 = %d\n", cutX2,
          // cutX1, cutY2, cutY1);
          // System.out.format("Brain: cutX2 - cutX1 / cutY2 - cutY1 = %.3f\n", (double) (cutX2 -
          // cutX1) / (cutY2 - cutY1));
          int[][] cutResizedGrayIntIm =
              ImageAlgorithms.buffIm2CutGrayResizedIntIm(
                  capturedIm,
                  cutX1,
                  cutY1,
                  cutX2,
                  cutY2,
                  DBImage.DB_IMAGE_WIDTH,
                  DBImage.DB_IMAGE_HEIGHT);
          if (cutResizedGrayIntIm == null) {
            continue;
          }
          GrayImageAndHistogram contourIntImAndHistogram =
              ImageAlgorithms.grayIntIm2ContourImAndHistogram(
                  cutResizedGrayIntIm, DBImage.CONTOUR_POWER);
          int[][] contourIntIm = contourIntImAndHistogram.getGrayImage();
          int[] histogram = contourIntImAndHistogram.getHistogram();
          int threshold =
              ImageAlgorithms.computeNecessaryThreshold(
                  DBImage.WHITE_PROPORTION, histogram, camImWidth * camImHeight);
          // System.out.format("Brain: threshold = %d\n", threshold);
          boolean[][] camBoolIm = ImageAlgorithms.grayIntIm2BoolIm(contourIntIm, threshold);
          this.processedImage =
              ImageAlgorithms.boolIm2BuffIm(camBoolIm, Color.BLACK.getRGB(), Color.WHITE.getRGB());
          Shape greatestShape = ImageAlgorithms.findGreatestShape(camBoolIm);
          // System.out.format("Brain: greatestShape's area is %d\n", greatestShape.getArea());

          Point2D leftMostPoint = greatestShape.getLeftMostPoint();
          Point2D rightMostPoint = greatestShape.getRightMostPoint();
          Point2D bottomMostPoint = greatestShape.getBottomMostPoint();
          Point2D topMostPoint = greatestShape.getTopMostPoint();

          Shape leftShape =
              ImageAlgorithms.reduceShapeHVAreaLimit(
                  greatestShape, leftMostPoint, DBImage.HV_THINNESS, true, DBImage.HV_AREA_LIMIT);
          Shape rightShape =
              ImageAlgorithms.reduceShapeHVAreaLimit(
                  greatestShape, rightMostPoint, DBImage.HV_THINNESS, true, DBImage.HV_AREA_LIMIT);
          Shape topShape =
              ImageAlgorithms.reduceShapeHVAreaLimit(
                  greatestShape, topMostPoint, DBImage.HV_THINNESS, false, DBImage.HV_AREA_LIMIT);
          Shape bottomShape =
              ImageAlgorithms.reduceShapeHVAreaLimit(
                  greatestShape,
                  bottomMostPoint,
                  DBImage.HV_THINNESS,
                  false,
                  DBImage.HV_AREA_LIMIT);

          int camLeftShapeCenter = leftShape.getCenter().getX();
          int camTopShapeCenter = topShape.getCenter().getY();
          int camShapeWidth = rightShape.getCenter().getX() - camLeftShapeCenter;
          int camShapeHeight = bottomShape.getCenter().getY() - camTopShapeCenter;
          // System.out.format("Brain: camLeftShapeCenter = %d, camTopShapeCenter = %d,
          // camShapeWidth = %d, camShapeHeight = %d\n", camLeftShapeCenter, camTopShapeCenter,
          // camShapeWidth, camShapeHeight);

          /* Comparison part.
           * Similar to that sucky algorithm Iulia showed me.
           * (The algorithm is sucky not Iulia)
           * BTW talkin'bout Iulia M., not Iulia P. cause Iulia P. _is_ forsure.
           */
          Vector<Letter> letters = this.parentModel.getLetters();
          if (letters == null) {
            continue;
          }
          // System.out.format("Brain: got %d letters.\n", letters.size());
          Iterator<Letter> itlt = letters.iterator();
          int letterIndex = 0;
          double maxMatchedDouble = 0.0;
          int maxMatchedIndex = 0;
          while (itlt.hasNext()) {
            Letter letter = itlt.next();
            Vector<DBImage> dbIms = letter.getDBImages();
            // System.out.format("Brain: got %d images for letter %d.\n", dbIms.size(),
            // letterIndex);
            if (dbIms == null) {
              continue;
            }
            Iterator<DBImage> itim = dbIms.iterator();
            int imIndex = 0;
            int nMatched = 0;
            while (itim.hasNext()) {
              DBImage dbIm = itim.next();

              boolean[][] dbBoolIm = dbIm.getRaster();
              // System.out.format("dbBoolIm's width and heigth is %d and %d\n", dbBoolIm[0].length,
              // dbBoolIm.length);
              int dbLeftShapeCenter = dbIm.getLeftShapeCenter();
              int dbTopShapeCenter = dbIm.getTopShapeCenter();
              int dbShapeWidth = dbIm.getShapeWidth();
              int dbShapeHeight = dbIm.getShapeHeight();
              // System.out.format("Brain: dbLeftShapeCenter = %d, dbTopShapeCenter = %d,
              // dbShapeWidth = %d, dbShapeHeight = %d\n", dbLeftShapeCenter, dbTopShapeCenter,
              // dbShapeWidth, dbShapeHeight);
              boolean[][] transZoomedBoolIm =
                  ImageAlgorithms.transZoomBoolIm(
                      camBoolIm,
                      dbLeftShapeCenter - camLeftShapeCenter,
                      dbTopShapeCenter - camTopShapeCenter,
                      (double) dbShapeWidth / camShapeWidth,
                      (double) dbShapeHeight / camShapeHeight,
                      camLeftShapeCenter,
                      camTopShapeCenter);
              // this.processedImage = ImageAlgorithms.boolIm2BuffIm(transZoomedBoolIm,
              // Color.BLACK.getRGB(), Color.BLUE.brighter().getRGB());
              // System.out.format("transZoomedBoolIm's width and heigth is %d and %d\n",
              // transZoomedBoolIm[0].length, transZoomedBoolIm.length);

              double match = ImageAlgorithms.compareTwoBoolIms(camBoolIm, dbBoolIm);
              // double match = ImageAlgorithms.compareTwoBoolIms(transZoomedBoolIm, dbBoolIm);
              // System.out.format("matching with letter %d, %d. image gives %.3f\n", letterIndex,
              // imIndex, match);
              if (match >= Brain.MINIMUM_RATE_NEEDED_TO_MATCH) {
                nMatched++;
              }

              imIndex++;
            }
            double nMatchedDouble = (double) nMatched / dbIms.size();
            if (nMatchedDouble > maxMatchedDouble) {
              maxMatchedDouble = nMatchedDouble;
              maxMatchedIndex = letterIndex + 1;
            }

            letterIndex++;
          }
          System.out.format(
              "Brain: compared with %d letters, maxMatchedDouble = %.3f, maxMatchedIndex = %d.\n",
              letterIndex, maxMatchedDouble, maxMatchedIndex);

          /* Evaluating the comparison.
           */
          if (maxMatchedDouble > Brain.MINIMUM_PROPORTION_OF_IMAGES_NEEDED_TO_MATCH) {
            currentResult = maxMatchedIndex;
          } else {
            currentResult = -1;
          }

          /* For testing: */
          // currentResult = 1 + r.nextInt(4);

        }

        if (currentResult != this.result) {
          this.result = currentResult;
          System.out.format("Brain: new result = %d\n", result);
          this.parentModel.setBrainResultChanged();
        }
      }
    }
  }
Beispiel #15
0
 // Zeichent ein Weisses Punkt
 public void deactivate(int x, int y) {
   this.setRGB(x, y, Color.WHITE.getRGB());
 }
  public static void renderTooltip(
      int x,
      int y,
      List<String> tooltipData,
      Color color,
      Color colorFade,
      FontRenderer fontRenderer) {
    TextureHelper.setActiveTextureToAtlasSprite();
    boolean lighting = GL11.glGetBoolean(GL11.GL_LIGHTING);
    if (lighting) RenderHelper.disableStandardItemLighting();

    if (!tooltipData.isEmpty()) {
      int esWidth = 0;
      for (String toolTip : tooltipData) {
        int width = fontRenderer.getStringWidth(toolTip);
        if (width > esWidth) esWidth = width;
      }
      int pX = x + 12;
      int pY = y - 12;
      int sumLineHeight = 8;
      if (tooltipData.size() > 1) sumLineHeight += 2 + (tooltipData.size() - 1) * 10;
      float z = 300F;

      drawGradientRect(pX - 3, pY - 4, z, pX + esWidth + 3, pY - 3, color, colorFade);
      drawGradientRect(
          pX - 3,
          pY + sumLineHeight + 3,
          z,
          pX + esWidth + 3,
          pY + sumLineHeight + 4,
          color,
          colorFade);
      drawGradientRect(
          pX - 3, pY - 3, z, pX + esWidth + 3, pY + sumLineHeight + 3, color, colorFade);
      drawGradientRect(pX - 4, pY - 3, z, pX - 3, pY + sumLineHeight + 3, color, colorFade);
      drawGradientRect(
          pX + esWidth + 3, pY - 3, z, pX + esWidth + 4, pY + sumLineHeight + 3, color, colorFade);

      int rgb = color.getRGB();
      int col = (rgb & 0x00FFFFFF) | rgb & 0xFF000000;
      Color colOp = new Color(col);
      drawGradientRect(pX - 3, pY - 3 + 1, z, pX - 3 + 1, pY + sumLineHeight + 3 - 1, color, colOp);
      drawGradientRect(
          pX + esWidth + 2,
          pY - 3 + 1,
          z,
          pX + esWidth + 3,
          pY + sumLineHeight + 3 - 1,
          color,
          colOp);
      drawGradientRect(pX - 3, pY - 3, z, pX + esWidth + 3, pY - 3 + 1, colOp, colOp);
      drawGradientRect(
          pX - 3,
          pY + sumLineHeight + 2,
          z,
          pX + esWidth + 3,
          pY + sumLineHeight + 3,
          color,
          color);

      GL11.glDisable(GL11.GL_DEPTH_TEST);
      for (int i = 0; i < tooltipData.size(); ++i) {
        String var14 = tooltipData.get(i);
        fontRenderer.drawString(var14, pX, pY, Color.WHITE.getRGB());
        if (i == 0) pY += 2;
        pY += 10;
      }
      GL11.glEnable(GL11.GL_DEPTH_TEST);
    }

    if (lighting) RenderHelper.enableStandardItemLighting();
    GL11.glColor4f(1F, 1F, 1F, 1F);
  }
Beispiel #17
0
  // prueft ob ein Punkt aktiv(schwarz) ist (mit int als Parameter)
  public boolean isActive(int x, int y) {
    if (x < 0 || y < 0 || x >= this.w || y >= this.h) return false;

    if (this.getRGB(x, y) == Color.WHITE.getRGB()) return false;
    else return true;
  }
  /**
   * Tests the {@link ImageWorker#makeColorTransparent} methods. Some trivial tests are performed
   * before.
   *
   * @throws IOException
   * @throws FileNotFoundException
   * @throws IllegalStateException
   */
  @Test
  public void testMakeColorTransparent()
      throws IllegalStateException, FileNotFoundException, IOException {
    assertTrue("Assertions should be enabled.", ImageWorker.class.desiredAssertionStatus());
    ImageWorker worker = new ImageWorker(sstImage);

    assertSame(sstImage, worker.getRenderedImage());
    assertEquals(1, worker.getNumBands());
    assertEquals(-1, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertFalse(worker.isBinary());
    assertTrue(worker.isIndexed());
    assertTrue(worker.isColorSpaceRGB());
    assertFalse(worker.isColorSpaceGRAYScale());
    assertFalse(worker.isTranslucent());

    assertSame(
        "Expected no operation.", sstImage, worker.forceIndexColorModel(false).getRenderedImage());
    assertSame(
        "Expected no operation.", sstImage, worker.forceIndexColorModel(true).getRenderedImage());
    assertSame("Expected no operation.", sstImage, worker.forceColorSpaceRGB().getRenderedImage());
    assertSame("Expected no operation.", sstImage, worker.retainFirstBand().getRenderedImage());
    assertSame("Expected no operation.", sstImage, worker.retainLastBand().getRenderedImage());

    // Following will change image, so we need to test after the above assertions.
    assertEquals(0, worker.getMinimums()[0], 0);
    assertEquals(255, worker.getMaximums()[0], 0);
    assertNotSame(sstImage, worker.getRenderedImage());
    assertSame(
        "Expected same databuffer, i.e. pixels should not be duplicated.",
        sstImage.getTile(0, 0).getDataBuffer(),
        worker.getRenderedImage().getTile(0, 0).getDataBuffer());

    assertSame(worker, worker.makeColorTransparent(Color.WHITE));
    assertEquals(255, worker.getTransparentPixel());
    assertFalse(worker.isTranslucent());
    assertSame(
        "Expected same databuffer, i.e. pixels should not be duplicated.",
        sstImage.getTile(0, 0).getDataBuffer(),
        worker.getRenderedImage().getTile(0, 0).getDataBuffer());

    // INDEX TO INDEX-ALPHA
    worker = new ImageWorker(chlImage).makeColorTransparent(Color.black);
    show(worker, "CHL01195.png");
    assertEquals(1, worker.getNumBands());
    assertEquals(0, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertTrue(worker.isIndexed());
    assertTrue(worker.isColorSpaceRGB());
    assertFalse(worker.isColorSpaceGRAYScale());
    assertFalse(worker.isTranslucent());
    RenderedImage image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof IndexColorModel);
    IndexColorModel iColorModel = (IndexColorModel) image.getColorModel();
    int transparentColor = iColorModel.getRGB(worker.getTransparentPixel()) & 0x00ffffff;
    assertTrue(transparentColor == 0);

    // INDEX TO INDEX-ALPHA
    worker = new ImageWorker(bathy).makeColorTransparent(Color.WHITE);
    show(worker, "BATHY.png");
    assertEquals(1, worker.getNumBands());
    assertEquals(206, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertTrue(worker.isIndexed());
    assertTrue(worker.isColorSpaceRGB());
    assertFalse(worker.isColorSpaceGRAYScale());
    assertFalse(worker.isTranslucent());
    image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof IndexColorModel);
    iColorModel = (IndexColorModel) image.getColorModel();
    transparentColor = iColorModel.getRGB(worker.getTransparentPixel()) & 0x00ffffff;
    assertTrue(transparentColor == (Color.WHITE.getRGB() & 0x00ffffff));

    // RGB TO RGBA
    worker = new ImageWorker(smallWorld).makeColorTransparent(new Color(11, 10, 50));
    show(worker, "small_world.png");
    assertEquals(4, worker.getNumBands());
    assertEquals(-1, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertFalse(worker.isIndexed());
    assertTrue(worker.isColorSpaceRGB());
    assertFalse(worker.isColorSpaceGRAYScale());
    assertTrue(worker.isTranslucent());
    image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof ComponentColorModel);

    // RGBA to RGBA
    worker = new ImageWorker(worldImage).makeColorTransparent(Color.white);
    show(worker, "world.png");
    assertEquals(4, worker.getNumBands());
    assertEquals(-1, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertFalse(worker.isIndexed());
    assertTrue(worker.isColorSpaceRGB());
    assertFalse(worker.isColorSpaceGRAYScale());
    assertTrue(worker.isTranslucent());
    image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof ComponentColorModel);

    // GRAY TO GRAY-ALPHA
    worker = new ImageWorker(gray).makeColorTransparent(Color.black);
    show(worker, "gray.png");
    assertEquals(2, worker.getNumBands());
    assertEquals(-1, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertFalse(worker.isIndexed());
    assertFalse(worker.isColorSpaceRGB());
    assertTrue(worker.isColorSpaceGRAYScale());
    assertTrue(worker.isTranslucent());
    image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof ComponentColorModel);

    // GRAY-ALPHA TO GRAY-ALPHA.
    worker = new ImageWorker(grayAlpha).makeColorTransparent(Color.black);
    show(worker, "gray-alpha.png");
    assertEquals(2, worker.getNumBands());
    assertEquals(-1, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertFalse(worker.isIndexed());
    assertFalse(worker.isColorSpaceRGB());
    assertTrue(worker.isColorSpaceGRAYScale());
    assertTrue(worker.isTranslucent());
    image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof ComponentColorModel);
  }
Beispiel #19
0
/**
 * A font in an Image Markup document that originates from a born-digital source, e.g. a
 * born-digital PDF document.
 *
 * @author sautter
 */
public class ImFont implements ImObject {

  /** the name of the attribute holding the font name */
  public static final String NAME_ATTRIBUTE = "name";

  /** the name of the attribute holding the font style */
  public static final String STYLE_ATTRIBUTE = "style";

  /** the name of the attribute holding character IDs */
  public static final String CHARACTER_ID_ATTRIBUTE = "charId";

  /** the name of the attribute holding character strings */
  public static final String CHARACTER_STRING_ATTRIBUTE = "charString";

  /** the name of the attribute holding character images */
  public static final String CHARACTER_IMAGE_ATTRIBUTE = "charImage";

  /** the name of the attribute indicating if the font is serif or sans-serif */
  public static final String SERIF_ATTRIBUTE = "serif";

  /**
   * the name of the attribute to a word storing the font specific char codes the word was composed
   * from
   */
  public static final String CHARACTER_CODE_STRING_ATTRIBUTE = "fontCharCodes";

  private ImDocument doc;

  /** the name of the font */
  public final String name;

  private boolean bold;
  private boolean italics;
  private boolean serif;

  private TreeMap characters = new TreeMap();

  /**
   * Constructor
   *
   * @param doc the Image Markup document the font belongs to
   * @param name the font name
   */
  public ImFont(ImDocument doc, String name) {
    this(doc, name, false, false, true);
  }

  /**
   * Constructor
   *
   * @param doc the Image Markup document the font belongs to
   * @param name the font name
   * @param bold is the font bold?
   * @param italics is the font in italics?
   * @param serif is the font serif or sans-serif?
   */
  public ImFont(ImDocument doc, String name, boolean bold, boolean italics, boolean serif) {
    this.doc = doc;
    this.name = name;
    this.bold = bold;
    this.italics = italics;
    this.serif = serif;
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.gamta.Attributed#setAttribute(java.lang.String)
   */
  public void setAttribute(String name) {
    if (BOLD_ATTRIBUTE.equals(name)) this.setBold(true);
    else if (ITALICS_ATTRIBUTE.equals(name)) this.setItalics(true);
    else if (SERIF_ATTRIBUTE.equals(name)) this.setSerif(true);
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.gamta.Attributed#setAttribute(java.lang.String, java.lang.Object)
   */
  public Object setAttribute(String name, Object value) {
    if (BOLD_ATTRIBUTE.equals(name)) {
      boolean wasBold = this.isBold();
      this.setBold(value != null);
      return new Boolean(wasBold);
    } else if (ITALICS_ATTRIBUTE.equals(name)) {
      boolean wasItalics = this.isItalics();
      this.setItalics(value != null);
      return new Boolean(wasItalics);
    } else if (SERIF_ATTRIBUTE.equals(name)) {
      boolean wasSerif = this.isSerif();
      this.setSerif(value != null);
      return new Boolean(wasSerif);
    } else if (name.startsWith(CHARACTER_STRING_ATTRIBUTE + "-") && (value instanceof String)) {
      int charId = Integer.parseInt(name.substring((CHARACTER_STRING_ATTRIBUTE + "-").length()));
      String oCharStr = this.getString(charId);
      this.addCharacter(charId, ((String) value), ((BufferedImage) null));
      return oCharStr;
    } else if (name.startsWith(CHARACTER_IMAGE_ATTRIBUTE + "-")
        && (value instanceof BufferedImage)) {
      int charId = Integer.parseInt(name.substring((CHARACTER_IMAGE_ATTRIBUTE + "-").length()));
      BufferedImage oCharImage = this.getImage(charId);
      this.addCharacter(charId, null, ((BufferedImage) value));
      return oCharImage;
    } else return null;
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.gamta.Attributed#copyAttributes(de.uka.ipd.idaho.gamta.Attributed)
   */
  public void copyAttributes(Attributed source) {
    /* we're not doing this here, as attributes are only to allow for generic undo management */
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.gamta.Attributed#getAttribute(java.lang.String)
   */
  public Object getAttribute(String name) {
    return this.getAttribute(name, null);
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.gamta.Attributed#getAttribute(java.lang.String, java.lang.Object)
   */
  public Object getAttribute(String name, Object def) {
    if (BOLD_ATTRIBUTE.equals(name)) return new Boolean(this.isBold());
    else if (ITALICS_ATTRIBUTE.equals(name)) return new Boolean(this.isItalics());
    else if (SERIF_ATTRIBUTE.equals(name)) return new Boolean(this.isSerif());
    else if (name.startsWith(CHARACTER_STRING_ATTRIBUTE + "-")) {
      int charId = Integer.parseInt(name.substring((CHARACTER_STRING_ATTRIBUTE + "-").length()));
      return this.getString(charId);
    } else if (name.startsWith(CHARACTER_IMAGE_ATTRIBUTE + "-")) {
      int charId = Integer.parseInt(name.substring((CHARACTER_IMAGE_ATTRIBUTE + "-").length()));
      return this.getImage(charId);
    } else return def;
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.gamta.Attributed#hasAttribute(java.lang.String)
   */
  public boolean hasAttribute(String name) {
    return (BOLD_ATTRIBUTE.equals(name)
        || ITALICS_ATTRIBUTE.equals(name)
        || SERIF_ATTRIBUTE.equals(name));
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.gamta.Attributed#getAttributeNames()
   */
  public String[] getAttributeNames() {
    String[] ans = {BOLD_ATTRIBUTE, ITALICS_ATTRIBUTE, SERIF_ATTRIBUTE};
    return ans;
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.gamta.Attributed#removeAttribute(java.lang.String)
   */
  public Object removeAttribute(String name) {
    if (BOLD_ATTRIBUTE.equals(name)) {
      boolean wasBold = this.isBold();
      this.setBold(false);
      return new Boolean(wasBold);
    } else if (ITALICS_ATTRIBUTE.equals(name)) {
      boolean wasItalics = this.isItalics();
      this.setItalics(false);
      return new Boolean(wasItalics);
    } else if (SERIF_ATTRIBUTE.equals(name)) {
      boolean wasSerif = this.isSerif();
      this.setSerif(false);
      return new Boolean(wasSerif);
    } else return null;
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.gamta.Attributed#clearAttributes()
   */
  public void clearAttributes() {
    /* we're not doing this here, as attributes are only to allow for generic undo management */
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.im.ImObject#getType()
   */
  public String getType() {
    return "font";
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.im.ImObject#setType(java.lang.String)
   */
  public void setType(String type) {}

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.im.ImObject#getDocument()
   */
  public ImDocument getDocument() {
    return this.doc;
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.im.ImObject#getDocumentProperty(java.lang.String)
   */
  public String getDocumentProperty(String propertyName) {
    return this.doc.getDocumentProperty(propertyName);
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.im.ImObject#getDocumentProperty(java.lang.String, java.lang.String)
   */
  public String getDocumentProperty(String propertyName, String defaultValue) {
    return this.doc.getDocumentProperty(propertyName, defaultValue);
  }

  /* (non-Javadoc)
   * @see de.uka.ipd.idaho.im.ImObject#getDocumentPropertyNames()
   */
  public String[] getDocumentPropertyNames() {
    return this.doc.getDocumentPropertyNames();
  }

  /**
   * Test whether or not the font is bold.
   *
   * @return true if the font is bold, false otherwise
   */
  public boolean isBold() {
    return this.bold;
  }

  /**
   * Mark the font as bold or non-bold.
   *
   * @param bold is the font bold?
   */
  public void setBold(boolean bold) {
    if (this.bold == bold) return;
    this.bold = bold;
    this.doc.notifyAttributeChanged(this, BOLD_ATTRIBUTE, (this.bold ? null : "true"));
  }

  /**
   * Test whether or not the font is in italics.
   *
   * @return true if the font is in italics, false otherwise
   */
  public boolean isItalics() {
    return this.italics;
  }

  /**
   * Mark the font as italics or non-italics.
   *
   * @param italics is the font in italics?
   */
  public void setItalics(boolean italics) {
    if (this.italics == italics) return;
    this.italics = italics;
    this.doc.notifyAttributeChanged(this, ITALICS_ATTRIBUTE, (this.italics ? null : "true"));
  }

  /**
   * Test whether the font is serif or sans-serif.
   *
   * @return true if the font is serif, false otherwise
   */
  public boolean isSerif() {
    return this.serif;
  }

  /**
   * Mark the font as serif or sans-serif.
   *
   * @param serif is the font serif?
   */
  public void setSerif(boolean serif) {
    if (this.serif == serif) return;
    this.serif = serif;
    this.doc.notifyAttributeChanged(this, SERIF_ATTRIBUTE, (this.serif ? null : "true"));
  }

  /**
   * Retrieve the number of characters in the font.
   *
   * @return the number of characters
   */
  public int getCharacterCount() {
    return this.characters.size();
  }

  /**
   * Add a character to the font. The character string is supposed to hold a Unicode representation
   * of the character, preferably one consisting of individual letters, digits, symbols, or
   * punctuation marks, rather than ligature characters or the like. The returned boolean indicates
   * if the font was modified, i.e., if a character was added or modified as a result of the call to
   * this method.
   *
   * @param charId the font-local ID of the character
   * @param charStr the Unicode representation of the character
   * @return true if the font was modified, false otherwise
   */
  public boolean addCharacter(int charId, String charStr) {
    return this.addCharacter(charId, charStr, ((BufferedImage) null));
  }

  /**
   * Add a character to the font. The character string is supposed to hold a Unicode representation
   * of the character, preferably one consisting of individual letters, digits, symbols, or
   * punctuation marks, rather than ligature characters or the like. The argument character image is
   * the glyph corresponding to the character in the source document, if any is explicitly given
   * there; it allows for users to double-check and modify the transcription of glyphs to Unicode
   * characters. The character image string is parsed as a hex encoding of a 32 pixel high
   * black-and-white bitmap. The returned boolean indicates if the font was modified, i.e., if a
   * character was added or modified as a result of the call to this method.
   *
   * @param charId the font-local ID of the character
   * @param charStr the Unicode representation of the character
   * @param charImageHex the character image as extracted from the source
   * @return true if the font was modified, false otherwise
   */
  public boolean addCharacter(int charId, String charStr, String charImageHex) {
    return this.addCharacter(charId, charStr, decodeCharacterImage(charImageHex));
  }

  /**
   * Add a character to the font. The character string is supposed to hold a Unicode representation
   * of the character, preferably one consisting of individual letters, digits, symbols, or
   * punctuation marks, rather than ligature characters or the like. The argument character image is
   * the glyph corresponding to the character in the source document, if any is explicitly given
   * there; it allows for users to double-check and modify the transcription of glyphs to Unicode
   * characters. The character image should be a black-and-white bitmap, 32 pixels high, with width
   * allowed to adjust proportionally in accordance to the glyph dimensions. The returned boolean
   * indicates if the font was modified, i.e., if a character was added or modified as a result of
   * the call to this method.
   *
   * @param charId the font-local ID of the character
   * @param charStr the Unicode representation of the character
   * @param charImage the character image as extracted from the source
   * @return true if the font was modified, false otherwise
   */
  public boolean addCharacter(int charId, String charStr, BufferedImage charImage) {
    ImCharacter chr = ((ImCharacter) this.characters.get(new Integer(charId)));
    if (chr == null) {
      chr = new ImCharacter(charId, charStr, charImage);
      this.characters.put(new Integer(chr.id), chr);
      return true;
    }
    boolean modified = false;
    if ((charStr != null) && !charStr.equals(chr.str)) {
      modified = true;
      String oCharStr = chr.str;
      chr.str = charStr;
      this.doc.notifyAttributeChanged(this, (CHARACTER_STRING_ATTRIBUTE + "-" + charId), oCharStr);
    }
    if ((charImage != null) && !characterImagesEqual(charImage, chr.image)) {
      modified = true;
      BufferedImage oCharImage = chr.image;
      chr.image = charImage;
      this.doc.notifyAttributeChanged(this, (CHARACTER_IMAGE_ATTRIBUTE + "-" + charId), oCharImage);
    }
    return modified;
  }

  /**
   * Retrieve the Unicode string representing a character.
   *
   * @param charId the font-local ID of the character
   * @return the Unicode string of the character with the argument ID
   */
  public String getString(int charId) {
    ImCharacter chr = ((ImCharacter) this.characters.get(new Integer(charId)));
    return ((chr == null) ? null : chr.str);
  }

  /**
   * Retrieve the glyph image for a character.
   *
   * @param charId the font-local ID of the character
   * @return the glyph image of the character with the argument ID
   */
  public BufferedImage getImage(int charId) {
    ImCharacter chr = ((ImCharacter) this.characters.get(new Integer(charId)));
    return ((chr == null) ? null : chr.image);
  }

  /**
   * Retrieve the hex representation of the glyph image for a character.
   *
   * @param charId the font-local ID of the character
   * @return the hex representation glyph image of the character with the argument ID
   */
  public String getImageHex(int charId) {
    ImCharacter chr = ((ImCharacter) this.characters.get(new Integer(charId)));
    return ((chr == null) ? null : encodeCharacterImage(chr.image));
  }

  /**
   * Retrieve the IDs of all characters belonging to the font.
   *
   * @return an array holding the character IDs
   */
  public int[] getCharacterIDs() {
    int[] charIDs = new int[this.characters.size()];
    int charIdIndex = 0;
    for (Iterator cidit = this.characters.keySet().iterator(); cidit.hasNext(); )
      charIDs[charIdIndex++] = ((Integer) cidit.next()).intValue();
    return charIDs;
  }

  private static class ImCharacter {
    int id;
    String str;
    BufferedImage image;

    ImCharacter(int id, String str, BufferedImage image) {
      this.id = id;
      this.str = str;
      this.image = image;
    }
  }

  private static final int whiteRgb = Color.WHITE.getRGB();
  private static final int blackRgb = Color.BLACK.getRGB();

  private static BufferedImage decodeCharacterImage(String charImageHex) {
    if (charImageHex == null) return null;
    int charImageWidth = (charImageHex.length() / 8);
    if (charImageWidth == 0) return null;

    BufferedImage charImage = new BufferedImage(charImageWidth, 32, BufferedImage.TYPE_BYTE_BINARY);
    int x = 0;
    int y = 0;
    int hex;
    int hexMask;
    for (int h = 0; h < charImageHex.length(); h++) {
      hex = Integer.parseInt(charImageHex.substring(h, (h + 1)), 16);
      hexMask = 8;
      while (hexMask != 0) {
        charImage.setRGB(x++, y, (((hex & hexMask) == 0) ? whiteRgb : blackRgb));
        hexMask >>= 1;
        if (x == charImageWidth) {
          x = 0;
          y++;
        }
      }
    }

    return charImage;
  }

  private static String encodeCharacterImage(BufferedImage charImage) {
    if (charImage == null) return null;

    int hex = 0;
    int hexBits = 0;
    StringBuffer charImageHex = new StringBuffer();
    for (int y = 0; y < charImage.getHeight(); y++)
      for (int x = 0; x < charImage.getWidth(); x++) {
        if (charImage.getRGB(x, y) != whiteRgb) hex += 1;
        if (hexBits == 3) {
          charImageHex.append(Integer.toString(hex, 16).toUpperCase());
          hex = 0;
          hexBits = 0;
        } else {
          hex <<= 1;
          hexBits++;
        }
      }

    return charImageHex.toString();
  }

  private static boolean characterImagesEqual(BufferedImage ci1, BufferedImage ci2) {
    if (ci1 == ci2) return true;
    if ((ci1 == null) || (ci2 == null)) return false;
    if ((ci1.getWidth() != ci2.getWidth()) || (ci1.getHeight() != ci2.getHeight())) return false;
    for (int x = 0; x < ci1.getWidth(); x++)
      for (int y = 0; y < ci1.getHeight(); y++) {
        if (ci1.getRGB(x, y) != ci2.getRGB(x, y)) return false;
      }
    return true;
  }

  /**
   * Scale a character image to 32 pixels high and proportional width. If the argument image already
   * is 32 pixels in height, it is simply returned. In any case, the type of the returned image is
   * the same as that of the argument image.
   *
   * @param charImage the character image to scale
   * @return the scaled character image
   */
  public static BufferedImage scaleCharImage(BufferedImage charImage) {
    if ((charImage == null) || (charImage.getHeight() == 32)) return charImage;
    BufferedImage sCharImage =
        new BufferedImage(
            Math.max(1, ((charImage.getWidth() * 32) / charImage.getHeight())),
            32,
            charImage.getType());
    Graphics2D sCiGr = sCharImage.createGraphics();
    sCiGr.setColor(Color.WHITE);
    sCiGr.fillRect(0, 0, sCharImage.getWidth(), sCharImage.getHeight());
    sCiGr.scale((32.0 / charImage.getHeight()), (32.0 / charImage.getHeight()));
    sCiGr.drawImage(charImage, 0, 0, null);
    sCiGr.dispose();
    //		JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(charImage)), ("Scaled " +
    // charImage.getWidth() + "x" + charImage.getHeight() + " to " + sCharImage.getWidth() + "x" +
    // sCharImage.getHeight()), JOptionPane.PLAIN_MESSAGE, new ImageIcon(sCharImage));
    return sCharImage;
  }
}