Re: [OpenMap Users] OMPoly - fill with translucent fillPattern ?

From: Don Dietrick <dietrick@bbn.com>
Date: Wed Mar 12 2003 - 09:06:44 EST

Hi Matt,

I think there is a problem with the way that DrawingAttributes is
calling the BufferedImageHelper to create the image. If an image type
isn't specified, it assumes that you want a RGB image, which is why the
fill pattern is opaque. I've modified the BufferedImageHelper so that
images created from URLs or Paths are created with ARGB image types.
That seems to be more intuitive anyway.

On Wednesday, March 12, 2003, at 06:11 AM, Matt Brennan wrote:

> Hello,
> I'd very much like to fill an OMPoly in a Layer with a translucent
> crosshatch pattern (an opaque set of lines with transparent areas
> revealing other layers). Using a DrawingAttribute, I've loaded a
> fillPattern of a (mostly transparent) GIF and used this to fill the
> poly (omPoly.setFillPaint(drawingAttributes.getFillPattern())).
>
> However, when rendered, the GIF in the OMPoly appears completely
> opaque onscreen and indeed:
>
> ((Transparency) obj).getTransparency() == Transparency.OPAQUE
>
> The 'background' Color 'behind' the GIF is white (which is a little
> interesting... why is this the default color and could I change the
> Alpha?).

I think that is the color used by the gif to represent the transparent
color - since the alpha channel is being ignored, the other values take
over.

> My question is, short of manually rendering a crosshatch pattern, have
> you any suggestions for creating a translucent textured fill for an
> OMPoly?

You could create the image and TexturePaint yourself with the
BufferedImageHelper and calling the methods that set the ARGB image
type, setting that in the fillPattern of your OMGraphics.

I've included the version of BufferedImageHelper that is going to be in
the next version of OpenMap that has the changes.

- Don

// **********************************************************************
//
// <copyright>
//
// BBN Technologies, a Verizon Company
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/image/BufferedImageHelper.java,v $
// $RCSfile: BufferedImageHelper.java,v $
// $Revision: 1.1.1.1 $
// $Date: 2003/02/14 21:35:48 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap.image;

import com.sun.image.codec.jpeg.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import javax.swing.*;

import com.bbn.openmap.util.ComponentFactory;
import com.bbn.openmap.util.Debug;

/**
 * This class provides some utility methods for creating a
 * BufferedImage. It will check to see if the Java Advanced Image
 * package is available and use it if it can.
 * @author dietrick - original implemenation and reflection mods.
 * @author Fredrik Lyden - JAI inspiration and initial code.
 */
public class BufferedImageHelper {

    /**
     * This class has only static methods, so there is no need to
     * construct anything.
     */
    private BufferedImageHelper() {};

    /**
     * A test/instantiation copy of the JAI object to use if JAI is
     * installed.
     */
    private static Object jaiObj = null;
    /**
     * Flag to use if the JAI has be checked for.
     */
    private static boolean checkedForJAI = false;

    /**
     * Get the JAI class if it's available.
     */
    protected static Object getJAI() {
        if (checkedForJAI == false) {
            jaiObj = ComponentFactory.create("javax.media.jai.JAI", null);
            checkedForJAI = true;
        }
        return jaiObj;
    }

    /**
     * Run the operation on JAI to create BufferedImage. Uses
     * reflection to determine if JAI is available.
     *
     * @param opName JAI opName, like "file" or "url"
     * @param param JAI object to use for operation, like the file
     * path (String) or URL.
     * @return BufferedImage if JAI can be used to create it, null if
     * anything goes wrong.
     */
    public static BufferedImage getJAIBufferedImage(String opName, Object param) {
        boolean DEBUG = Debug.debugging("bufferedimage");

        Object jai = getJAI();

        if (jai == null) {
            return null;
        }

        if (DEBUG) {
            Debug.output("Using JAI to create image from " + opName);
        }

        try {
            // Do a little reflection to run methods on classes we might not know about.
            Class[] createArgs = new Class[] {Class.forName("java.lang.String"),
                                              Class.forName("java.lang.Object")};

            Method createMethod = jai.getClass().getDeclaredMethod("create", createArgs);

            Object[] createParams = new Object[] {opName, param};
            Object planarImageObject = createMethod.invoke(jai, createParams);

            if (planarImageObject != null) {
                Method getBufferedImageMethod = planarImageObject.getClass().getMethod("getAsBufferedImage", null);

                return (BufferedImage) getBufferedImageMethod.invoke(planarImageObject, null);
            }

        } catch (ClassNotFoundException cnfe) {
            if (DEBUG) {
                Debug.error("BufferedImageHelper.getJAIBufferedImage() ClassNotFoundException error: \n" + cnfe.getMessage());
            }
        } catch (IllegalAccessException iae) {
            if (DEBUG) {
                Debug.error("BufferedImageHelper.getJAIBufferedImage() IllegalAccessException error: \n" + iae.getMessage());
            }
        } catch (InvocationTargetException ite) {
            if (DEBUG) {
                Debug.error("BufferedImageHelper.getJAIBufferedImage() InvocationTargetException error: \n" + ite.getMessage());
            }
        } catch (NoSuchMethodException nsme) {
            if (DEBUG) {
                Debug.error("BufferedImageHelper.getJAIBufferedImage() NoSuchMethodException error: " + nsme.toString());
                nsme.printStackTrace();
            }
        } catch (SecurityException se) {
            if (DEBUG) {
                Debug.error("BufferedImageHelper.getJAIBufferedImage() SecurityException error: \n" + se.getMessage());
            }
        }

        return null;
        // All this above to replace this:
// PlanarImage planarImage = JAI.create(opName, param);
// return getBufferedImage(planarImage.getAsBufferedImage(), x, y, w, h);
    }

    /**
     * Run the operation on JAI to create BufferedImage. Uses
     * reflection to determine if JAI is available. If x or y is not
     * zero, or w and h are not the image dimensions, the image
     * returned will be cropped/translated to match the values.
     *
     * @param opName JAI opName, like "file" or "url"
     * @param param JAI object to use for operation, like the file
     * path (String) or URL.
     * @param x x start pixel
     * @param y y start pixel
     * @param w crop width (-1 uses image width)
     * @param h crop height (-1 uses image height)
     * @return BufferedImage if JAI can be used to create it, null if
     * anything goes wrong.
     * @throws InterruptedException
     */
    public static BufferedImage getJAIBufferedImage(String opName, Object param,
                                                    int x, int y, int w, int h)
        throws InterruptedException {

        BufferedImage bi = getJAIBufferedImage(opName, param);

        // If the whole image isn't wanted, do another operation...
        if (bi != null && (x != 0 || y != 0 || w > 0 || h > 0)) {

            int imageType = BufferedImage.TYPE_INT_RGB;
            if (bi.getColorModel().hasAlpha()) {
                imageType = BufferedImage.TYPE_INT_ARGB;
            }

            return getBufferedImage(bi, x, y, w, h, imageType);
        }
        // else return null or the original image.
        return bi;
    }

    /**
     * Return a BufferedImage loaded from a URL.
     * @return BufferedImage if it can be created, null if
     * anything goes wrong.
     * @throws InterruptedException
     */
    public static BufferedImage getBufferedImage(URL url)
        throws InterruptedException {
        return getBufferedImage(url, 0, 0, -1, -1);
    }

    /**
     * Return a BufferedImage loaded from a URL.
     * @param url the source URL
     * @param x x start pixel
     * @param y y start pixel
     * @param w crop width (-1 uses image width)
     * @param h crop height (-1 uses image height)
     * @return BufferedImage if it can be created, null if
     * anything goes wrong.
     * @throws InterruptedException
     */
    public static BufferedImage getBufferedImage(URL url,
                                                 int x, int y,
                                                 int w, int h)
        throws InterruptedException {

        BufferedImage bi = getJAIBufferedImage("url", url, x, y, w, h);

        if (bi != null) {
            return bi;
        }

        if (Debug.debugging("bufferedimage")) {
            Debug.output("BufferedImageHelper.getBufferedImage(URL) can't use JAI, using ImageIcon");
        }

        // if JAI is not installed....
        ImageIcon ii = new ImageIcon(url);
        if (w <= 0) w = ii.getIconWidth();
        if (h <= 0) h = ii.getIconHeight();
        return getBufferedImage(ii.getImage(), x, y, w, h,
                                BufferedImage.TYPE_INT_ARGB);
    }

    /**
     * Return a BufferedImage loaded from a file path.
     * @return BufferedImage if it can be created, null if
     * anything goes wrong.
     * @throws InterruptedException
     */
    public static BufferedImage getBufferedImage(String path)
        throws InterruptedException {
        return getBufferedImage(path, 0, 0, -1, -1);
    }

    /**
     * Return a BufferedImage loaded from an image file path.
     * @param path file path to the image
     * @param x x start pixel
     * @param y y start pixel
     * @param w crop width (-1 uses image width)
     * @param h crop height (-1 uses image height)
     * @return BufferedImage if it can be created, null if
     * anything goes wrong.
     * @throws InterruptedException
     */
    public static BufferedImage getBufferedImage(String path,
                                                 int x, int y,
                                                 int w, int h)
        throws InterruptedException {

        BufferedImage bi = getJAIBufferedImage("file", path, x, y, w, h);

        if (bi != null) {
            return bi;
        }

        if (Debug.debugging("bufferedimage")) {
            Debug.output("BufferedImageHelper.getBufferedImage(path) can't use JAI, using ImageIcon");
        }

        // if JAI is not installed....
        ImageIcon ii = new ImageIcon(path);
        if (w <= 0) w = ii.getIconWidth();
        if (h <= 0) h = ii.getIconHeight();
        return getBufferedImage(ii.getImage(), x, y, w, h,
                                BufferedImage.TYPE_INT_ARGB);
    }

    /**
     * Return a BufferedImage loaded from a Image. The type of image
     * is BufferedImage.Type_INT_RGB. If you know the height and
     * width, use them because it's slower to have the class figure it
     * out.
     *
     * @param image the source Image
     * @param x x start pixel
     * @param y y start pixel
     * @param w crop width (-1 uses image width)
     * @param h crop height (-1 uses image height)
     * @return BufferedImage if it can be created, null if
     * anything goes wrong.
     * @throws InterruptedException
     */
    public static BufferedImage getBufferedImage(Image image,
                                                 int x, int y,
                                                 int w, int h)
        throws InterruptedException {
        return getBufferedImage(image, x, y, w, h, BufferedImage.TYPE_INT_RGB);
    }

    /**
     * Return a BufferedImage loaded from a Image. If you know the height and
     * width, use them because it's slower to have the class figure it
     * out.
     *
     * @param image the source Image
     * @param x x start pixel - the horizontal pixel location in the
     * returned image that the provided image will be set.
     * @param y y start pixel - the vertical pixel location in the
     * returned image that the provided image will be set.
     * @param w crop width (-1 uses image width)
     * @param h crop height (-1 uses image height)
     * @param imageType the image color model. See BufferedImage.
     * @return BufferedImage if it can be created, null if
     * anything goes wrong.
     * @throws InterruptedException
     */
    public static BufferedImage getBufferedImage(Image image,
                                                 int x, int y,
                                                 int w, int h,
                                                 int imageType)
        throws InterruptedException {

        if (w <= 0 || h <= 0) {
            if (Debug.debugging("bufferedimage")) {
                Debug.output("BufferedImageHelper.getBufferedImage() don't know h/w, using pixel grabber");
            }
            return getBufferedImageFromPixelGrabber(image, x, y, w, h, imageType);
        } else {
            BufferedImage bufferedImage = new BufferedImage(w, h, imageType);
            Graphics2D g2d = bufferedImage.createGraphics();
            g2d.drawImage(image, x, y, null);
            g2d.dispose();
            return bufferedImage;
        }
    }

    /**
     * Return a BufferedImage loaded from a Image, using a
     * PixelGrabber. Good for when you have an Image, not a
     * BufferedImage, and don't know the width and height. There is a
     * performance penalty with this method, though.
     *
     * @param image the source Image
     * @param x x start pixel - the horizontal pixel location in the
     * returned image that the provided image will be set.
     * @param y y start pixel - the vertical pixel location in the
     * returned image that the provided image will be set.
     * @param w crop width (-1 uses image width)
     * @param h crop height (-1 uses image height)
     * @param imageType the image color model. See BufferedImage.
     * @return BufferedImage if it can be created, null if
     * anything goes wrong.
     */
    public static BufferedImage getBufferedImageFromPixelGrabber(Image image,
                                                                 int x, int y,
                                                                 int w, int h,
                                                                 int imageType) {

        PixelGrabber pg = new PixelGrabber(image, x, y, w, h, true);
        int[] pixels = ImageHelper.grabPixels(pg);

        if (pixels == null){
            return null;
        }

        w = pg.getWidth();
        h = pg.getHeight();
        pg = null;

        BufferedImage bi = new BufferedImage(w, h, imageType);
        if (Debug.debugging("imagehelper")){
            Debug.output("BufferedImageHelper.getBufferedImage(): Got buffered image...");
        }

        bi.setRGB(0, 0, w, h, pixels, 0, w);

        if (Debug.debugging("imagehelper")){
            Debug.output("BufferedImageHelper.getBufferedImage(): set pixels in image...");
        }

        return bi;
    }
}

> Sorry if this question veers beyond OpenMap into 2DGraphics
> territory...
>
> The GIF file is here for reference;
>
> http://www.classforge.com/openmap/red_hatch_32x32.gif
>
> Thanks in anticipation,
>
> matt :-)
>
> --
> [To unsubscribe to this list send an email to "majdart@bbn.com"
> with the following text in the BODY of the message "unsubscribe
> openmap-users"]
>

--
[To unsubscribe to this list send an email to "majdart@bbn.com"
with the following text in the BODY of the message "unsubscribe openmap-users"]
Received on Wed Mar 12 09:09:05 2003

This archive was generated by hypermail 2.1.8 : Thu May 12 2005 - 07:18:35 EDT