1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 import java.awt.Color; 24 import java.awt.Font; 25 import java.awt.Graphics2D; 26 import java.awt.RenderingHints; 27 import java.awt.image.BufferedImage; 28 import java.io.IOException; 29 30 /** 31 * @test 32 * @bug 8015070 33 * @summary Tests for artifacts around the edges of anti-aliased text 34 * drawn over translucent background color. 35 */ 36 public class AntialiasedTextArtifact { 37 /* Image dimensions */ 38 private static final int TEST_IMAGE_WIDTH = 2800; 39 private static final int TEST_IMAGE_HEIGHT = 100; 40 private static final String TEST_STRING = 41 "The quick brown fox jumps over the lazy dog. 0123456789."; 42 43 /* 44 * The artifacts appear when text is drawn ontop of translucent 45 * background. In other words, a background with alpha channel. 46 * Hence we test the algorithm for image types that contain either 47 * straight alpha channel or pre-multiplied alpha channel. In 48 * addition we test the images with other common pixel formats. 49 */ 50 private static final int[] TYPES = {BufferedImage.TYPE_INT_ARGB, 51 BufferedImage.TYPE_INT_ARGB_PRE, 52 BufferedImage.TYPE_4BYTE_ABGR, 53 BufferedImage.TYPE_4BYTE_ABGR_PRE, 54 BufferedImage.TYPE_INT_RGB, 55 BufferedImage.TYPE_INT_BGR, 56 BufferedImage.TYPE_3BYTE_BGR}; 57 58 public static void main(String[] args) throws IOException { 59 /* Iterate over different image types */ 60 for (int type : TYPES) { 61 BufferedImage testImg = getBufferedImage(type); 62 63 /* Draw anti-aliased string and check for artifacts */ 64 drawAntialiasedString(testImg); 65 checkArtifact(testImg); 66 } 67 } 68 69 private static BufferedImage getBufferedImage(int imageType) { 70 /* Create a Graphics2D object from the given image type */ 71 BufferedImage image = new BufferedImage(TEST_IMAGE_WIDTH, 72 TEST_IMAGE_HEIGHT, 73 imageType); 74 return image; 75 } 76 77 private static void drawAntialiasedString(BufferedImage image) { 78 /* Create Graphics2D object */ 79 Graphics2D graphics = (Graphics2D) image.getGraphics(); 80 81 /* Fill the image with translucent color */ 82 graphics.setColor(new Color(127, 127, 127, 127)); 83 graphics.fillRect(0, 0, TEST_IMAGE_WIDTH, TEST_IMAGE_HEIGHT); 84 85 /* Drawstring with Antialiasing hint */ 86 graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 87 RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 88 Font font = new Font("Verdana" , Font.PLAIN, 60); 89 graphics.setFont(font); 90 graphics.setColor(new Color(255, 0, 0)); 91 graphics.drawString(TEST_STRING, 10, 75); 92 graphics.dispose(); 93 } 94 95 private static void checkArtifact(BufferedImage image) throws IOException { 96 int componentMask = 0xff; 97 int colorThreshold = 200; 98 int rowIndex = 0; 99 int colIndex = 0; 100 101 /* Loop through every pixel to check for possible artifact */ 102 for (rowIndex = 0; rowIndex < image.getHeight(); rowIndex++) { 103 for (colIndex = 0; colIndex < image.getWidth(); colIndex++) { 104 /* 105 * API: getRGB(x,y) returns color in INT_ARGB color space. 106 * Extract individual color components with a simple mask. 107 */ 108 int colorValue = image.getRGB(colIndex, rowIndex); 109 int colorComponent1 = colorValue & componentMask; 110 int colorComponent2 = (colorValue>>8) & componentMask; 111 int colorComponent3 = (colorValue>>16) & componentMask; 112 113 /* 114 * Artifacts are predominantly a subjective decision based on 115 * the quality of the rendered image content. However, in the 116 * current use-case, the artifacts around the edges of the anti 117 * aliased text appear like spots of white pixels without any 118 * relation to the color of foreground text or the background 119 * translucent shape. 120 * 121 * To identify the artifact pixels, each color component from 122 * the testImage is compared with a constant threshold. The 123 * component threshold has been set based on observation from 124 * different experiments on mulitple Java versions. 125 */ 126 if (colorComponent1 >= colorThreshold 127 && colorComponent2 >= colorThreshold 128 && colorComponent3 >= colorThreshold) { 129 /* Artifact has been noticed. Report error. */ 130 throw new RuntimeException("Test Failed."); 131 } 132 } 133 } 134 } 135 }