Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8308148

font antialiasing cannot be turned off in macOS when drawing text on image

XMLWordPrintable

    • 2d
    • aarch64
    • os_x

      ADDITIONAL SYSTEM INFORMATION :
      This bug has existed since macOS Catalina and only occurs on Macs, not Windows. It occurs in all versions of Java since Catalina; I have tested it on Java 8 SE, Java 19 SE, Java 20 SE, and Java 21 SE Early Access.

      A DESCRIPTION OF THE PROBLEM :
      We have a Java application that uses java.awt to draw text and line plots in an image. Since macOS Catalina and still present in macOS Monterey, the text fonts are always antialiased, even though we try to turn the antialiasing completely off.

      The same Java application works as expected in Windows, which properly displays antialiased text and non-antialiased text when specified.

      Included below is an example Java program DrawStringOnImage.java that reproducibly demonstrates the bug.

      Currently we are using OpenJDK 19 64-bit for production use, but this bug has been occurring with versions of Java going back to Java SE 8 and still exists in Java SE 21 Early Access. It also does not seem to matter whether we use OpenJDK or Oracle Java SE on macOS.

      Also, this behavior occurs on multiple Macs. We have tested and observed it on three separate Macs at different (but more recent than Catalina) versions of macOS.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      See the example source code provided by Wayne Rasband, lead developer of ImageJ. The example source code was generated by ChatGPT in response to Wayne's precise query.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Output text drawn on image should be completely non-antialiased.
      ACTUAL -
      Output text drawn on image is always antialiased.

      ---------- BEGIN SOURCE ----------
      import java.awt.Color;
      import java.awt.Font;
      import java.awt.FontMetrics;
      import java.awt.Graphics;
      import java.awt.Graphics2D;
      import java.awt.RenderingHints;
      import java.awt.image.BufferedImage;
      import javax.swing.ImageIcon;
      import javax.swing.JFrame;
      import javax.swing.JLabel;

      public class DrawStringOnImage {
          public static void main(String[] args) {
              // Get Java version and OS name
              String javaVersion = System.getProperty("java.version");
              String osName = System.getProperty("os.name");

              // Create a BufferedImage with desired width and height
              int width = 400;
              int height = 200;
              BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

              // Get the Graphics object for the BufferedImage
              Graphics2D g2d = image.createGraphics();

              // Disable antialiasing
              g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);

              // Set background color
              g2d.setColor(Color.WHITE);
              g2d.fillRect(0, 0, width, height);

              // Set font and color for the text
              Font font = new Font("Arial", Font.BOLD, 24);
              g2d.setFont(font);
              g2d.setColor(Color.BLACK);

              // Draw the Java version and OS name on the BufferedImage
              FontMetrics fm = g2d.getFontMetrics();
              int javaVersionWidth = fm.stringWidth("Java version: " + javaVersion);
              int osNameWidth = fm.stringWidth("OS: " + osName);
              int x = (width - Math.max(javaVersionWidth, osNameWidth)) / 2;
              int y = (height - fm.getHeight()) / 2;
              g2d.drawString("Java version: " + javaVersion, x, y);
              g2d.drawString("OS: " + osName, x, y + fm.getHeight());

              // Dispose the Graphics object
              g2d.dispose();

              // Create a JFrame to display the BufferedImage
              JFrame frame = new JFrame("Image with Text");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

              // Create a JLabel with the ImageIcon
              ImageIcon icon = new ImageIcon(image);
              JLabel label = new JLabel(icon);

              // Add the JLabel to the JFrame
              frame.getContentPane().add(label);

              // Adjust the size of the JFrame to fit the image
              frame.pack();

              // Set the JFrame to be visible
              frame.setVisible(true);
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      No workaround found yet. We have been searching hard for one, but no luck.
      The only "workaround" is to use Windows instead of Macs, but we don't realistically have that option.

      FREQUENCY : always


            prr Philip Race
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: