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

gov.nasa.worldwind.data.BufferedImageRaster Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */
package gov.nasa.worldwind.data;

import gov.nasa.worldwind.*;
import gov.nasa.worldwind.avlist.*;
import gov.nasa.worldwind.cache.Cacheable;
import gov.nasa.worldwind.formats.tiff.GeoTiff;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.util.*;

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.util.Calendar;

/**
 * @author dcollins
 * @version $Id: BufferedImageRaster.java 1171 2013-02-11 21:45:02Z dcollins $
 */
public class BufferedImageRaster extends AbstractDataRaster implements Cacheable, Disposable
{
    private java.awt.image.BufferedImage bufferedImage;
    private java.awt.Graphics2D g2d;

    public BufferedImageRaster(Sector sector, java.awt.image.BufferedImage bufferedImage)
    {
        this(sector, bufferedImage, null);
    }

    public BufferedImageRaster(Sector sector, java.awt.image.BufferedImage bufferedImage, AVList list)
    {
        super((null != bufferedImage) ? bufferedImage.getWidth() : 0,
            (null != bufferedImage) ? bufferedImage.getHeight() : 0,
            sector, list);

        if (bufferedImage == null)
        {
            String message = Logging.getMessage("nullValue.ImageIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.bufferedImage = bufferedImage;
    }

    public BufferedImageRaster(int width, int height, int transparency, Sector sector)
    {
        super(width, height, sector);

        if (width < 1)
        {
            String message = Logging.getMessage("generic.InvalidWidth", width);
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        if (height < 1)
        {
            String message = Logging.getMessage("generic.InvalidHeight", height);
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.bufferedImage = ImageUtil.createCompatibleImage(width, height, transparency);
    }

    public java.awt.image.BufferedImage getBufferedImage()
    {
        return this.bufferedImage;
    }

    public java.awt.Graphics2D getGraphics()
    {
        if (this.g2d == null)
        {
            this.g2d = this.bufferedImage.createGraphics();
            // Enable bilinear interpolation.
            this.g2d.setRenderingHint(java.awt.RenderingHints.KEY_INTERPOLATION,
                java.awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        }
        return g2d;
    }

    public void drawOnTo(DataRaster canvas)
    {
        if (canvas == null)
        {
            String message = Logging.getMessage("nullValue.DestinationIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }
        if (!(canvas instanceof BufferedImageRaster))
        {
            String message = Logging.getMessage("DataRaster.IncompatibleRaster", canvas);
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.doDrawOnTo((BufferedImageRaster) canvas);
    }

    public void fill(java.awt.Color color)
    {
        if (color == null)
        {
            String message = Logging.getMessage("nullValue.ColorIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        java.awt.Graphics2D g2d = this.getGraphics();

        // Keep track of the previous color.
        java.awt.Color prevColor = g2d.getColor();
        try
        {
            // Fill the raster with the specified color.
            g2d.setColor(color);
            g2d.fillRect(0, 0, this.getWidth(), this.getHeight());
        }
        finally
        {
            // Restore the previous color.
            g2d.setColor(prevColor);
        }
    }

    public long getSizeInBytes()
    {
        long size = 0L;
        java.awt.image.Raster raster = this.bufferedImage.getRaster();
        if (raster != null)
        {
            java.awt.image.DataBuffer db = raster.getDataBuffer();
            if (db != null)
            {
                size = sizeOfDataBuffer(db);
            }
        }
        return size;
    }

//    public void finalize()
//    {
//        try
//        {
//            super.finalize();
//            this.dispose();
//        }
//        catch (Throwable t)
//        {
//            Logging.logger().log(java.util.logging.Level.FINEST, t.getMessage(), t);
//        }
//    }

    public void dispose()
    {
        if (this.g2d != null)
        {
            this.g2d.dispose();
            this.g2d = null;
        }

        if (this.bufferedImage != null)
        {
            this.bufferedImage.flush();
            this.bufferedImage = null;
        }
    }

//    protected void doDrawOnTo(BufferedImageRaster canvas)
//    {
//        Sector sector = this.getSector();
//        if (null == sector)
//        {
//            String message = Logging.getMessage("nullValue.SectorIsNull");
//            Logging.logger().severe(message);
//            throw new IllegalArgumentException(message);
//        }
//
//        if (!sector.intersects(canvas.getSector()))
//        {
//            return;
//        }
//
//        BufferedImage transformedImage = null;
//        java.awt.Graphics2D g2d = null;
//        java.awt.Shape prevClip = null;
//        java.awt.Composite prevComposite = null;
//
//        try
//        {
//            int canvasWidth = canvas.getWidth();
//            int canvasHeight = canvas.getHeight();
//
//            // Apply the transform that correctly maps the image onto the canvas.
//            java.awt.geom.AffineTransform transform = this.computeSourceToDestTransform(
//                this.getWidth(), this.getHeight(), this.getSector(), canvasWidth, canvasHeight, canvas.getSector());
//
//            AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
//            Rectangle2D rect = op.getBounds2D(this.getBufferedImage());
//
//            int clipWidth = (int) Math.ceil((rect.getMaxX() >= canvasWidth) ? canvasWidth : rect.getMaxX());
//            int clipHeight = (int) Math.ceil((rect.getMaxY() >= canvasHeight) ? canvasHeight : rect.getMaxY());
//
//            if (clipWidth <= 0 || clipHeight <= 0)
//            {
//                return;
//            }
//
//            int transformedImageType = (BufferedImage.TYPE_CUSTOM != this.getBufferedImage().getType())
//                ? this.getBufferedImage().getType() : BufferedImage.TYPE_INT_ARGB;
//
//            transformedImage = new BufferedImage(clipWidth, clipHeight, transformedImageType);
//            op.filter(this.getBufferedImage(), transformedImage);
//
//            g2d = canvas.getGraphics();
//
//            prevClip = g2d.getClip();
//            prevComposite = g2d.getComposite();
//
//            // Set the alpha composite for appropriate alpha blending.
//            g2d.setComposite(java.awt.AlphaComposite.SrcOver);
//            g2d.drawImage(transformedImage, 0, 0, null);
//        }
//        catch (java.awt.image.ImagingOpException ioe)
//        {
//            // If we catch a ImagingOpException, then the transformed image has a width or height of 0.
//            // This indicates that there is no intersection between the source image and the canvas,
//            // or the intersection is smaller than one pixel.
//        }
//        catch (java.awt.image.RasterFormatException rfe)
//        {
//            // If we catch a RasterFormatException, then the transformed image has a width or height of 0.
//            // This indicates that there is no intersection between the source image and the canvas,
//            // or the intersection is smaller than one pixel.
//        }
//        finally
//        {
//            // Restore the previous clip, composite, and transform.
//            try
//            {
//                if (null != transformedImage)
//                {
//                    transformedImage.flush();
//                }
//
//                if (null != g2d)
//                {
//                    if (null != prevClip)
//                    {
//                        g2d.setClip(prevClip);
//                    }
//
//                    if (null != prevComposite)
//                    {
//                        g2d.setComposite(prevComposite);
//                    }
//                }
//            }
//            catch (Throwable t)
//            {
//                Logging.logger().log(java.util.logging.Level.FINEST, WWUtil.extractExceptionReason(t), t);
//            }
//        }
//    }

    protected void doDrawOnTo(BufferedImageRaster canvas)
    {
        Sector sector = this.getSector();
        if (null == sector)
        {
            String message = Logging.getMessage("nullValue.SectorIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        if (!sector.intersects(canvas.getSector()))
        {
            return;
        }

        java.awt.Graphics2D g2d = null;
        java.awt.Shape prevClip = null;
        java.awt.Composite prevComposite = null;
        java.lang.Object prevInterpolation = null, prevAntialiasing = null;

        try
        {
            int canvasWidth = canvas.getWidth();
            int canvasHeight = canvas.getHeight();

            // Apply the transform that correctly maps the image onto the canvas.
            java.awt.geom.AffineTransform transform = this.computeSourceToDestTransform(
                this.getWidth(), this.getHeight(), this.getSector(), canvasWidth, canvasHeight, canvas.getSector());

            AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
            Rectangle2D rect = op.getBounds2D(this.getBufferedImage());

            int clipWidth = (int) Math.ceil((rect.getMaxX() >= canvasWidth) ? canvasWidth : rect.getMaxX());
            int clipHeight = (int) Math.ceil((rect.getMaxY() >= canvasHeight) ? canvasHeight : rect.getMaxY());

            if (clipWidth <= 0 || clipHeight <= 0)
            {
                return;
            }

            g2d = canvas.getGraphics();

            prevClip = g2d.getClip();
            prevComposite = g2d.getComposite();
            prevInterpolation = g2d.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
            prevAntialiasing = g2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING);

            // Set the alpha composite for appropriate alpha blending.
            g2d.setComposite(java.awt.AlphaComposite.SrcOver);
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            g2d.drawImage(this.getBufferedImage(), transform, null);
        }
//        catch (java.awt.image.ImagingOpException ioe)
//        {
//            // If we catch a ImagingOpException, then the transformed image has a width or height of 0.
//            // This indicates that there is no intersection between the source image and the canvas,
//            // or the intersection is smaller than one pixel.
//        }
//        catch (java.awt.image.RasterFormatException rfe)
//        {
//            // If we catch a RasterFormatException, then the transformed image has a width or height of 0.
//            // This indicates that there is no intersection between the source image and the canvas,
//            // or the intersection is smaller than one pixel.
//        }
        catch (Throwable t)
        {
            String reason = WWUtil.extractExceptionReason(t);
            Logging.logger().log(java.util.logging.Level.SEVERE, reason, t);
        }
        finally
        {
            // Restore the previous clip, composite, and transform.
            try
            {
                if (null != g2d)
                {
                    if (null != prevClip)
                        g2d.setClip(prevClip);

                    if (null != prevComposite)
                        g2d.setComposite(prevComposite);

                    if (null != prevInterpolation)
                        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, prevInterpolation);

                    if (null != prevAntialiasing)
                        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, prevAntialiasing);
                }
            }
            catch (Throwable t)
            {
                Logging.logger().log(java.util.logging.Level.FINEST, WWUtil.extractExceptionReason(t), t);
            }
        }
    }

    private static long sizeOfDataBuffer(java.awt.image.DataBuffer dataBuffer)
    {
        return sizeOfElement(dataBuffer.getDataType()) * dataBuffer.getSize();
    }

    private static long sizeOfElement(int dataType)
    {
        switch (dataType)
        {
            case java.awt.image.DataBuffer.TYPE_BYTE:
                return (Byte.SIZE / 8);
            case java.awt.image.DataBuffer.TYPE_DOUBLE:
                return (Double.SIZE / 8);
            case java.awt.image.DataBuffer.TYPE_FLOAT:
                return (Float.SIZE / 8);
            case java.awt.image.DataBuffer.TYPE_INT:
                return (Integer.SIZE / 8);
            case java.awt.image.DataBuffer.TYPE_SHORT:
            case java.awt.image.DataBuffer.TYPE_USHORT:
                return (Short.SIZE / 8);
            case java.awt.image.DataBuffer.TYPE_UNDEFINED:
                break;
        }
        return 0L;
    }

    public static DataRaster wrap(BufferedImage image, AVList params)
    {
        if (null == image)
        {
            String message = Logging.getMessage("nullValue.ImageIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        if (null == params)
        {
            String msg = Logging.getMessage("nullValue.AVListIsNull");
            Logging.logger().finest(msg);
            throw new IllegalArgumentException(msg);
        }

        if (params.hasKey(AVKey.WIDTH))
        {
            int width = (Integer) params.getValue(AVKey.WIDTH);
            if (width != image.getWidth())
            {
                String msg = Logging.getMessage("generic.InvalidWidth", "" + width + "!=" + image.getWidth());
                Logging.logger().finest(msg);
                throw new IllegalArgumentException(msg);
            }
        }
        else
        {
            params.setValue(AVKey.WIDTH, image.getWidth());
        }

        if (params.hasKey(AVKey.HEIGHT))
        {
            int height = (Integer) params.getValue(AVKey.HEIGHT);
            if (height != image.getHeight())
            {
                String msg = Logging.getMessage("generic.InvalidHeight", "" + height + "!=" + image.getHeight());
                Logging.logger().finest(msg);
                throw new IllegalArgumentException(msg);
            }
        }
        else
        {
            params.setValue(AVKey.HEIGHT, image.getHeight());
        }

        Sector sector = null;
        if (params.hasKey(AVKey.SECTOR))
        {
            Object o = params.getValue(AVKey.SECTOR);
            if (o instanceof Sector)
            {
                sector = (Sector) o;
            }
        }

        return new BufferedImageRaster(sector, image, params);
    }

    public static DataRaster wrapAsGeoreferencedRaster(BufferedImage image, AVList params)
    {
        if (null == image)
        {
            String message = Logging.getMessage("nullValue.ImageIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        if (null == params)
        {
            String msg = Logging.getMessage("nullValue.AVListIsNull");
            Logging.logger().finest(msg);
            throw new IllegalArgumentException(msg);
        }

        if (params.hasKey(AVKey.WIDTH))
        {
            int width = (Integer) params.getValue(AVKey.WIDTH);
            if (width != image.getWidth())
            {
                String msg = Logging.getMessage("generic.InvalidWidth", "" + width + "!=" + image.getWidth());
                Logging.logger().finest(msg);
                throw new IllegalArgumentException(msg);
            }
        }

        if (params.hasKey(AVKey.HEIGHT))
        {
            int height = (Integer) params.getValue(AVKey.HEIGHT);
            if (height != image.getHeight())
            {
                String msg = Logging.getMessage("generic.InvalidHeight", "" + height + "!=" + image.getHeight());
                Logging.logger().finest(msg);
                throw new IllegalArgumentException(msg);
            }
        }

        if (!params.hasKey(AVKey.SECTOR))
        {
            String msg = Logging.getMessage("generic.MissingRequiredParameter", AVKey.SECTOR);
            Logging.logger().finest(msg);
            throw new IllegalArgumentException(msg);
        }

        Sector sector = (Sector) params.getValue(AVKey.SECTOR);
        if (null == sector)
        {
            String msg = Logging.getMessage("nullValue.SectorIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        if (!params.hasKey(AVKey.COORDINATE_SYSTEM))
        {
            // assume Geodetic Coordinate System
            params.setValue(AVKey.COORDINATE_SYSTEM, AVKey.COORDINATE_SYSTEM_GEOGRAPHIC);
        }

        String cs = params.getStringValue(AVKey.COORDINATE_SYSTEM);
        if (!params.hasKey(AVKey.PROJECTION_EPSG_CODE))
        {
            if (AVKey.COORDINATE_SYSTEM_GEOGRAPHIC.equals(cs))
            {
                // assume WGS84
                params.setValue(AVKey.PROJECTION_EPSG_CODE, GeoTiff.GCS.WGS_84);
            }
            else
            {
                String msg = Logging.getMessage("generic.MissingRequiredParameter", AVKey.PROJECTION_EPSG_CODE);
                Logging.logger().finest(msg);
                throw new IllegalArgumentException(msg);
            }
        }

        // if PIXEL_WIDTH is specified, we are not overriding it because UTM images
        // will have different pixel size
        if (!params.hasKey(AVKey.PIXEL_WIDTH))
        {
            if (AVKey.COORDINATE_SYSTEM_GEOGRAPHIC.equals(cs))
            {
                double pixelWidth = sector.getDeltaLonDegrees() / (double) image.getWidth();
                params.setValue(AVKey.PIXEL_WIDTH, pixelWidth);
            }
            else
            {
                String msg = Logging.getMessage("generic.MissingRequiredParameter", AVKey.PIXEL_WIDTH);
                Logging.logger().finest(msg);
                throw new IllegalArgumentException(msg);
            }
        }

        // if PIXEL_HEIGHT is specified, we are not overriding it
        // because UTM images will have different pixel size
        if (!params.hasKey(AVKey.PIXEL_HEIGHT))
        {
            if (AVKey.COORDINATE_SYSTEM_GEOGRAPHIC.equals(cs))
            {
                double pixelHeight = sector.getDeltaLatDegrees() / (double) image.getHeight();
                params.setValue(AVKey.PIXEL_HEIGHT, pixelHeight);
            }
            else
            {
                String msg = Logging.getMessage("generic.MissingRequiredParameter", AVKey.PIXEL_HEIGHT);
                Logging.logger().finest(msg);
                throw new IllegalArgumentException(msg);
            }
        }

        if (!params.hasKey(AVKey.PIXEL_FORMAT))
        {
            params.setValue(AVKey.PIXEL_FORMAT, AVKey.IMAGE);
        }
        else if (!AVKey.IMAGE.equals(params.getStringValue(AVKey.PIXEL_FORMAT)))
        {
            String msg = Logging.getMessage("generic.UnknownValueForKey",
                params.getStringValue(AVKey.PIXEL_FORMAT), AVKey.PIXEL_FORMAT);
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }

        if (!params.hasKey(AVKey.ORIGIN) && AVKey.COORDINATE_SYSTEM_GEOGRAPHIC.equals(cs))
        {
            // set UpperLeft corner as the origin, if not specified
            LatLon origin = new LatLon(sector.getMaxLatitude(), sector.getMinLongitude());
            params.setValue(AVKey.ORIGIN, origin);
        }

        if (!params.hasKey(AVKey.DATE_TIME))
        {
            // add NUL (\0) termination as required by TIFF v6 spec (20 bytes length)
            String timestamp = String.format("%1$tY:%1$tm:%1$td %tT\0", Calendar.getInstance());
            params.setValue(AVKey.DATE_TIME, timestamp);
        }

        if (!params.hasKey(AVKey.VERSION))
        {
            params.setValue(AVKey.VERSION, Version.getVersion());
        }

        boolean hasAlpha = (null != image.getColorModel() && image.getColorModel().hasAlpha());
        params.setValue(AVKey.RASTER_HAS_ALPHA, hasAlpha);

        return new BufferedImageRaster(sector, image, params);
    }

    @Override
    DataRaster doGetSubRaster(int roiWidth, int roiHeight, Sector roiSector, AVList roiParams)
    {
        int transparency = java.awt.image.BufferedImage.TRANSLUCENT; // TODO: make configurable
        BufferedImageRaster canvas = new BufferedImageRaster(roiWidth, roiHeight, transparency, roiSector);
        this.drawOnTo(canvas);
        return canvas;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy