Example usage for java.awt.image BufferedImage getSubimage

List of usage examples for java.awt.image BufferedImage getSubimage

Introduction

In this page you can find the example usage for java.awt.image BufferedImage getSubimage.

Prototype

public BufferedImage getSubimage(int x, int y, int w, int h) 

Source Link

Document

Returns a subimage defined by a specified rectangular region.

Usage

From source file:org.structr.common.ImageHelper.java

public static Thumbnail createThumbnail(final Image originalImage, final int maxWidth, final int maxHeight,
        final boolean crop) {

    // String contentType = (String) originalImage.getProperty(Image.CONTENT_TYPE_KEY);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    Thumbnail tn = new Thumbnail();

    try {/*from   w  w w. j  a va2  s . c  om*/

        // read image
        long start = System.nanoTime();
        InputStream in = originalImage.getInputStream();
        BufferedImage source = null;

        try {

            source = ImageIO.read(in);

        } catch (Throwable t) {

            logger.log(Level.WARNING, "Could not read original image {0} ({1})",
                    new Object[] { originalImage.getName(), originalImage.getId() });

        } finally {

            if (in != null) {

                in.close();
            }

        }

        if (source != null) {

            int sourceWidth = source.getWidth();
            int sourceHeight = source.getHeight();

            // Update image dimensions
            originalImage.setWidth(sourceWidth);
            originalImage.setHeight(sourceHeight);

            // float aspectRatio = sourceWidth/sourceHeight;
            float scaleX = 1.0f * sourceWidth / maxWidth;
            float scaleY = 1.0f * sourceHeight / maxHeight;
            float scale;

            if (crop) {

                scale = Math.min(scaleX, scaleY);
            } else {

                scale = Math.max(scaleX, scaleY);
            }

            //                              System.out.println("Source (w,h): " + sourceWidth + ", " + sourceHeight + ", Scale (x,y,res): " + scaleX + ", " + scaleY + ", " + scale);
            // Don't scale up
            if (scale > 1.0000f) {

                int destWidth = Math.max(3, Math.round(sourceWidth / scale));
                int destHeight = Math.max(3, Math.round(sourceHeight / scale));

                //                                      System.out.println("Dest (w,h): " + destWidth + ", " + destHeight);
                ResampleOp resampleOp = new ResampleOp(destWidth, destHeight);

                // resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Soft);
                BufferedImage resampled = resampleOp.filter(source, null);
                BufferedImage result = null;

                if (crop) {

                    int offsetX = Math.abs(maxWidth - destWidth) / 2;
                    int offsetY = Math.abs(maxHeight - destHeight) / 2;

                    logger.log(Level.FINE, "Offset and Size (x,y,w,h): {0},{1},{2},{3}",
                            new Object[] { offsetX, offsetY, maxWidth, maxHeight });

                    result = resampled.getSubimage(offsetX, offsetY, maxWidth, maxHeight);

                    tn.setWidth(maxWidth);
                    tn.setHeight(maxHeight);

                } else {

                    result = resampled;

                    tn.setWidth(destWidth);
                    tn.setHeight(destHeight);

                }

                ImageIO.write(result, Thumbnail.FORMAT, baos);

            } else {

                // Thumbnail is source image
                ImageIO.write(source, Thumbnail.FORMAT, baos);
                tn.setWidth(sourceWidth);
                tn.setHeight(sourceHeight);
            }

        } else {

            logger.log(Level.WARNING, "Thumbnail could not be created");

            return null;

        }

        long end = System.nanoTime();
        long time = (end - start) / 1000000;

        logger.log(Level.FINE, "Thumbnail created. Reading, scaling and writing took {0} ms", time);
        tn.setBytes(baos.toByteArray());

        return tn;
    } catch (Throwable t) {

        logger.log(Level.WARNING, "Error creating thumbnail");

    } finally {

        try {

            if (baos != null) {

                baos.close();
            }

        } catch (Exception ignore) {
        }

    }

    return null;
}

From source file:org.structr.web.common.ImageHelper.java

public static Thumbnail createThumbnail(final Image originalImage, final int maxWidth, final int maxHeight,
        final boolean crop) {

    // String contentType = (String) originalImage.getProperty(Image.CONTENT_TYPE_KEY);
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    final Thumbnail tn = new Thumbnail();

    try (final InputStream in = originalImage.getInputStream()) {

        if (in == null) {

            logger.log(Level.FINE, "InputStream of original image {0} ({1}) is null",
                    new Object[] { originalImage.getName(), originalImage.getId() });
            return null;
        }/*from ww w .  ja v  a2  s. c o  m*/

        final long start = System.nanoTime();
        BufferedImage source = null;

        // read image
        source = ImageIO.read(in);
        if (source != null) {

            int sourceWidth = source.getWidth();
            int sourceHeight = source.getHeight();

            // Update image dimensions
            originalImage.setProperty(Image.width, sourceWidth);
            originalImage.setProperty(Image.height, sourceHeight);

            // float aspectRatio = sourceWidth/sourceHeight;
            float scaleX = 1.0f * sourceWidth / maxWidth;
            float scaleY = 1.0f * sourceHeight / maxHeight;
            float scale;

            if (crop) {

                scale = Math.min(scaleX, scaleY);
            } else {

                scale = Math.max(scaleX, scaleY);
            }

            // Don't scale up
            if (scale > 1.0) {

                final int destWidth = Math.max(4, Math.round(sourceWidth / scale));
                final int destHeight = Math.max(4, Math.round(sourceHeight / scale));

                //System.out.println(destWidth + " / " + destHeight);

                ResampleOp resampleOp = new ResampleOp(destWidth, destHeight);
                BufferedImage resampled = resampleOp.filter(source, null);
                BufferedImage result = null;

                if (crop) {

                    int offsetX = Math.abs(maxWidth - destWidth) / 2;
                    int offsetY = Math.abs(maxHeight - destHeight) / 2;

                    logger.log(Level.FINE, "Offset and Size (x,y,w,h): {0},{1},{2},{3}",
                            new Object[] { offsetX, offsetY, maxWidth, maxHeight });

                    result = resampled.getSubimage(offsetX, offsetY, maxWidth, maxHeight);

                    tn.setWidth(maxWidth);
                    tn.setHeight(maxHeight);

                } else {

                    result = resampled;

                    tn.setWidth(destWidth);
                    tn.setHeight(destHeight);

                }

                ImageIO.write(result, Thumbnail.FORMAT, baos);

            } else {

                // Thumbnail is source image
                ImageIO.write(source, Thumbnail.FORMAT, baos);
                tn.setWidth(sourceWidth);
                tn.setHeight(sourceHeight);
            }

        } else {

            logger.log(Level.FINE, "Thumbnail could not be created");
            return null;
        }

        long end = System.nanoTime();
        long time = (end - start) / 1000000;

        logger.log(Level.FINE, "Thumbnail created. Reading, scaling and writing took {0} ms", time);
        tn.setBytes(baos.toByteArray());

        return tn;

    } catch (Throwable t) {

        logger.log(Level.WARNING, "Unable to create thumbnail for image with ID {0}.", originalImage.getUuid());
    }

    return null;
}

From source file:org.uva.itast.blended.omr.pages.PageImage.java

/**
 * @param rectMM bounding box in milimeters
 * @see #getSubimage(double, double, double, double, int)
 * @return/*  w w w .ja v a 2s. c  o  m*/
 */
public SubImage getSubimage(Rectangle2D rectMM, int imageType) {

    Rectangle rect = this.toPixels(rectMM);
    if (logger.isDebugEnabled()) {
        logger.debug("Subimage " + rectMM + " mm " + rect + " px.");
    }
    PagePoint upperLeft = new PagePoint(this, rectMM.getX(), rectMM.getY());

    Point reference = upperLeft.getPixelsPoint();

    BufferedImage originalImage = getImage();
    Rectangle originalRect = new Rectangle(originalImage.getWidth(), originalImage.getHeight());
    // copy what is available from image
    Rectangle available = rect.intersection(originalRect);

    BufferedImage originalSubImage = originalImage.getSubimage(available.x, available.y, available.width,
            available.height);

    //rotate image
    SubImage subimage = new SubImage(rect.width, rect.height, imageType);
    subimage.setReference(reference);
    subimage.setBoundingBox(rect);
    subimage.setCapturedBoundingBox(available);

    Graphics2D g = subimage.createGraphics();
    g.drawImage(originalSubImage, available.x - rect.x, available.y - rect.y, null);

    return subimage;
}

From source file:org.xframium.page.element.SeleniumElement.java

@Override
public Image _getImage(Resolution imageResolution) {
    WebElement imageElement = getElement();

    if (imageElement != null) {
        if (imageElement.getLocation() != null && imageElement.getSize() != null
                && imageElement.getSize().getWidth() > 0 && imageElement.getSize().getHeight() > 0) {
            String fileKey = "PRIVATE:" + getDeviceName() + ".png";

            byte[] imageData = null;

            String cloudName = ((DeviceWebDriver) webDriver).getDevice().getCloud();
            if (cloudName == null || cloudName.trim().isEmpty())
                cloudName = CloudRegistry.instance().getCloud().getName();

            if (CloudRegistry.instance().getCloud(cloudName).getProvider().equals("PERFECTO")) {
                PerfectoMobile.instance().imaging().screenShot(getExecutionId(), getDeviceName(), fileKey,
                        Screen.primary, ImageFormat.png, imageResolution);
                imageData = PerfectoMobile.instance().repositories().download(RepositoryType.MEDIA, fileKey);
            } else {
                if (webDriver instanceof TakesScreenshot) {
                    try {
                        imageData = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.BYTES);
                    } catch (Exception e) {
                        log.error("Error taking screenshot", e);
                    }//from  ww w  .java2 s .  c  om
                }
            }
            if (imageData != null && imageData.length > 0) {
                try {
                    BufferedImage fullImage = ImageIO.read(new ByteArrayInputStream(imageData));
                    return fullImage.getSubimage(imageElement.getLocation().getX(),
                            imageElement.getLocation().getY(), imageElement.getSize().getWidth(),
                            imageElement.getSize().getHeight());
                } catch (Exception e) {
                    log.error(Thread.currentThread().getName() + ": Error extracting image data", e);
                }
            } else
                log.warn(Thread.currentThread().getName() + ": No image data could be retrieved for [" + fileKey
                        + "]");

        } else
            log.warn(Thread.currentThread().getName() + ": The element returned via " + getKey()
                    + " did not contain a location or size");
    }

    return null;
}

From source file:org.yes.cart.service.domain.impl.ImageServiceImpl.java

/**
 * {@inheritDoc}//from   ww w.j  a  v a2  s .  c  om
 */
public byte[] resizeImage(final String filename, final byte[] content, final String width, final String height,
        final boolean cropToFit) {

    try {

        final InputStream bis = new ByteArrayInputStream(content);

        final BufferedImage originalImg = ImageIO.read(bis);
        final String codec = getCodecFromFilename(filename);
        final boolean supportsAlpha = hasAlphaSupport(codec);

        int x = NumberUtils.toInt(width);
        int y = NumberUtils.toInt(height);
        int originalX = originalImg.getWidth();
        int originalY = originalImg.getHeight();

        boolean doCropToFit = cropToFit || x < forceCropToFitOnSize || y < forceCropToFitOnSize;

        final int imageType = originalImg.getType();

        final Image resizedImg;
        //            final BufferedImage resizedImg;
        final int padX, padY;
        if (doCropToFit) {
            // crop the original to best fit of target size
            int[] cropDims = cropImageToCenter(x, y, originalX, originalY);
            padX = 0;
            padY = 0;

            final BufferedImage croppedImg = originalImg.getSubimage(cropDims[0], cropDims[1], cropDims[2],
                    cropDims[3]);
            resizedImg = croppedImg.getScaledInstance(x, y, Image.SCALE_SMOOTH);

            //                final BufferedImage croppedImg = originalImg.getSubimage(cropDims[0], cropDims[1], cropDims[2], cropDims[3]);
            //                resizedImg = new BufferedImage(y, x, imageType);
            //                Graphics2D graphics = resizedImg.createGraphics();
            //                graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            //                graphics.drawImage(croppedImg, 0, 0, x, y, null);
        } else {
            int[] scaleDims = scaleImageToCenter(x, y, originalX, originalY);
            padX = scaleDims[0];
            padY = scaleDims[1];

            resizedImg = originalImg.getScaledInstance(scaleDims[2], scaleDims[3], Image.SCALE_SMOOTH);

            //                resizedImg = new BufferedImage(scaleDims[3], scaleDims[2], imageType);
            //                Graphics2D graphics = resizedImg.createGraphics();
            //                graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            //                graphics.drawImage(originalImg, 0, 0, scaleDims[2], scaleDims[3], null);
        }

        // base canvas
        final BufferedImage resizedImgFinal = new BufferedImage(x, y, imageType);

        // fill base color
        final Graphics2D graphics = resizedImgFinal.createGraphics();
        graphics.setPaint(supportsAlpha ? alphaBorder : defaultBorder);
        graphics.fillRect(0, 0, x, y);

        // insert scaled image
        graphics.drawImage(resizedImg, padX, padY, null);

        final ByteArrayOutputStream bos = new ByteArrayOutputStream();

        ImageIO.write(resizedImgFinal, codec, bos);

        return bos.toByteArray();

    } catch (Exception exp) {
        ShopCodeContext.getLog(this).error("Unable to resize image " + filename, exp);
    }

    return new byte[0];

}

From source file:pl.edu.icm.visnow.lib.utils.ImageUtilities.java

public static BufferedImage autoPanImage(BufferedImage img, Color bgcolor) {
    BufferedImage out = null;//from   w ww .j a v  a2 s . c o  m
    if (img == null) {
        return null;
    }

    int bgcolorInt = bgcolor.getRGB();
    int w = img.getWidth();
    int h = img.getHeight();
    int up = 0;
    int down = h - 1;
    int left = 0;
    int right = w - 1;
    int tmp;

    for (int x = 0; x < w; x++) {
        for (int y = 0; y < h / 2; y++) {
            tmp = img.getRGB(x, y);
            if (tmp == bgcolorInt) {
                if (y > up) {
                    up = y;
                }
            } else {
                break;
            }
        }

        for (int y = h - 1; y > h / 2; y--) {
            tmp = img.getRGB(x, y);
            if (tmp == bgcolorInt) {
                if (y < down) {
                    down = y;
                }
            } else {
                break;
            }
        }

    }

    for (int y = up; y < down; y++) {
        for (int x = 0; x < w / 2; x++) {
            tmp = img.getRGB(x, y);
            if (tmp == bgcolorInt) {
                if (x > left) {
                    left = x;
                }
            } else {
                break;
            }
        }

        for (int x = w - 1; x > w / 2; x--) {
            tmp = img.getRGB(x, y);
            if (tmp == bgcolorInt) {
                if (x < right) {
                    right = x;
                }
            } else {
                break;
            }
        }

    }

    System.out.println("up=" + up);
    System.out.println("down=" + down);
    System.out.println("left=" + left);
    System.out.println("right=" + right);

    out = img.getSubimage(left, up, right - left + 1, down - up + 1);
    return out;
}

From source file:plugin.exporttokens.PortraitToken.java

/**
 * Generate a thumbnail image based on the character's portrait and 
 * the thumnbnail rectangle.// ww  w.  j ava2  s . c  o  m
 * 
 * @param display The character being output.
 * @return The thumbnail image, or null if not defined.
 */
private BufferedImage generateThumb(CharacterDisplay display) {
    Rectangle cropRect = display.getPortraitThumbnailRect();
    BufferedImage portrait = null;
    try {
        File file = new File(display.getPortraitPath());
        if (file.isFile()) {
            portrait = ImageIO.read(file);
        }
    } catch (IOException ex) {
        Logging.errorPrint("Could not load image", ex);
    }
    if (portrait == null || cropRect == null) {
        return null;
    }

    BufferedImage thumb = portrait.getSubimage(cropRect.x, cropRect.y, cropRect.width, cropRect.height);
    thumb = getScaledInstance(thumb, Constants.THUMBNAIL_SIZE, Constants.THUMBNAIL_SIZE,
            RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);
    return thumb;
}

From source file:preprocessing.Utils.java

public static BufferedImage cropper(BufferedImage img) {
    int height = img.getHeight();
    int width = img.getWidth();
    int pixel;/*from ww  w. j av  a2  s .c  om*/
    int startX, endX, startY, endY;
    //startX = startY = 1000000;
    startX = img.getWidth();
    startY = img.getHeight();
    endX = endY = 0;
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            pixel = img.getRGB(x, y);
            //determine whether the pixel is black or red. if red and firstred == null, assign to firstred. same with black. each red or black pixel read can be assigned to lastred or lastblack as when it's done looping you'll automatically have the last black or red. Also, assign the x and y values to a variable.
            if (pixel != -1) {
                if (x < startX)
                    startX = x;
                if (x > endX)
                    endX = x;
                if (y < startY)
                    startY = y;
                if (y > endY)
                    endY = y;
            }

            //invertir colores
            /*
            if(pixel!=-1)
            img.setRGB(x,y,-1);
            else
            img.setRGB(x, y, -16777216);
            */
            //System.out.println("las +"+pixel);
        }
    }
    if (endX <= startX)
        return img;
    if (endY <= startY)
        return img;
    // create a cropped image from the original image
    BufferedImage croppedImage = img.getSubimage(startX, startY, endX - startX, endY - startY);

    return croppedImage;
}

From source file:preprocessing.Utils.java

public static BufferedImage limpiarBordeImagen(BufferedImage numero1, int proporcionX, int proporcionY) {
    BufferedImage nuevo = numero1;
    if (proporcionX == -1)
        proporcionX = 1;/* ww w  .  j  ava  2 s .  com*/
    if (proporcionY == -1)
        proporcionY = 1;
    int inicioY, inicioX, finY, finX;
    inicioY = 0;
    for (int i = 0; i < numero1.getHeight() / proporcionY; i++) {
        int[] linea = new int[numero1.getWidth()];
        for (int j = 0; j < numero1.getWidth(); j++)
            linea[j] = numero1.getRGB(j, i);
        if (esLineaNegra(linea)) {
            inicioY = i + 1;
        }
    }

    finY = numero1.getHeight() - 1;
    for (int i = numero1.getHeight() - 1; i > (numero1.getHeight()
            - (numero1.getHeight() / proporcionY)); i--) {
        int[] linea = new int[numero1.getWidth()];
        for (int j = 0; j < numero1.getWidth(); j++)
            linea[j] = numero1.getRGB(j, i);
        if (esLineaNegra(linea)) {
            finY = i - 1;
        }
    }

    inicioX = 0;
    for (int i = 0; i < numero1.getWidth() / proporcionX; i++) {
        int[] linea = new int[numero1.getHeight()];
        for (int j = 0; j < numero1.getHeight(); j++)
            linea[j] = numero1.getRGB(i, j);
        if (esLineaNegra(linea)) {
            inicioX = i + 1;
        }
    }

    finX = numero1.getWidth() - 1;
    for (int i = numero1.getWidth() - 1; i > (numero1.getWidth() - (numero1.getWidth() / proporcionX)); i--) {
        int[] linea = new int[numero1.getHeight()];
        for (int j = 0; j < numero1.getHeight(); j++)
            linea[j] = numero1.getRGB(i, j);
        if (esLineaNegra(linea)) {
            finX = i - 1;
        }
    }
    return numero1.getSubimage(inicioX, inicioY, (finX - inicioX), (finY - inicioY));
}

From source file:ucar.unidata.idv.ui.ImageGenerator.java

/**
 * Process the image//from   w w w .ja v a2s  . co  m
 *
 * @param image The image
 * @param filename File to write the image to
 * @param node Node to process
 * @param props Extra properties
 * @param viewManager The viewmanager this image came from
 * @param imageProps  the image properties
 *
 *
 * @return The processed image
 * @throws Throwable On badness
 */
protected BufferedImage processImage(BufferedImage image, String filename, Element node, Hashtable props,
        ViewManager viewManager, Hashtable imageProps) throws Throwable {

    if (node == null) {
        return image;
    }

    if (props == null) {
        props = new Hashtable();
    }
    if (viewManager != null) {
        Animation animation = viewManager.getAnimation();
        props.put(PROP_ANIMATIONTIME, "");
        if (animation != null) {
            if (animation.getAniValue() != null) {
                props.put(PROP_ANIMATIONTIME, animation.getAniValue());
            }
        }
    }
    getProperties().putAll(props);

    NodeList elements = XmlUtil.getElements(node);
    Hashtable seenColorTable = new Hashtable();
    for (int childIdx = 0; childIdx < elements.getLength(); childIdx++) {
        boolean shouldIterateChildren = true;
        BufferedImage newImage = null;
        int imageWidth = image.getWidth(null);
        int imageHeight = image.getHeight(null);
        Element child = (Element) elements.item(childIdx);
        String tagName = child.getTagName();

        if (tagName.equals(TAG_RESIZE)) {
            newImage = ImageUtils.toBufferedImage(resize(image, child));
        } else if (tagName.equals(TAG_FILESET)) {
            //ignore
        } else if (tagName.equals(TAG_OUTPUT)) {
            processTagOutput(child);
        } else if (tagName.equals(TAG_DISPLAYLIST)) {
            if (viewManager != null) {
                newImage = ImageUtils.toBufferedImage(image, true);
                Graphics g = newImage.getGraphics();
                String valign = applyMacros(child, ATTR_VALIGN, VALUE_BOTTOM);
                Font font = getFont(child);
                if (XmlUtil.hasAttribute(child, ATTR_MATTEBG)) {
                    int height = viewManager.paintDisplayList((Graphics2D) g, null, imageWidth, imageHeight,
                            valign.equals(VALUE_BOTTOM), null, font);

                    int top = (valign.equals(VALUE_TOP) ? height : 0);
                    int bottom = (valign.equals(VALUE_BOTTOM) ? height : 0);
                    newImage = ImageUtils.matte(image, top, bottom, 0, 0,
                            applyMacros(child, ATTR_MATTEBG, Color.white));
                    g = newImage.getGraphics();
                    imageHeight += height;
                }

                Color c = applyMacros(child, ATTR_COLOR, (Color) null);
                viewManager.paintDisplayList((Graphics2D) g, null, imageWidth, imageHeight,
                        valign.equals(VALUE_BOTTOM), c, font);
            }
        } else if (tagName.equals(TAG_COLORBAR) || tagName.equals(TAG_KML_COLORBAR)) {
            // only do one colorbar if we are writing to kml
            Integer index = (Integer) props.get(PROP_IMAGEINDEX);
            if ((index != null) && (index.intValue() > 0) && tagName.equals(TAG_KML_COLORBAR)) {
                continue;
            }

            boolean showLines = applyMacros(child, ATTR_SHOWLINES, false);

            List<DisplayControlImpl> controls = (List<DisplayControlImpl>) ((viewManager != null)
                    ? viewManager.getControls()
                    : new ArrayList());

            if (XmlUtil.hasAttribute(child, ATTR_DISPLAY)) {
                DisplayControlImpl display = ((controls.size() > 0)
                        ? findDisplayControl(XmlUtil.getAttribute(child, ATTR_DISPLAY), controls)
                        : findDisplayControl(child));
                if (display == null) {
                    error("Could not find display:" + XmlUtil.toString(node));
                    return null;
                }
                controls = Misc.newList(display);
            }

            int width = applyMacros(child, ATTR_WIDTH, 150);
            int height = applyMacros(child, ATTR_HEIGHT, 20);
            int ticks = applyMacros(child, ATTR_TICKMARKS, 0);
            double interval = applyMacros(child, ATTR_INTERVAL, -1.0);
            String valuesStr = applyMacros(child, ATTR_VALUES, (String) null);
            Color c = applyMacros(child, ATTR_COLOR, Color.black);

            Color lineColor = applyMacros(child, ATTR_LINECOLOR, c);

            Rectangle imageRect = new Rectangle(0, 0, imageWidth, imageHeight);

            Point pp = ImageUtils.parsePoint(applyMacros(child, ATTR_PLACE, "ll,10,-10"), imageRect);
            Point ap = ImageUtils.parsePoint(applyMacros(child, ATTR_ANCHOR, "ll"),
                    new Rectangle(0, 0, width, height));

            String orientation = applyMacros(child, ATTR_ORIENTATION, VALUE_BOTTOM);
            boolean vertical = orientation.equals(VALUE_RIGHT) || orientation.equals(VALUE_LEFT);
            int baseY = pp.y - ap.y + (vertical ? 0 : height);
            int baseX = pp.x - ap.x;

            List colorTables = new ArrayList();
            List ranges = new ArrayList();
            List units = new ArrayList();

            boolean forKml = tagName.equals(TAG_KML_COLORBAR);

            for (int i = 0; i < controls.size(); i++) {
                DisplayControlImpl control = (DisplayControlImpl) controls.get(i);
                ColorTable colorTable = control.getColorTable();
                if (colorTable == null) {
                    continue;
                }
                Range range = control.getRangeForColorTable();
                //only do unique color tables
                Object[] key = { colorTable, range };
                if (seenColorTable.get(key) != null) {
                    continue;
                }
                seenColorTable.put(key, key);
                colorTables.add(colorTable);
                ranges.add(range);
                units.add(control.getDisplayUnit());
            }

            for (int i = 0; i < colorTables.size(); i++) {
                ColorTable colorTable = (ColorTable) colorTables.get(i);
                Range range = (Range) ranges.get(i);
                Unit unit = (Unit) units.get(i);
                Image imageToDrawIn;
                if (forKml) {
                    if (vertical) {
                        baseX = 0;
                        baseY = 0;
                    } else {
                        baseX = 0;
                        baseY = height;
                    }
                    int space = applyMacros(child, ATTR_SPACE, (vertical ? width : height));
                    imageToDrawIn = new BufferedImage(width + (vertical ? space : 0),
                            height + (vertical ? 0 : space), BufferedImage.TYPE_INT_RGB);
                } else {
                    imageToDrawIn = newImage = ImageUtils.toBufferedImage(image);
                }
                Graphics g = imageToDrawIn.getGraphics();
                if (forKml) {
                    Color bgColor = applyMacros(child, ATTR_BACKGROUND, Color.white);
                    g.setColor(bgColor);
                    g.fillRect(0, 0, imageToDrawIn.getWidth(null), imageToDrawIn.getHeight(null));
                }
                boolean includeAlpha = applyMacros(child, ATTR_TRANSPARENCY, true);

                float[][] ctValues;

                if (includeAlpha) {
                    ctValues = colorTable.getAlphaTable();
                } else {
                    ctValues = colorTable.getNonAlphaTable();
                }
                ColorMap colorMap = new BaseRGBMap(ctValues);
                ColorPreview preview = new ColorPreview(colorMap, (vertical ? width : height));
                if (vertical) {
                    preview.setSize(new Dimension(height, width));
                } else {
                    preview.setSize(new Dimension(width, height));
                }
                Image previewImage = ColorTableCanvas.getImage(colorTable, (vertical ? height : width),
                        (vertical ? width : height), includeAlpha);

                if (vertical) {
                    int imageType = includeAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;

                    BufferedImage tmpImage = new BufferedImage(width, height, imageType);

                    Graphics2D tmpG = (Graphics2D) tmpImage.getGraphics();
                    tmpG.rotate(Math.toRadians(90.0));
                    tmpG.drawImage(previewImage, 0, 0 - width, null);
                    previewImage = tmpImage;
                }
                if (forKml) {
                    g.drawImage(previewImage, 0, 0, null);
                } else {
                    g.drawImage(previewImage, baseX, (vertical ? baseY : baseY - height), null);
                }
                if (showLines) {
                    g.setColor(lineColor);
                    g.drawRect(baseX, (vertical ? baseY : baseY - height), width - 1,
                            height - (vertical ? 1 : 0));
                }
                setFont(g, child);
                FontMetrics fm = g.getFontMetrics();
                List values = new ArrayList();
                String suffixFrequency = XmlUtil.getAttribute(child, ATTR_SUFFIXFREQUENCY,
                        XmlUtil.getAttribute(child, ATTR_SHOWUNIT, "false")).toLowerCase();
                String unitDefault = (!suffixFrequency.equals("false")) ? " %unit%" : "";
                String labelSuffix = applyMacros(child, ATTR_SUFFIX, unitDefault);
                if (unit != null) {
                    labelSuffix = labelSuffix.replace("%unit%", "" + unit);
                } else {
                    labelSuffix = labelSuffix.replace("%unit%", "");
                }
                if (valuesStr != null) {
                    double[] valueArray = Misc.parseDoubles(valuesStr, ",");
                    for (int valueIdx = 0; valueIdx < valueArray.length; valueIdx++) {
                        values.add(new Double(valueArray[valueIdx]));
                    }
                } else if (ticks > 0) {
                    int spacing = ((ticks == 1) ? 0 : (vertical ? height : width) / (ticks - 1));
                    for (int tickIdx = 0; tickIdx < ticks; tickIdx++) {
                        double percent = ((ticks > 1) ? (double) tickIdx / (double) (ticks - 1) : 0.0);
                        values.add(new Double(range.getValueOfPercent(percent)));
                    }
                } else if (interval > 0) {
                    double value = range.getMin();
                    double max = range.getMax();
                    while (value <= max) {
                        values.add(new Double(value));
                        value += interval;
                    }
                }
                for (int valueIdx = 0; valueIdx < values.size(); valueIdx++) {
                    double value = ((Double) values.get(valueIdx)).doubleValue();
                    int x;
                    int y;
                    if (vertical) {
                        if (orientation.equals(VALUE_RIGHT)) {
                            x = baseX + width;
                        } else {
                            x = baseX;
                        }
                        y = baseY + (int) (range.getPercent(value) * height);
                        if (y > baseY + height) {
                            break;
                        }
                    } else {
                        if (orientation.equals(VALUE_BOTTOM)) {
                            y = baseY;
                        } else {
                            y = baseY - height;
                        }

                        if (range != null) {
                            x = baseX + (int) (range.getPercent(value) * width);
                        } else {
                            x = baseX;
                        }

                        if (x > baseX + width) {
                            break;
                        }
                    }
                    String tickLabel = getIdv().getDisplayConventions().format(value);
                    if (suffixFrequency.equals(VALUE_LAST) && (valueIdx == values.size() - 1)) {
                        tickLabel += labelSuffix;
                    } else if (suffixFrequency.equals(VALUE_FIRST) && (valueIdx == 0)) {
                        tickLabel += labelSuffix;
                    } else if (suffixFrequency.equals(VALUE_ALL) || suffixFrequency.equals("true")) {
                        tickLabel += labelSuffix;
                    }

                    Rectangle2D rect = fm.getStringBounds(tickLabel, g);
                    g.setColor(lineColor);
                    if (orientation.equals(VALUE_RIGHT)) {
                        g.drawLine(x + 1, y, x, y);
                        if (showLines) {
                            g.drawLine(x, y, x - width, y);
                        }
                    } else if (orientation.equals(VALUE_LEFT)) {
                        g.drawLine(x - 1, y, x, y);
                        if (showLines) {
                            g.drawLine(x, y, x + width, y);
                        }
                    } else if (orientation.equals(VALUE_BOTTOM)) {
                        g.drawLine(x, y + 1, x, y);
                        if (showLines) {
                            g.drawLine(x, y, x, y - height);
                        }
                    } else {
                        g.drawLine(x, y - 1, x, y);
                        if (showLines) {
                            g.drawLine(x, y, x, y + height);
                        }
                    }
                    g.setColor(c);
                    if (orientation.equals(VALUE_RIGHT)) {
                        int yLoc = y + (int) (rect.getHeight() / 2) - 2;
                        if (forKml) {
                            if (valueIdx == 0) {
                                yLoc = y + (int) (rect.getHeight()) - 2;
                            } else if (valueIdx == values.size() - 1) {
                                yLoc = y - (int) (rect.getHeight()) + 6;
                            }
                        }
                        g.drawString(tickLabel, x + 2, yLoc);
                    } else if (orientation.equals(VALUE_LEFT)) {
                        int xLoc = x - 2 - (int) rect.getWidth();
                        g.drawString(tickLabel, xLoc, y + (int) (rect.getHeight() / 2) - 2);
                    } else if (orientation.equals(VALUE_BOTTOM)) {
                        int xLoc = x - (int) (rect.getWidth() / 2);
                        if (forKml) {
                            if (valueIdx == 0) {
                                xLoc = x + 2;
                            } else if (valueIdx == values.size() - 1) {
                                xLoc = x - (int) rect.getWidth() + 2;
                            }
                        }
                        g.drawString(tickLabel, xLoc, y + (int) rect.getHeight() + 2);
                    } else {
                        g.drawString(tickLabel, x - (int) (rect.getWidth() / 2), y - 2);
                    }
                }
                if (vertical) {
                    baseX += width + 30;
                } else {
                    baseY += height + 30;
                }
                if (forKml) {
                    String tmpImageFile = applyMacros(child, ATTR_FILE,
                            getIdv().getStore().getTmpFile("testcolorbar${viewindex}.png"));
                    String template = "<ScreenOverlay><name>${kml.name}</name><Icon><href>${icon}</href></Icon>\n"
                            + "<overlayXY x=\"${kml.overlayXY.x}\" y=\"${kml.overlayXY.y}\" xunits=\"${kml.overlayXY.xunits}\" yunits=\"${kml.overlayXY.yunits}\"/>\n"
                            + "<screenXY x=\"${kml.screenXY.x}\" y=\"${kml.screenXY.y}\" xunits=\"${kml.screenXY.xunits}\" yunits=\"${kml.screenXY.yunits}\"/>\n"
                            + "<size x=\"${kml.size.x}\" y=\"${kml.size.y}\" xunits=\"${kml.size.xunits}\" yunits=\"${kml.size.yunits}\"/>\n"
                            + "</ScreenOverlay>\n";
                    String[] macros = { "kml.name", "kml.overlayXY.x", "kml.overlayXY.y",
                            "kml.overlayXY.xunits", "kml.overlayXY.yunits", "kml.screenXY.x", "kml.screenXY.y",
                            "kml.screenXY.xunits", "kml.screenXY.yunits", "kml.size.x", "kml.size.y",
                            "kml.size.xunits", "kml.size.yunits" };
                    String[] macroValues = { "", "0", "1", "fraction", "fraction", "0", "1", "fraction",
                            "fraction", "-1", "-1", "pixels", "pixels" };

                    for (int macroIdx = 0; macroIdx < macros.length; macroIdx++) {
                        template = template.replace("${" + macros[macroIdx] + "}",
                                applyMacros(child, macros[macroIdx], macroValues[macroIdx]));
                    }
                    template = template.replace("${icon}", IOUtil.getFileTail(tmpImageFile));
                    imageProps.put("kml", template);
                    List kmlFiles = (List) imageProps.get("kmlfiles");
                    //TODO: Only do the first one for now
                    if (kmlFiles == null) {
                        kmlFiles = new ArrayList();
                        imageProps.put("kmlfiles", kmlFiles);
                    }
                    kmlFiles.add(tmpImageFile);

                    //                        System.out.println(template);
                    ImageUtils.writeImageToFile(imageToDrawIn, tmpImageFile);
                }
            }

        } else if (tagName.equals(TAG_TRANSPARENT) || tagName.equals(TAG_BGTRANSPARENT)) {
            Color c = null;
            if (tagName.equals(TAG_BGTRANSPARENT)) {
                c = viewManager.getBackground();
            } else {
                c = applyMacros(child, ATTR_COLOR, (Color) null);
            }
            //                System.err.println ("c:" + c);
            int[] redRange = { 0, 0 };
            int[] greenRange = { 0, 0 };
            int[] blueRange = { 0, 0 };
            if (c != null) {
                //                    System.err.println("got color");
                redRange[0] = redRange[1] = c.getRed();
                greenRange[0] = greenRange[1] = c.getGreen();
                blueRange[0] = blueRange[1] = c.getBlue();
            } else {
            }
            newImage = ImageUtils.makeColorTransparent(image, redRange, greenRange, blueRange);
        } else if (tagName.equals(TAG_SHOW)) {
            JComponent contents = new JLabel(new ImageIcon(image));
            String message = applyMacros(child, ATTR_MESSAGE, (String) null);
            if (message != null) {
                contents = GuiUtils.topCenter(new JLabel(message), contents);
            }
            if (!GuiUtils.askOkCancel("Continue?", contents)) {
                throw new MyQuitException();
            }
        } else if (tagName.equals(TAG_MATTE)) {
            newImage = doMatte(image, child, 0);
        } else if (tagName.equals(TAG_LATLONLABELS)) {
            newImage = doLatLonLabels(child, viewManager, image, imageProps);
        } else if (tagName.equals(TAG_WRITE)) {
            ImageUtils.writeImageToFile(image, getImageFileName(applyMacros(child, ATTR_FILE)));

        } else if (tagName.equals(TAG_PUBLISH)) {
            getIdv().getPublishManager().publishIslImage(this, node, image);
        } else if (tagName.equals(TAG_CLIP)) {
            int[] ul;
            int[] lr;
            if (XmlUtil.hasAttribute(child, ATTR_DISPLAY)) {
                //                    System.err.println("Clipping from display");
                DisplayControlImpl dc = findDisplayControl(child);
                if (dc == null) {
                    throw new IllegalArgumentException("Could not find display:" + XmlUtil.toString(node));
                }
                NavigatedDisplay display = (NavigatedDisplay) viewManager.getMaster();
                MapProjection mapProjection = dc.getDataProjection();
                java.awt.geom.Rectangle2D rect = mapProjection.getDefaultMapArea();
                LatLonPoint llplr = mapProjection.getLatLon(new double[][] { { rect.getX() + rect.getWidth() },
                        { rect.getY() + rect.getHeight() } });
                LatLonPoint llpul = mapProjection
                        .getLatLon(new double[][] { { rect.getX() }, { rect.getY() } });
                EarthLocation ulEl = new EarthLocationTuple(llpul, new Real(RealType.Altitude, 0));
                EarthLocation lrEl = new EarthLocationTuple(llplr, new Real(RealType.Altitude, 0));
                ul = display.getScreenCoordinates(display.getSpatialCoordinates(ulEl, null));
                lr = display.getScreenCoordinates(display.getSpatialCoordinates(lrEl, null));
                //System.err.println("ul:" + ulEl + " lr:" + lrEl);
                if (ul[0] > lr[0]) {
                    int tmp = ul[0];
                    ul[0] = lr[0];
                    lr[0] = tmp;
                }
                if (ul[1] > lr[1]) {
                    int tmp = ul[1];
                    ul[1] = lr[1];
                    lr[1] = tmp;
                }
                imageProps.put(ATTR_NORTH, new Double(ulEl.getLatitude().getValue()));
                imageProps.put(ATTR_WEST, new Double(ulEl.getLongitude().getValue()));
                imageProps.put(ATTR_SOUTH, new Double(lrEl.getLatitude().getValue()));
                imageProps.put(ATTR_EAST, new Double(lrEl.getLongitude().getValue()));
            } else if ((viewManager != null) && XmlUtil.hasAttribute(child, ATTR_NORTH)) {
                NavigatedDisplay display = (NavigatedDisplay) viewManager.getMaster();
                EarthLocation el1 = DisplayControlImpl.makeEarthLocation(toDouble(child, ATTR_NORTH),
                        toDouble(child, ATTR_WEST), 0);
                EarthLocation el2 = DisplayControlImpl.makeEarthLocation(toDouble(child, ATTR_SOUTH),
                        toDouble(child, ATTR_EAST), 0);
                ul = display.getScreenCoordinates(display.getSpatialCoordinates(el1, null));
                lr = display.getScreenCoordinates(display.getSpatialCoordinates(el2, null));
                imageProps.put(ATTR_NORTH, new Double(el1.getLatitude().getValue()));
                imageProps.put(ATTR_WEST, new Double(el1.getLongitude().getValue()));
                imageProps.put(ATTR_SOUTH, new Double(el2.getLatitude().getValue()));
                imageProps.put(ATTR_EAST, new Double(el2.getLongitude().getValue()));
            } else if (XmlUtil.hasAttribute(child, ATTR_LEFT)) {
                ul = new int[] { (int) toDouble(child, ATTR_LEFT, imageWidth),
                        (int) toDouble(child, ATTR_TOP, imageHeight) };
                lr = new int[] { (int) toDouble(child, ATTR_RIGHT, imageWidth),
                        (int) toDouble(child, ATTR_BOTTOM, imageHeight) };
            } else if (viewManager != null) {
                //TODO: Clip on visad coordinates
                NavigatedDisplay display = (NavigatedDisplay) viewManager.getMaster();
                ul = display.getScreenCoordinates(new double[] { -1, 1, 0 });
                lr = display.getScreenCoordinates(new double[] { 1, -1, 0 });
                int space = applyMacros(child, ATTR_SPACE, 0);
                int hspace = applyMacros(child, ATTR_HSPACE, space);
                int vspace = applyMacros(child, ATTR_VSPACE, space);
                ul[0] -= applyMacros(child, ATTR_SPACE_LEFT, hspace);
                ul[1] -= applyMacros(child, ATTR_SPACE_TOP, vspace);
                lr[0] += applyMacros(child, ATTR_SPACE_RIGHT, hspace);
                lr[1] += applyMacros(child, ATTR_SPACE_BOTTOM, vspace);
            } else {
                continue;
            }

            for (String attr : (List<String>) Misc.newList(ATTR_NORTH, ATTR_SOUTH, ATTR_EAST, ATTR_WEST)) {
                String kmlAttr = "kml." + attr;
                if (XmlUtil.hasAttribute(child, kmlAttr)) {
                    imageProps.put(attr, new Double(applyMacros(child, kmlAttr, 0.0)));
                }
            }

            ul[0] = Math.max(0, ul[0]);
            ul[1] = Math.max(0, ul[1]);

            lr[0] = Math.min(lr[0], imageWidth);
            lr[1] = Math.min(lr[1], imageHeight);

            newImage = ImageUtils.clip(image, ul, lr);
        } else if (tagName.equals(TAG_SPLIT)) {
            shouldIterateChildren = false;
            int width = image.getWidth(null);
            int height = image.getHeight(null);
            int cols = applyMacros(child, ATTR_COLUMNS, 2);
            int rows = applyMacros(child, ATTR_ROWS, 2);
            String file = applyMacros(child, ATTR_FILE);
            int cnt = 0;
            int hSpace = width / cols;
            int vSpace = height / rows;
            for (int row = 0; row < rows; row++) {
                for (int col = 0; col < cols; col++) {
                    pushProperties();
                    Hashtable myprops = new Hashtable();
                    putProperty("row", new Integer(row));
                    putProperty("column", new Integer(col));
                    putProperty("count", new Integer(++cnt));
                    String realFile = applyMacros(file, myprops);
                    Image splitImage = image.getSubimage(hSpace * col, vSpace * row, hSpace, vSpace);
                    processImage(ImageUtils.toBufferedImage(splitImage), realFile, child, myprops, viewManager,
                            new Hashtable());
                    popProperties();
                }
            }
        } else if (tagName.equals(TAG_THUMBNAIL)) {
            shouldIterateChildren = false;
            BufferedImage thumbImage = ImageUtils.toBufferedImage(resize(image, child));
            String thumbFile = applyMacros(child, ATTR_FILE, (String) null);
            if (thumbFile == null) {
                thumbFile = IOUtil.stripExtension(filename) + "_thumb" + IOUtil.getFileExtension(filename);
            }
            processImage(thumbImage, thumbFile, child, null, viewManager, new Hashtable());
        } else if (tagName.equals(TAG_KML)) {
            //NOOP
        } else if (tagName.equals(TAG_KMZFILE)) {
            //NOOP
        } else if (tagName.equals(TAG_OVERLAY)) {
            double transparency = applyMacros(child, ATTR_TRANSPARENCY, 0.0);
            Graphics2D g = image.createGraphics();
            String imagePath = applyMacros(child, ATTR_IMAGE, (String) null);

            float scale = (float) applyMacros(child, ATTR_SCALE, 1.0);

            Rectangle imageRect = new Rectangle(0, 0, imageWidth, imageHeight);
            Point pp = ImageUtils.parsePoint(applyMacros(child, ATTR_PLACE, "lr,-10,-10"), imageRect);
            String text = applyMacros(child, ATTR_TEXT, (String) null);
            Color bg = applyMacros(child, ATTR_BACKGROUND, (Color) null);
            if (text != null) {
                double angle = Math.toRadians(applyMacros(child, ATTR_ANGLE, 0.0));
                text = applyMacros(text);
                Color c = applyMacros(child, ATTR_COLOR, Color.white);
                if ((c != null) && (transparency > 0)) {
                    c = new Color(c.getRed(), c.getGreen(), c.getBlue(), ImageUtils.toAlpha(transparency));
                }
                //Color bg = applyMacros(child, ATTR_BACKGROUND,
                //                       (Color) null);
                if ((bg != null) && (transparency > 0)) {
                    bg = new Color(bg.getRed(), bg.getGreen(), bg.getBlue(), ImageUtils.toAlpha(transparency));
                }
                setFont(g, child);
                FontMetrics fm = g.getFontMetrics();
                Rectangle2D rect = fm.getStringBounds(text, g);
                int width = (int) rect.getWidth();
                int height = (int) (rect.getHeight());

                Point ap = ImageUtils.parsePoint(applyMacros(child, ATTR_ANCHOR, "lr,-10,-10"),
                        new Rectangle(0, 0, width, height));

                g.rotate(angle);

                if (bg != null) {
                    g.setColor(bg);
                    g.fillRect(pp.x - ap.x - 1, pp.y - ap.y - 1, (int) width + 2, (int) height + 2);
                }
                g.setColor(c);
                g.drawString(text, pp.x - ap.x, pp.y - ap.y + height);
            }

            if (imagePath != null) {
                Image overlay = ImageUtils.readImage(imagePath);
                if (overlay != null) {
                    if (transparency > 0) {
                        overlay = ImageUtils.setAlpha(overlay, transparency);
                    }

                    int width = overlay.getWidth(null);
                    int height = overlay.getHeight(null);
                    int scaledWidth = Math.round(width * scale);
                    int scaledHeight = Math.round(height * scale);

                    Image scaled = getScaledImage(overlay, scaledWidth, scaledHeight);
                    Rectangle overlayRect = new Rectangle(0, 0, scaledWidth, scaledHeight);
                    Point ap = ImageUtils.parsePoint(applyMacros(child, ATTR_ANCHOR, "lr,-10,-10"),
                            overlayRect);
                    g.drawImage(scaled, pp.x - ap.x, pp.y - ap.y, bg, null);
                }
            }
        } else {
            error("Unknown tag:" + tagName);
        }
        if (newImage != null) {
            String newFileName = applyMacros(child, ATTR_FILE, (String) null);
            if (shouldIterateChildren) {
                logger.trace("newFileName='{}' viewManager={} newImage={}", newFileName, viewManager, newImage);
                newImage = processImage(newImage, newFileName, child, null, viewManager, new Hashtable());
                logger.trace("finished processImage; result: {}", newImage);
            }
            if (newFileName != null) {
                logger.trace("calling writeImageToFile...");
                ImageUtils.writeImageToFile(newImage, getImageFileName(newFileName));
                logger.trace("finished writeImageToFile");
                debug("Writing image:" + newFileName);
            }
            if (!applyMacros(child, ATTR_COPY, false)) {
                image = newImage;
            }
        }
    }

    if (filename != null) {
        float quality = (float) applyMacros(node, ATTR_QUALITY, 1.0);
        List<String> fileToks = StringUtil.split(filename, ",", true, true);
        for (String file : fileToks) {
            file = getImageFileName(file);
            debug("Writing image:" + file);
            if (file.endsWith(FileManager.SUFFIX_KMZ) || file.endsWith(FileManager.SUFFIX_KML)) {
                GeoLocationInfo bounds = null;
                if (viewManager != null) {
                    bounds = viewManager.getVisibleGeoBounds();
                    ImageSequenceGrabber.subsetBounds(bounds, imageProps);
                    String tmpImageFile = getOutputPath(file);
                    ImageUtils.writeImageToFile(image, tmpImageFile, quality);
                    ImageWrapper imageWrapper = new ImageWrapper(tmpImageFile, null, bounds, null);
                    imageWrapper.setProperties(imageProps);
                    new ImageSequenceGrabber(file, getIdv(), this, node,
                            (List<ImageWrapper>) Misc.newList(imageWrapper), null, 1);
                }
            } else {
                logger.trace("another writeImageToFile call...");
                ImageUtils.writeImageToFile(image, file, quality);
                logger.trace("and it's done.");
            }
        }
    }
    logger.trace("result: {}", image);
    return image;
}