Changeset 13038 in josm


Ignore:
Timestamp:
2017-10-25T23:26:40+02:00 (3 weeks ago)
Author:
Don-vip
Message:

fix #15476 - Antialiased text and better resize quality when viewing photos

Location:
trunk/src/org/openstreetmap/josm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java

    r12846 r13038  
    1313import java.awt.Point;
    1414import java.awt.Rectangle;
     15import java.awt.RenderingHints;
    1516import java.awt.Toolkit;
    1617import java.awt.event.MouseEvent;
     
    2829import org.openstreetmap.josm.spi.preferences.Config;
    2930import org.openstreetmap.josm.tools.ExifReader;
     31import org.openstreetmap.josm.tools.ImageProvider;
    3032import org.openstreetmap.josm.tools.Logging;
    3133
     
    461463    }
    462464
     465    /**
     466     * Sets the On-Screen-Display text.
     467     * @param text text to display on top of the image
     468     */
    463469    public void setOsdText(String text) {
    464470        this.osdText = text;
     
    478484            visibleRect = this.visibleRect;
    479485            errorLoading = this.errorLoading;
     486        }
     487
     488        if (g instanceof Graphics2D) {
     489            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    480490        }
    481491
     
    502512        } else {
    503513            Rectangle target = calculateDrawImageRectangle(visibleRect, size);
    504             g.drawImage(image,
    505                     target.x, target.y, target.x + target.width, target.y + target.height,
    506                     visibleRect.x, visibleRect.y, visibleRect.x + visibleRect.width, visibleRect.y + visibleRect.height,
    507                     null);
     514            // See https://community.oracle.com/docs/DOC-983611 - The Perils of Image.getScaledInstance()
     515            // Pre-scale image when downscaling by more than two times to avoid aliasing from default algorithm
     516            if (selectedRect == null && (target.width < visibleRect.width/2 || target.height < visibleRect.height/2)) {
     517                BufferedImage buffImage = ImageProvider.toBufferedImage(image);
     518                g.drawImage(ImageProvider.createScaledImage(buffImage, target.width, target.height, RenderingHints.VALUE_INTERPOLATION_BILINEAR),
     519                        target.x, target.y, target.x + target.width, target.y + target.height,
     520                        visibleRect.x, visibleRect.y, visibleRect.x + target.width, visibleRect.y + target.height,
     521                        null);
     522            } else {
     523                g.drawImage(image,
     524                        target.x, target.y, target.x + target.width, target.y + target.height,
     525                        visibleRect.x, visibleRect.y, visibleRect.x + visibleRect.width, visibleRect.y + visibleRect.height,
     526                        null);
     527            }
    508528            if (selectedRect != null) {
    509529                Point topLeft = img2compCoord(visibleRect, selectedRect.x, selectedRect.y, size);
  • trunk/src/org/openstreetmap/josm/tools/ImageProvider.java

    r12937 r13038  
    13941394
    13951395    /**
     1396     * Returns a scaled instance of the provided {@code BufferedImage}.
     1397     * This method will use a multi-step scaling technique that provides higher quality than the usual
     1398     * one-step technique (only useful in downscaling cases, where {@code targetWidth} or {@code targetHeight} is
     1399     * smaller than the original dimensions, and generally only when the {@code BILINEAR} hint is specified).
     1400     *
     1401     * From https://community.oracle.com/docs/DOC-983611: "The Perils of Image.getScaledInstance()"
     1402     *
     1403     * @param img the original image to be scaled
     1404     * @param targetWidth the desired width of the scaled instance, in pixels
     1405     * @param targetHeight the desired height of the scaled instance, in pixels
     1406     * @param hint one of the rendering hints that corresponds to
     1407     * {@code RenderingHints.KEY_INTERPOLATION} (e.g.
     1408     * {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR},
     1409     * {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR},
     1410     * {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC})
     1411     * @return a scaled version of the original {@code BufferedImage}
     1412     * @since 13038
     1413     */
     1414    public static BufferedImage createScaledImage(BufferedImage img, int targetWidth, int targetHeight, Object hint) {
     1415        int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
     1416        // start with original size, then scale down in multiple passes with drawImage() until the target size is reached
     1417        BufferedImage ret = img;
     1418        int w = img.getWidth(null);
     1419        int h = img.getHeight(null);
     1420        do {
     1421            if (w > targetWidth) {
     1422                w /= 2;
     1423                if (w < targetWidth) {
     1424                    w = targetWidth;
     1425                }
     1426            }
     1427            if (h > targetHeight) {
     1428                h /= 2;
     1429                if (h < targetHeight) {
     1430                    h = targetHeight;
     1431                }
     1432            }
     1433            BufferedImage tmp = new BufferedImage(w, h, type);
     1434            Graphics2D g2 = tmp.createGraphics();
     1435            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
     1436            g2.drawImage(ret, 0, 0, w, h, null);
     1437            g2.dispose();
     1438            ret = tmp;
     1439        } while (w != targetWidth || h != targetHeight);
     1440        return ret;
     1441    }
     1442
     1443    /**
    13961444     * Replies the icon for an OSM primitive type
    13971445     * @param type the type
     
    19101958        }
    19111959    }
     1960
     1961    /**
     1962     * Converts an {@link Image} to a {@link BufferedImage} instance.
     1963     * @param image image to convert
     1964     * @return a {@code BufferedImage} instance for the given {@code Image}.
     1965     * @since 13038
     1966     */
     1967    public static BufferedImage toBufferedImage(Image image) {
     1968        if (image instanceof BufferedImage) {
     1969            return (BufferedImage) image;
     1970        } else {
     1971            BufferedImage buffImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
     1972            Graphics2D g2 = buffImage.createGraphics();
     1973            g2.drawImage(image, 0, 0, null);
     1974            g2.dispose();
     1975            return buffImage;
     1976        }
     1977    }
    19121978}
Note: See TracChangeset for help on using the changeset viewer.