All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.monte.media.image.SubpixAA Maven / Gradle / Ivy

There is a newer version: 1.1
Show newest version
/*
 * @(#)SubpixAA.java  1.0  2009-12-11
 * 
 * Copyright (c) 2009 Werner Randelshofer, Goldau, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */
package org.monte.media.image;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.ImageObserver;
import java.awt.image.WritableRaster;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Scales an image down and applies Subpixel antialiasing to it.
 *
 * @author Werner Randelshofer
 * @version 1.0 2009-12-11 Created.
 */
public class SubpixAA {

    public final static Object HBGR;
    public final static Object VBGR;
    public final static Object HRGB;
    public final static Object VRGB;

    static {
        Object hbgr, vbgr, hrgb, vrgb;
        try {
            vbgr = RenderingHints.class.getField("VALUE_TEXT_ANTIALIAS_LCD_VBGR").get(null);
            vrgb = RenderingHints.class.getField("VALUE_TEXT_ANTIALIAS_LCD_VRGB").get(null);
            hbgr = RenderingHints.class.getField("VALUE_TEXT_ANTIALIAS_LCD_HBGR").get(null);
            hrgb = RenderingHints.class.getField("VALUE_TEXT_ANTIALIAS_LCD_HRGB").get(null);
        } catch (Exception ex) {
            hrgb = "HRGB";
            hbgr = "HBGR";
            vrgb = "VRGB";
            vbgr = "VBGR";
        }
        HBGR = hbgr;
        HRGB = hrgb;
        VBGR = vrgb;
        VRGB = vbgr;
    }
    /** Source image buffer. */
    private BufferedImage sBuf;
    /** Destination image buffer. */
    private BufferedImage dBuf;

    /*
    private static void setup(Graphics gr) {
    Graphics2D g = (Graphics2D) gr;
    g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
    g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
    }

    private static void setup2(Graphics gr) {
    Graphics2D g = (Graphics2D) gr;
    g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
    g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
    }

    public static void main(String[] args) {
    System.setProperty("apple.awt.graphics.UseQuartz", "false");
    GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode();
    Map map = (Map) Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints");
    System.out.println(map);

    SwingUtilities.invokeLater(new Runnable() {

    public void run() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setSize(430, 340);
    f.setLocation(0, 180);
    f.setTitle("SubpixAA");
    JPanel p = new JPanel() {
    
    public void update(Graphics g) {
    paint(g);
    }

    public void paint(Graphics gr) {
    Graphics2D g = (Graphics2D) gr;
    setup(g);
    Font f = new Font("Times New Roman", Font.PLAIN, 18);

    g.setFont(f);
    g.setColor(Color.white);
    g.fillRect(0, 0, size().width, size().height);
    g.setColor(Color.black);
    int y = 5;
    g.drawString("Sample Text String", 5, y + getFontMetrics(f).getAscent());
    y += getFontMetrics(f).getHeight();
    drawClearType(g, "Sample Text String", 5, y += getFontMetrics(f).getHeight(), RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
    drawClearType(g, "Sample Text String", 5, y += getFontMetrics(f).getHeight(), RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    drawClearType(g, "Sample Text String", 5, y += getFontMetrics(f).getHeight(), RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
    drawClearType(g, "Sample Text String", 5, y += getFontMetrics(f).getHeight() * 2, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR);
    drawClearType(g, "Sample Text String", 5, y += getFontMetrics(f).getHeight() * 2, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB);
    drawClearType(g, "Sample Text String", 5, y += getFontMetrics(f).getHeight() * 3, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR);
    }

    public void drawClearType(Graphics g, String s, int x, int y, Object method) {
    Font f = g.getFont();
    FontMetrics fm = getFontMetrics(f);
    int sw = fm.stringWidth(s);
    int sh = fm.getHeight();
    Dimension dim = getSourceDimension(sw, sh, method);
    int width = dim.width;
    int height = dim.height;
    BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    Graphics2D grph = img.createGraphics();
    setup2(grph);
    grph.setColor(Color.white);
    grph.fillRect(0, 0, width, height);
    grph.setColor(Color.black);
    grph.setFont(f.deriveFont(AffineTransform.getScaleInstance(dim.width / sw, dim.height / sh)));
    grph.drawString(s, 0, grph.getFontMetrics().getMaxAscent());
    grph.dispose();
    SubpixAA aa = new SubpixAA();
    aa.drawAA(g, img, x, y - sh, sw, sh, method, this);
    g.drawImage(img, x, y, this);
    }
    };
    f.setContentPane(p);
    f.setVisible(true);
    }
    });


    }*/
    /** Renders an image with subpixel antialiasing.
     *
     * This method uses caching to improve the performance of subsequent calls.
     *
     * The image must be larger than the destination width and height.
     */
    public void drawAA(Graphics gr, BufferedImage img, int x, int y, int width, int height, ImageObserver observer) {
        Graphics2D g = (Graphics2D) gr;
        drawAA(gr, img, x, y, width, height, g.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING), observer);
    }

    /** Renders an image with subpixel antialiasing.
     *
     * This method uses caching to improve the performance of subsequent calls.
     *
     * The image must be larger than the destination width and height.
     */
    public void drawAA(Graphics gr, BufferedImage img, int x, int y, int width, int height, Object method, ImageObserver observer) {
        // If the image dimension matches width and height, draw it as is.
        if (img.getWidth() == width && img.getHeight() == height) {
            gr.drawImage(img, x, y, observer);
            return;
        }

        Graphics2D g = (Graphics2D) gr;
        // Rescale the image if it does not have the right size for the
        // subpixel antialiasing method.
        Dimension sdim = getSourceDimension(width, height, method);
        if (img.getWidth() != sdim.width || img.getHeight() != sdim.height) {
            if (sBuf == null || sBuf.getWidth() != sdim.width || sBuf.getHeight() != sdim.height) {
                sBuf = new BufferedImage(sdim.width, sdim.height, BufferedImage.TYPE_INT_RGB);
            }
            Graphics2D sg = sBuf.createGraphics();
            setupRendering(sg);
            sg.drawImage(img, 0, 0, sdim.width, sdim.height, null);
            //System.out.println("rescale " + img.getWidth() + "," + img.getHeight() + " to " + sBuf.getWidth() + "," + sBuf.getHeight());
            sg.dispose();
            img = sBuf;
        }
        if (dBuf == null || dBuf.getWidth() != width || dBuf.getHeight() != height) {
            dBuf = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        }

        aa(img, dBuf, method);

        g.drawImage(dBuf, x, y, observer);
    }

    /** Returns the dimensions needed of the source image for the desired
     * destination image size.
     *
     * @param width The desired width of the destination image.
     * @param height The desired height of the destination image.
     * @param method The Antialiasing method to be used must be one of
     * {@code RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB}, {@code ..._HBGR},
     */
    public static Dimension getSourceDimension(int width, int height, Object method) {
        Dimension dim;
        if (method == HRGB ||//
                method == HBGR) {
            dim = new Dimension(width * 3, height);
        } else if (method == VRGB ||//
                method == VBGR) {
            dim = new Dimension(width, height * 3);
        } else {
            dim = new Dimension(width, height);
        }
        return dim;
    }

    /** Scales down an image using the specified antialiasing method.
     * 

* For methods {@code HBGR} and {@code HRGB}, the image width is scaled down * by factor 3. * For methods {@code VBGR} and {@code VRGB}, the image height is scaled down * by factor 3. * * @param src The source image. * @param dst The destination image. * @param m The method. */ public static void aa(BufferedImage src, BufferedImage dst, Object m) { if (m == HRGB) { aaHRGB(src, dst); } else if (m == HBGR) { aaHBGR(src, dst); } else if (m == VRGB) { aaVRGB(src, dst); } else if (m == VBGR) { aaVBGR(src, dst); } else { Graphics2D g = dst.createGraphics(); setupRendering(g); g.drawImage(src, 0, 0, dst.getWidth(), dst.getHeight(), null); g.dispose(); } } /** * Set up the graphics transform to match the clip region * to the image size. */ private static void setupRendering(Graphics2D g) { g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); //getToolkit(). } /** Scales down an image using HRGB antia-aliasing. *

* Source and destination image must be of type BufferedImage.TYPE_RGB * and have a data buffer of type DataBufferInt. *

* The height of source and destination image must be the same. * The width of the source image must be 3 times the width of the * destination image. *

* Intensity weights: *

     *
     *            1
     *            |
     *       +----+----+
     *       |    |    |
     *      1/3  1/3  1/3
     *            |
     *  +----+----+----+----+
     *  |    |    |    |    |
     * 1/9  2/9  3/9  2/9  1/9
     * 
* * @param src The source image. * @param dst The destination image. */ public static void aaHRGB(BufferedImage src, BufferedImage dst) { WritableRaster sras = src.getRaster(); WritableRaster dras = dst.getRaster(); int[] s = ((DataBufferInt) sras.getDataBuffer()).getData(); int[] d = ((DataBufferInt) dras.getDataBuffer()).getData(); int sw = src.getWidth(); int sh = src.getHeight(); int dw = dst.getWidth(); int dh = dst.getHeight(); // weights:left-left,left,center,right,right-right,total //final int wll = 0, wl = 0, wc = 1, wr = 0, wrr = 0, tw = wll + wl + wc + wr + wrr; //final int wll = 0, wl = 1, wc = 1, wr = 1, wrr = 0, tw = wll+wl+wc+wr+wrr; final int wll = 1, wl = 2, wc = 3, wr = 2, wrr = 1, tw = wll + wl + wc + wr + wrr; for (int y = 0; y < dh; y++) { int sxy = y * sw; int dxy = y * dw; int dxyeol = dxy + dw - 1; // Process the first pixel of the line. d[dxy] =// // Red component: ((// (s[sxy + 0] & 0xff0000) * (wll + wl + wc) +// (s[sxy + 1] & 0xff0000) * wr +// (s[sxy + 2] & 0xff0000) * wrr// ) / tw & 0xff0000) | // // Green component: ((// (s[sxy + 0] & 0x00ff00) * (wll + wl) + // (s[sxy + 1] & 0x00ff00) * wc + // (s[sxy + 2] & 0x00ff00) * wr + // (s[sxy + 3] & 0x00ff00) * wrr// ) / tw & 0x00ff00) | // // Blue component: ((// (s[sxy + 0] & 0x0000ff) * wll + // (s[sxy + 1] & 0x0000ff) * wl + // (s[sxy + 2] & 0x0000ff) * wc + // (s[sxy + 3] & 0x0000ff) * wr +// (s[sxy + 4] & 0x0000ff) * wrr// ) / tw); sxy += 3; dxy++; // Process the pixels in the middle of the line. for (; dxy < dxyeol; sxy += 3, dxy++) { d[dxy] =// // Red component: ((// (s[sxy - 2] & 0xff0000) * wll + // (s[sxy - 1] & 0xff0000) * wl + // (s[sxy + 0] & 0xff0000) * wc + // (s[sxy + 1] & 0xff0000) * wr +// (s[sxy + 2] & 0xff0000) * wrr// ) / tw & 0xff0000) | // // Green component: ((// (s[sxy - 1] & 0x00ff00) * wll +// (s[sxy - 0] & 0x00ff00) * wl + // (s[sxy + 1] & 0x00ff00) * wc + // (s[sxy + 2] & 0x00ff00) * wr + // (s[sxy + 3] & 0x00ff00) * wrr// ) / tw & 0x00ff00) | // // Blue component: ((// (s[sxy + 0] & 0x0000ff) * wll + // (s[sxy + 1] & 0x0000ff) * wl + // (s[sxy + 2] & 0x0000ff) * wc + // (s[sxy + 3] & 0x0000ff) * wr +// (s[sxy + 4] & 0x0000ff) * wrr// ) / tw); /* if (x == 2) { System.out.println("y:" + y + " sxy:" + sxy + " :" + Integer.toHexString(s[sxy]).substring(2) + " " + Integer.toHexString(s[sxy + 1]).substring(2) + " " + Integer.toHexString(s[sxy + 2]).substring(2) + ":" + Integer.toHexString(0xff00000 | d[dxy]).substring(2)); }*/ } // Process the last pixel on the line d[dxy] =// // Red component: ((// (s[sxy - 2] & 0xff0000) * wll + // (s[sxy - 1] & 0xff0000) * wl + // (s[sxy + 0] & 0xff0000) * wc + // (s[sxy + 1] & 0xff0000) * wr +// (s[sxy + 2] & 0xff0000) * wrr// ) / tw & 0xff0000) | // // Green component: ((// (s[sxy - 1] & 0x00ff00) * wll +// (s[sxy + 0] & 0x00ff00) * wl + // (s[sxy + 1] & 0x00ff00) * wc + // (s[sxy + 2] & 0x00ff00) * (wr + wrr) // ) / tw & 0x00ff00) | // // Blue component: ((// (s[sxy + 0] & 0x0000ff) * wll + // (s[sxy + 1] & 0x0000ff) * wl + // (s[sxy + 2] & 0x0000ff) * (wc + wr + wrr) // ) / tw); } } /** Scales down an image using HBGR antia-aliasing. *

* Source and destination image must be of type BufferedImage.TYPE_RGB * and have a data buffer of type DataBufferInt. *

* The height of source and destination image must be the same. * The width of the source image must be 3 times the width of the * destination image. *

* Intensity weights: *

     *
     *            1
     *            |
     *       +----+----+
     *       |    |    |
     *      1/3  1/3  1/3
     *            |
     *  +----+----+----+----+
     *  |    |    |    |    |
     * 1/9  2/9  3/9  2/9  1/9
     * 
* * @param src The source image. * @param dst The destination image. */ public static void aaHBGR(BufferedImage src, BufferedImage dst) { WritableRaster sras = src.getRaster(); WritableRaster dras = dst.getRaster(); int[] s = ((DataBufferInt) sras.getDataBuffer()).getData(); int[] d = ((DataBufferInt) dras.getDataBuffer()).getData(); int sw = src.getWidth(); int sh = src.getHeight(); int dw = dst.getWidth(); int dh = dst.getHeight(); // weights:left-left,left,center,right,right-right,total //final int wll = 0, wl = 0, wc = 1, wr = 0, wrr = 0, tw = wll + wl + wc + wr + wrr; final int wll = 1, wl = 2, wc = 3, wr = 2, wrr = 1, tw = wll + wl + wc + wr + wrr; for (int y = 0; y < dh; y++) { int sxy = y * sw; int dxy = y * dw; int dxyeol = dxy + dw - 1; // Process the first pixel of the line. d[dxy] =// // Blue component: ((// (s[sxy + 0] & 0x0000ff) * (wll + wl + wc) +// (s[sxy + 1] & 0x0000ff) * wr +// (s[sxy + 2] & 0x0000ff) * wrr// ) / tw) | // // Green component: ((// (s[sxy + 0] & 0x00ff00) * (wll + wl) + // (s[sxy + 1] & 0x00ff00) * wc + // (s[sxy + 2] & 0x00ff00) * wr + // (s[sxy + 3] & 0x00ff00) * wrr// ) / tw & 0x00ff00) | // // Red component: ((// (s[sxy + 0] & 0xff0000) * wll + // (s[sxy + 1] & 0xff0000) * wl + // (s[sxy + 2] & 0xff0000) * wc + // (s[sxy + 3] & 0xff0000) * wr +// (s[sxy + 4] & 0xff0000) * wrr// ) / tw & 0xff0000); sxy += 3; dxy++; // Process the pixels in the middle of the line. for (; dxy < dxyeol; sxy += 3, dxy++) { d[dxy] =// // Blue component: ((// (s[sxy - 2] & 0x0000ff) * wll + // (s[sxy - 1] & 0x0000ff) * wl + // (s[sxy + 0] & 0x0000ff) * wc + // (s[sxy + 1] & 0x0000ff) * wr +// (s[sxy + 2] & 0x0000ff) * wrr// ) / tw) | // // Green component: ((// (s[sxy - 1] & 0x00ff00) * wll +// (s[sxy + 0] & 0x00ff00) * wl + // (s[sxy + 1] & 0x00ff00) * wc + // (s[sxy + 2] & 0x00ff00) * wr + // (s[sxy + 3] & 0x00ff00) * wrr// ) / tw & 0x00ff00) | // // Red component: ((// (s[sxy + 0] & 0xff0000) * wll + // (s[sxy + 1] & 0xff0000) * wl + // (s[sxy + 2] & 0xff0000) * wc + // (s[sxy + 3] & 0xff0000) * wr +// (s[sxy + 4] & 0xff0000) * wrr// ) / tw & 0xff0000); /* if (x == 2) { System.out.println("y:" + y + " sxy:" + sxy + " :" + Integer.toHexString(s[sxy]).substring(2) + " " + Integer.toHexString(s[sxy + 1]).substring(2) + " " + Integer.toHexString(s[sxy + 2]).substring(2) + ":" + Integer.toHexString(0xff00000 | d[dxy]).substring(2)); }*/ } // Process the last pixel on the line d[dxy] =// // Blue component: ((// (s[sxy - 2] & 0x0000ff) * wll + // (s[sxy - 1] & 0x0000ff) * wl + // (s[sxy + 0] & 0x0000ff) * wc + // (s[sxy + 1] & 0x0000ff) * wr +// (s[sxy + 2] & 0x0000ff) * wrr// ) / tw) | // // Green component: ((// (s[sxy - 1] & 0x00ff00) * wll +// (s[sxy + 0] & 0x00ff00) * wl + // (s[sxy + 1] & 0x00ff00) * wc + // (s[sxy + 2] & 0x00ff00) * (wr + wrr) // ) / tw & 0x00ff00) | // // Red component: ((// (s[sxy + 0] & 0xff0000) * wll + // (s[sxy + 1] & 0xff0000) * wl + // (s[sxy + 2] & 0xff0000) * (wc + wr + wrr) // ) / tw & 0xff0000); } } /** Scales down an image using VRGB antia-aliasing. *

* Source and destination image must be of type BufferedImage.TYPE_RGB * and have a data buffer of type DataBufferInt. *

* The width of source and destination image must be the same. * The height of the source image must be 3 times the height of the * destination image. *

* Intensity weights: *

     *
     *            1
     *            |
     *       +----+----+
     *       |    |    |
     *      1/3  1/3  1/3
     *            |
     *  +----+----+----+----+
     *  |    |    |    |    |
     * 1/9  2/9  3/9  2/9  1/9
     * 
* * @param src The source image. * @param dst The destination image. */ public static void aaVRGB(BufferedImage src, BufferedImage dst) { WritableRaster sras = src.getRaster(); WritableRaster dras = dst.getRaster(); int[] s = ((DataBufferInt) sras.getDataBuffer()).getData(); int[] d = ((DataBufferInt) dras.getDataBuffer()).getData(); int sw = src.getWidth(); int sh = src.getHeight(); int dw = dst.getWidth(); int dh = dst.getHeight(); // weights:left-left,left,center,right,right-right,total //final int wll = 0, wl = 0, wc = 1, wr = 0, wrr = 0, tw = wll + wl + wc + wr + wrr; //final int wll = 0, wl = 1, wc = 1, wr = 1, wrr = 0, tw = wll+wl+wc+wr+wrr; final int wll = 1, wl = 2, wc = 3, wr = 2, wrr = 1, tw = wll + wl + wc + wr + wrr; for (int x = 0; x < dw; x++) { int sxy = x; int dxy = x; int dxyeol = dxy + dw * (dh - 1); // Process the first pixel of the line. d[dxy] =// // Red component: ((// (s[sxy + 0] & 0xff0000) * (wll + wl + wc) +// (s[sxy + sw] & 0xff0000) * wr +// (s[sxy + sw * 2] & 0xff0000) * wrr// ) / tw & 0xff0000) | // // Green component: ((// (s[sxy + 0] & 0x00ff00) * (wll + wl) + // (s[sxy + sw] & 0x00ff00) * wc + // (s[sxy + sw * 2] & 0x00ff00) * wr + // (s[sxy + sw * 3] & 0x00ff00) * wrr// ) / tw & 0x00ff00) | // // Blue component: ((// (s[sxy + 0] & 0x0000ff) * wll + // (s[sxy + sw] & 0x0000ff) * wl + // (s[sxy + sw * 2] & 0x0000ff) * wc + // (s[sxy + sw * 3] & 0x0000ff) * wr +// (s[sxy + sw * 4] & 0x0000ff) * wrr// ) / tw); sxy += 3 * sw; dxy += dw; // Process the pixels in the middle of the line. for (; dxy < dxyeol; sxy += 3 * sw, dxy += dw) { d[dxy] =// // Red component: ((// (s[sxy - sw * 2] & 0xff0000) * wll + // (s[sxy - sw] & 0xff0000) * wl + // (s[sxy + 0] & 0xff0000) * wc + // (s[sxy + sw] & 0xff0000) * wr +// (s[sxy + sw * 2] & 0xff0000) * wrr// ) / tw & 0xff0000) | // // Green component: ((// (s[sxy - sw] & 0x00ff00) * wll +// (s[sxy - 0] & 0x00ff00) * wl + // (s[sxy + sw] & 0x00ff00) * wc + // (s[sxy + sw * 2] & 0x00ff00) * wr + // (s[sxy + sw * 3] & 0x00ff00) * wrr// ) / tw & 0x00ff00) | // // Blue component: ((// (s[sxy + 0] & 0x0000ff) * wll + // (s[sxy + sw] & 0x0000ff) * wl + // (s[sxy + sw * 2] & 0x0000ff) * wc + // (s[sxy + sw * 3] & 0x0000ff) * wr +// (s[sxy + sw * 4] & 0x0000ff) * wrr// ) / tw); /* if (dxy <= dw*2) { System.out.println("x:" + x + " sxy:" + sxy + " :" + Integer.toHexString(s[sxy]).substring(2) + " " + Integer.toHexString(s[sxy + 1]).substring(2) + " " + Integer.toHexString(s[sxy + 2]).substring(2) + ":" + Integer.toHexString(0xff00000 | d[dxy]).substring(2)); }*/ } // Process the last pixel on the line d[dxy] =// // Red component: ((// (s[sxy - sw * 2] & 0xff0000) * wll + // (s[sxy - sw] & 0xff0000) * wl + // (s[sxy + 0] & 0xff0000) * wc + // (s[sxy + sw] & 0xff0000) * wr +// (s[sxy + sw * 2] & 0xff0000) * wrr// ) / tw & 0xff0000) | // // Green component: ((// (s[sxy - sw] & 0x00ff00) * wll +// (s[sxy + 0] & 0x00ff00) * wl + // (s[sxy + sw] & 0x00ff00) * wc + // (s[sxy + sw * 2] & 0x00ff00) * (wr + wrr) // ) / tw & 0x00ff00) | // // Blue component: ((// (s[sxy + 0] & 0x0000ff) * wll + // (s[sxy + sw] & 0x0000ff) * wl + // (s[sxy + sw * 2] & 0x0000ff) * (wc + wr + wrr) // ) / tw); } } /** Scales down an image using VBGR antia-aliasing. *

* Source and destination image must be of type BufferedImage.TYPE_RGB * and have a data buffer of type DataBufferInt. *

* The width of source and destination image must be the same. * The height of the source image must be 3 times the height of the * destination image. *

* Intensity weights: *

     *
     *            1
     *            |
     *       +----+----+
     *       |    |    |
     *      1/3  1/3  1/3
     *            |
     *  +----+----+----+----+
     *  |    |    |    |    |
     * 1/9  2/9  3/9  2/9  1/9
     * 
* * @param src The source image. * @param dst The destination image. */ public static void aaVBGR(BufferedImage src, BufferedImage dst) { WritableRaster sras = src.getRaster(); WritableRaster dras = dst.getRaster(); int[] s = ((DataBufferInt) sras.getDataBuffer()).getData(); int[] d = ((DataBufferInt) dras.getDataBuffer()).getData(); int sw = src.getWidth(); int sh = src.getHeight(); int dw = dst.getWidth(); int dh = dst.getHeight(); // weights:left-left,left,center,right,right-right,total //final int wll = 0, wl = 0, wc = 1, wr = 0, wrr = 0, tw = wll + wl + wc + wr + wrr; //final int wll = 0, wl = 1, wc = 1, wr = 1, wrr = 0, tw = wll+wl+wc+wr+wrr; final int wll = 1, wl = 2, wc = 3, wr = 2, wrr = 1, tw = wll + wl + wc + wr + wrr; for (int x = 0; x < dw; x++) { int sxy = x; int dxy = x; int dxyeol = dxy + dw * (dh - 1); // Process the first pixel of the line. d[dxy] =// // Blue component: ((// (s[sxy + 0] & 0x0000ff) * (wll + wl + wc) +// (s[sxy + sw] & 0x0000ff) * wr +// (s[sxy + sw * 2] & 0x0000ff) * wrr// ) / tw) | // // Green component: ((// (s[sxy + 0] & 0x00ff00) * (wll + wl) + // (s[sxy + sw] & 0x00ff00) * wc + // (s[sxy + sw * 2] & 0x00ff00) * wr + // (s[sxy + sw * 3] & 0x00ff00) * wrr// ) / tw & 0x00ff00) | // // Red component: ((// (s[sxy + 0] & 0xff0000) * wll + // (s[sxy + sw] & 0xff0000) * wl + // (s[sxy + sw * 2] & 0xff0000) * wc + // (s[sxy + sw * 3] & 0xff0000) * wr +// (s[sxy + sw * 4] & 0xff0000) * wrr// ) / tw & 0xff0000); sxy += 3 * sw; dxy += dw; // Process the pixels in the middle of the line. for (; dxy < dxyeol; sxy += 3 * sw, dxy += dw) { d[dxy] =// // Blue component: ((// (s[sxy - sw * 2] & 0x0000ff) * wll + // (s[sxy - sw] & 0x0000ff) * wl + // (s[sxy + 0] & 0x0000ff) * wc + // (s[sxy + sw] & 0x0000ff) * wr +// (s[sxy + sw * 2] & 0x0000ff) * wrr// ) / tw) | // // Green component: ((// (s[sxy - sw] & 0x00ff00) * wll +// (s[sxy - 0] & 0x00ff00) * wl + // (s[sxy + sw] & 0x00ff00) * wc + // (s[sxy + sw * 2] & 0x00ff00) * wr + // (s[sxy + sw * 3] & 0x00ff00) * wrr// ) / tw & 0x00ff00) | // // Red component: ((// (s[sxy + 0] & 0xff0000) * wll + // (s[sxy + sw] & 0xff0000) * wl + // (s[sxy + sw * 2] & 0xff0000) * wc + // (s[sxy + sw * 3] & 0xff0000) * wr +// (s[sxy + sw * 4] & 0xff0000) * wrr// ) / tw & 0xff0000); /* if (dxy <= dw*2) { System.out.println("x:" + x + " sxy:" + sxy + " :" + Integer.toHexString(s[sxy]).substring(2) + " " + Integer.toHexString(s[sxy + 1]).substring(2) + " " + Integer.toHexString(s[sxy + 2]).substring(2) + ":" + Integer.toHexString(0xff00000 | d[dxy]).substring(2)); }*/ } // Process the last pixel on the line d[dxy] =// // Blue component: ((// (s[sxy - sw * 2] & 0x0000ff) * wll + // (s[sxy - sw] & 0x0000ff) * wl + // (s[sxy + 0] & 0x0000ff) * wc + // (s[sxy + sw] & 0x0000ff) * wr +// (s[sxy + sw * 2] & 0x0000ff) * wrr// ) / tw) | // // Green component: ((// (s[sxy - sw] & 0x00ff00) * wll +// (s[sxy + 0] & 0x00ff00) * wl + // (s[sxy + sw] & 0x00ff00) * wc + // (s[sxy + sw * 2] & 0x00ff00) * (wr + wrr) // ) / tw & 0x00ff00) | // // Red component: ((// (s[sxy + 0] & 0xff0000) * wll + // (s[sxy + sw] & 0xff0000) * wl + // (s[sxy + sw * 2] & 0xff0000) * (wc + wr + wrr) // ) / tw & 0xff0000); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy