Example usage for java.awt Graphics2D setRenderingHint

List of usage examples for java.awt Graphics2D setRenderingHint

Introduction

In this page you can find the example usage for java.awt Graphics2D setRenderingHint.

Prototype

public abstract void setRenderingHint(Key hintKey, Object hintValue);

Source Link

Document

Sets the value of a single preference for the rendering algorithms.

Usage

From source file:uk.co.real_logic.aeron.tools.perf_tools.AeronLatencyUnderLoadPublisher.java

private void generateScatterPlot() throws IOException {
    final BufferedImage image = new BufferedImage(1800, 1000, BufferedImage.TYPE_INT_ARGB);
    final Graphics2D g2 = image.createGraphics();
    final FontMetrics fm = g2.getFontMetrics();
    final String filename = "throughputency.png";
    final File imageFile = new File(filename);

    final int height = 940;
    double min = Double.MAX_VALUE;
    double max = Double.MIN_VALUE;
    for (final long timestamp : timestamps) {
        final double ts = timestamp / 1000.0;
        if (ts < min) {
            min = ts;//from   www . j a v  a2 s  .  co m
        }
        if (ts > max) {
            max = ts;
        }
    }
    final double stepY = height / max;

    g2.setColor(Color.white);
    g2.fillRect(0, 0, 1800, 1000);
    g2.setColor(Color.black);
    g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    g2.drawString("Latency ScatterPlot (microseconds)",
            900 - fm.stringWidth("Latency ScatterPlot (microseconds)") / 2, 20);
    g2.drawString("" + max, 10, 20);
    g2.drawLine(100, 20, 100, 960);
    g2.drawLine(100, 960, 1790, 960);
    int start = 0;
    int end = 100;
    final double width = 1690.0 / 7.0;
    g2.setColor(Color.red);
    plotSubset(g2, start, end, "10 msgs/sec", 100, width, stepY, means[0]);

    start = 100;
    end = 1100;
    g2.setColor(Color.green);
    plotSubset(g2, start, end, "100 msgs/sec", 100 + width, width, stepY, means[1]);

    start = 1100;
    end = 11100;
    g2.setColor(Color.blue);
    plotSubset(g2, start, end, "1K msgs/sec", 100 + width * 2, width, stepY, means[2]);

    start = 11100;
    end = 111100;
    g2.setColor(Color.cyan);
    plotSubset(g2, start, end, "10K msgs/sec", 100 + width * 3, width, stepY, means[3]);

    start = 111100;
    end = 1111100;
    g2.setColor(Color.magenta);
    plotSubset(g2, start, end, "100K msgs/sec", 100 + width * 4, width, stepY, means[4]);

    start = 1111100;
    end = 11111100;
    g2.setColor(Color.yellow);
    plotSubset(g2, start, end, "1M msgs/sec", 100 + width * 5, width, stepY, means[5]);

    start = 11111100;
    end = 41111100;
    g2.setColor(Color.orange);
    plotSubset(g2, start, end, "3M msgs/sec", 100 + width * 6, width, stepY, means[6]);

    ImageIO.write(image, "png", imageFile);
}

From source file:au.org.ala.biocache.web.MapController.java

@Deprecated
@RequestMapping(value = "/occurrences/wms", method = RequestMethod.GET)
public void pointsWmsImage(SpatialSearchRequestParams requestParams,
        @RequestParam(value = "colourby", required = false, defaultValue = "0") Integer colourby,
        @RequestParam(value = "width", required = false, defaultValue = "256") Integer widthObj,
        @RequestParam(value = "height", required = false, defaultValue = "256") Integer heightObj,
        @RequestParam(value = "zoom", required = false, defaultValue = "0") Integer zoomLevel,
        @RequestParam(value = "symsize", required = false, defaultValue = "4") Integer symsize,
        @RequestParam(value = "symbol", required = false, defaultValue = "circle") String symbol,
        @RequestParam(value = "bbox", required = false, defaultValue = "110,-45,157,-9") String bboxString,
        @RequestParam(value = "type", required = false, defaultValue = "normal") String type,
        @RequestParam(value = "outline", required = true, defaultValue = "false") boolean outlinePoints,
        @RequestParam(value = "outlineColour", required = true, defaultValue = "0x000000") String outlineColour,
        HttpServletResponse response) throws Exception {

    // size of the circles
    int size = symsize.intValue();
    int width = widthObj.intValue();
    int height = heightObj.intValue();

    requestParams.setStart(0);/*from  w  w w  . j av a  2 s  .c  o m*/
    requestParams.setPageSize(Integer.MAX_VALUE);
    String query = requestParams.getQ();
    String[] filterQuery = requestParams.getFq();

    if (StringUtils.isBlank(query) && StringUtils.isBlank(requestParams.getFormattedQuery())) {
        displayBlankImage(width, height, false, response);
        return;
    }

    // let's force it to PNG's for now 
    response.setContentType("image/png");

    // Convert array to list so we append more values onto it
    ArrayList<String> fqList = null;
    if (filterQuery != null) {
        fqList = new ArrayList<String>(Arrays.asList(filterQuery));
    } else {
        fqList = new ArrayList<String>();
    }

    // the bounding box
    double[] bbox = new double[4];
    int i;
    i = 0;
    for (String s : bboxString.split(",")) {
        try {
            bbox[i] = Double.parseDouble(s);
            i++;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    double pixelWidth = (bbox[2] - bbox[0]) / width;
    double pixelHeight = (bbox[3] - bbox[1]) / height;
    bbox[0] += pixelWidth / 2;
    bbox[2] -= pixelWidth / 2;
    bbox[1] += pixelHeight / 2;
    bbox[3] -= pixelHeight / 2;

    //offset for points bounding box by size
    double xoffset = (bbox[2] - bbox[0]) / (double) width * (size * 2);
    double yoffset = (bbox[3] - bbox[1]) / (double) height * (size * 2);

    //adjust offset for pixel height/width
    xoffset += pixelWidth;
    yoffset += pixelHeight;

    double[] bbox2 = new double[4];
    bbox2[0] = convertMetersToLng(bbox[0] - xoffset);
    bbox2[1] = convertMetersToLat(bbox[1] - yoffset);
    bbox2[2] = convertMetersToLng(bbox[2] + xoffset);
    bbox2[3] = convertMetersToLat(bbox[3] + yoffset);

    bbox[0] = convertMetersToLng(bbox[0]);
    bbox[1] = convertMetersToLat(bbox[1]);
    bbox[2] = convertMetersToLng(bbox[2]);
    bbox[3] = convertMetersToLat(bbox[3]);

    double[] pbbox = new double[4]; //pixel bounding box
    pbbox[0] = convertLngToPixel(bbox[0]);
    pbbox[1] = convertLatToPixel(bbox[1]);
    pbbox[2] = convertLngToPixel(bbox[2]);
    pbbox[3] = convertLatToPixel(bbox[3]);

    String bboxString2 = bbox2[0] + "," + bbox2[1] + "," + bbox2[2] + "," + bbox2[3];
    bboxToQuery(bboxString2, fqList);

    PointType pointType = getPointTypeForZoomLevel(zoomLevel);

    String[] newFilterQuery = (String[]) fqList.toArray(new String[fqList.size()]); // convert back to array

    requestParams.setFq(newFilterQuery);

    List<OccurrencePoint> points = searchDAO.getFacetPoints(requestParams, pointType);
    logger.debug("Points search for " + pointType.getLabel() + " - found: " + points.size());

    if (points.size() == 0) {
        displayBlankImage(width, height, false, response);
        return;
    }

    BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = (Graphics2D) img.getGraphics();
    g.setColor(Color.RED);

    int x, y;
    int pointWidth = size * 2;
    double width_mult = (width / (pbbox[2] - pbbox[0]));
    double height_mult = (height / (pbbox[1] - pbbox[3]));

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    Color oColour = Color.decode(outlineColour);

    for (i = 0; i < points.size(); i++) {
        OccurrencePoint pt = points.get(i);
        float lng = pt.getCoordinates().get(0).floatValue();
        float lat = pt.getCoordinates().get(1).floatValue();

        x = (int) ((convertLngToPixel(lng) - pbbox[0]) * width_mult);
        y = (int) ((convertLatToPixel(lat) - pbbox[3]) * height_mult);

        if (colourby != null) {
            int colour = 0xFF000000 | colourby.intValue();
            Color c = new Color(colour);
            g.setPaint(c);
        } else {
            g.setPaint(Color.blue);
        }

        // g.fillOval(x - (size / 2), y - (size / 2), pointWidth, pointWidth);
        Shape shp = getShape(symbol, x - (size / 2), y - (size / 2), pointWidth, pointWidth);
        g.draw(shp);
        g.fill(shp);
        if (outlinePoints) {
            g.setPaint(oColour);
            g.drawOval(x - (size / 2), y - (size / 2), pointWidth, pointWidth);
        }
    }

    g.dispose();

    try {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(img, "png", outputStream);
        ServletOutputStream outStream = response.getOutputStream();
        outStream.write(outputStream.toByteArray());
        outStream.flush();
        outStream.close();

    } catch (Exception e) {
        logger.error("Unable to write image", e);
    }
}

From source file:net.technicpack.launcher.lang.ResourceLoader.java

public BufferedImage getCircleClippedImage(String imageName) {
    BufferedImage contentImage = getImage(imageName);

    // copy the picture to an image with transparency capabilities
    BufferedImage outputImage = new BufferedImage(contentImage.getWidth(), contentImage.getHeight(),
            BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = (Graphics2D) outputImage.getGraphics();
    g2.drawImage(contentImage, 0, 0, null);

    // Create the area around the circle to cut out
    Area cutOutArea = new Area(new Rectangle(0, 0, outputImage.getWidth(), outputImage.getHeight()));

    int diameter = (outputImage.getWidth() < outputImage.getHeight()) ? outputImage.getWidth()
            : outputImage.getHeight();/*from   ww  w. jav  a  2s . co m*/
    cutOutArea.subtract(new Area(new Ellipse2D.Float((outputImage.getWidth() - diameter) / 2,
            (outputImage.getHeight() - diameter) / 2, diameter, diameter)));

    // Set the fill color to an opaque color
    g2.setColor(Color.WHITE);
    // Set the composite to clear pixels
    g2.setComposite(AlphaComposite.Clear);
    // Turn on antialiasing
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    // Clear the cut out area
    g2.fill(cutOutArea);

    // dispose of the graphics object
    g2.dispose();

    return outputImage;
}

From source file:org.geoserver.wms.legendgraphic.ColorMapLegendCreator.java

private Queue<BufferedImage> createBody() {

    final Queue<BufferedImage> queue = new LinkedList<BufferedImage>();

    ///*  w w  w . j  av  a2 s.  c o  m*/
    // draw the various elements
    //
    // create the boxes for drawing later
    final int rowHeight = (int) Math.round(rowH);
    final int colorWidth = (int) Math.round(colorW);
    final int ruleWidth = (int) Math.round(ruleW);
    final int labelWidth = (int) Math.round(labelW);
    final Rectangle clipboxA = new Rectangle(0, 0, colorWidth, rowHeight);
    final Rectangle clipboxB = new Rectangle(0, 0, ruleWidth, rowHeight);
    final Rectangle clipboxC = new Rectangle(0, 0, labelWidth, rowHeight);

    //
    // Body
    //
    //
    // draw the various bodyCells
    for (ColorMapEntryLegendBuilder row : bodyRows) {

        //
        // row number i
        //
        // get element for color default behavior
        final Cell colorCell = row.getColorManager();
        // draw it
        final BufferedImage colorCellLegend = new BufferedImage(colorWidth, rowHeight,
                BufferedImage.TYPE_INT_ARGB);
        Graphics2D rlg = colorCellLegend.createGraphics();
        rlg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        rlg.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        colorCell.draw(rlg, clipboxA, border);
        rlg.dispose();

        BufferedImage ruleCellLegend = null;
        if (forceRule) {
            // get element for rule
            final Cell ruleCell = row.getRuleManager();
            // draw it
            ruleCellLegend = new BufferedImage(ruleWidth, rowHeight, BufferedImage.TYPE_INT_ARGB);
            rlg = ruleCellLegend.createGraphics();
            rlg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            rlg.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            ruleCell.draw(rlg, clipboxB, borderRule);
            rlg.dispose();
        }

        // draw it if it is present
        if (labelWidth > 0) {
            // get element for label
            final Cell labelCell = row.getLabelManager();
            if (labelCell != null) {
                final BufferedImage labelCellLegend = new BufferedImage(labelWidth, rowHeight,
                        BufferedImage.TYPE_INT_ARGB);
                rlg = labelCellLegend.createGraphics();
                rlg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                rlg.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
                labelCell.draw(rlg, clipboxC, borderLabel);
                rlg.dispose();

                //
                // merge the bodyCells for this row
                //
                //

                final Map<Key, Object> hintsMap = new HashMap<Key, Object>();
                queue.add(LegendUtils.hMergeBufferedImages(colorCellLegend, ruleCellLegend, labelCellLegend,
                        hintsMap, transparent, backgroundColor, dx));
            } else {
                final Map<Key, Object> hintsMap = new HashMap<Key, Object>();
                queue.add(LegendUtils.hMergeBufferedImages(colorCellLegend, ruleCellLegend, null, hintsMap,
                        transparent, backgroundColor, dx));
            }

        } else {
            //
            // merge the bodyCells for this row
            //
            //

            final Map<Key, Object> hintsMap = new HashMap<Key, Object>();
            queue.add(LegendUtils.hMergeBufferedImages(colorCellLegend, ruleCellLegend, null, hintsMap,
                    transparent, backgroundColor, dx));

        }

    }

    // return the list of legends
    return queue;// mergeRows(queue);
}

From source file:net.technicpack.ui.lang.ResourceLoader.java

public BufferedImage getCircleClippedImage(BufferedImage contentImage) {
    // copy the picture to an image with transparency capabilities
    BufferedImage outputImage = new BufferedImage(contentImage.getWidth(), contentImage.getHeight(),
            BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = (Graphics2D) outputImage.getGraphics();
    g2.drawImage(contentImage, 0, 0, null);

    // Create the area around the circle to cut out
    Area cutOutArea = new Area(new Rectangle(0, 0, outputImage.getWidth(), outputImage.getHeight()));

    int diameter = (outputImage.getWidth() < outputImage.getHeight()) ? outputImage.getWidth()
            : outputImage.getHeight();//from  ww  w  .j ava 2 s  . co m
    cutOutArea.subtract(new Area(new Ellipse2D.Float((outputImage.getWidth() - diameter) / 2,
            (outputImage.getHeight() - diameter) / 2, diameter, diameter)));

    // Set the fill color to an opaque color
    g2.setColor(Color.WHITE);
    // Set the composite to clear pixels
    g2.setComposite(AlphaComposite.Clear);
    // Turn on antialiasing
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    // Clear the cut out area
    g2.fill(cutOutArea);

    // dispose of the graphics object
    g2.dispose();

    return outputImage;
}

From source file:org.tros.logo.swing.LogoPanel.java

@Override
public void forward(final double distance) {
    Drawable command = new Drawable() {

        @Override/*from  w ww.ja  va  2s. c  o m*/
        public void draw(Graphics2D g2, TurtleState turtleState) {
            double newx = turtleState.penX + (distance * Math.cos(turtleState.angle));
            double newy = turtleState.penY + (distance * Math.sin(turtleState.angle));

            if (!turtleState.penup) {
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2.draw(new Line2D.Double(turtleState.penX, turtleState.penY, newx, newy));
            }

            turtleState.penX = newx;
            turtleState.penY = newy;
        }

        @Override
        public void addListener(DrawListener listener) {
        }

        @Override
        public void removeListener(DrawListener listener) {
        }

        @Override
        public Drawable cloneDrawable() {
            return this;
        }
    };
    submitCommand(command);
}

From source file:org.tros.logo.swing.LogoPanel.java

@Override
public void backward(final double distance) {
    Drawable command = new Drawable() {

        @Override/*from  www . j  a  v a2  s.co m*/
        public void draw(Graphics2D g2, TurtleState turtleState) {
            double newx = turtleState.penX - (distance * Math.cos(turtleState.angle));
            double newy = turtleState.penY - (distance * Math.sin(turtleState.angle));

            if (!turtleState.penup) {
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2.draw(new Line2D.Double(turtleState.penX, turtleState.penY, newx, newy));
            }

            turtleState.penX = newx;
            turtleState.penY = newy;
        }

        @Override
        public void addListener(DrawListener listener) {
        }

        @Override
        public void removeListener(DrawListener listener) {
        }

        @Override
        public Drawable cloneDrawable() {
            return this;
        }
    };
    submitCommand(command);
}

From source file:org.tros.logo.swing.LogoPanel.java

@Override
public void setXY(final double x, final double y) {
    Drawable command = new Drawable() {

        @Override//from   w  w w  .  j a  v a2  s. co  m
        public void draw(Graphics2D g2, TurtleState turtleState) {
            double x2 = (turtleState.width > 0 ? turtleState.width : getWidth()) / 2.0 + x;
            double y2 = (turtleState.height > 0 ? turtleState.height : getHeight()) / 2.0 + y;

            if (!turtleState.penup) {
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2.draw(new Line2D.Double(turtleState.penX, turtleState.penY, x2, y2));
            }
            turtleState.penX = x2;
            turtleState.penY = y2;
        }

        @Override
        public void addListener(DrawListener listener) {
        }

        @Override
        public void removeListener(DrawListener listener) {
        }

        @Override
        public Drawable cloneDrawable() {
            return this;
        }
    };
    submitCommand(command);
}

From source file:org.kalypso.ogc.gml.map.MapPanel.java

/**
 * Paints contents of the map in the following order:
 * <ul>/* w w  w .  ja  v  a2s.  c o  m*/
 * <li>the buffered image containing the layers</li>
 * <li>the status, if not OK</li>
 * <li>all 'paint-listeners'</li>
 * <li>the current widget</li>
 * </ul>
 * 
 * @see java.awt.Component#paint(java.awt.Graphics)
 */
@Override
public void paint(final Graphics g) {
    final int width = getWidth();
    final int height = getHeight();
    if (height == 0 || width == 0)
        return;

    // only recreate buffered image if size has changed
    if (m_imageBuffer == null || m_imageBuffer.getWidth() != width || m_imageBuffer.getHeight() != height)
        m_imageBuffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    else
        // this seems to be enough for clearing the image here
        m_imageBuffer.flush();

    Graphics2D bufferGraphics = null;
    try {
        bufferGraphics = m_imageBuffer.createGraphics();
        bufferGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        bufferGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        final BufferPaintJob bufferPaintJob = m_bufferPaintJob; // get copy (for more thread safety)
        if (bufferPaintJob != null) {
            paintBufferedMap(bufferGraphics, bufferPaintJob);
        }

        // TODO: at the moment, we paint the status just on top of the map, if we change this component to SWT, we should
        // show the statusComposite in a title bar, if the status is non-OK (with details button for a stack trace)
        paintStatus(bufferGraphics);

        final IMapPanelPaintListener[] pls = m_paintListeners.toArray(new IMapPanelPaintListener[] {});
        for (final IMapPanelPaintListener pl : pls)
            pl.paint(bufferGraphics);

        paintWidget(bufferGraphics);
    } finally {
        if (bufferGraphics != null)
            bufferGraphics.dispose();
    }

    if (m_isMultitouchEnabled) {
        final IMapPanelMTPaintListener[] postls = m_postPaintListeners
                .toArray(new IMapPanelMTPaintListener[] {});
        for (final IMapPanelMTPaintListener pl : postls)
            pl.paint(m_imageBuffer);
    } else {
        g.drawImage(m_imageBuffer, 0, 0, null);
    }
}

From source file:au.org.ala.layers.web.UserDataService.java

@RequestMapping(value = WS_USERDATA_WMS, method = RequestMethod.GET)
public void getPointsMap(
        @RequestParam(value = "CQL_FILTER", required = false, defaultValue = "") String cql_filter,
        @RequestParam(value = "ENV", required = false, defaultValue = "") String env,
        @RequestParam(value = "BBOX", required = false, defaultValue = "") String bboxString,
        @RequestParam(value = "WIDTH", required = false, defaultValue = "") String widthString,
        @RequestParam(value = "HEIGHT", required = false, defaultValue = "") String heightString,
        HttpServletRequest request, HttpServletResponse response) {
    RecordsLookup.setUserDataDao(userDataDao);

    response.setHeader("Cache-Control", "max-age=86400"); //age == 1 day
    response.setContentType("image/png"); //only png images generated

    int width = 256, height = 256;
    try {/* www  . j  a  v  a2 s . c o  m*/
        width = Integer.parseInt(widthString);
        height = Integer.parseInt(heightString);
    } catch (Exception e) {
        logger.error("error parsing to int: " + widthString + " or " + heightString, e);
    }

    try {
        env = URLDecoder.decode(env, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        logger.error("error decoding env from UTF-8: " + env, e);
    }
    int red = 0, green = 0, blue = 0, alpha = 0;
    String name = "circle";
    int size = 4;
    boolean uncertainty = false;
    String highlight = null;
    String colourMode = null;
    for (String s : env.split(";")) {
        String[] pair = s.split(":");
        if (pair[0].equals("color")) {
            while (pair[1].length() < 6) {
                pair[1] = "0" + pair[1];
            }
            red = Integer.parseInt(pair[1].substring(0, 2), 16);
            green = Integer.parseInt(pair[1].substring(2, 4), 16);
            blue = Integer.parseInt(pair[1].substring(4), 16);
        } else if (pair[0].equals("name")) {
            name = pair[1];
        } else if (pair[0].equals("size")) {
            size = Integer.parseInt(pair[1]);
        } else if (pair[0].equals("opacity")) {
            alpha = (int) (255 * Double.parseDouble(pair[1]));
            //            } else if (pair[0].equals("uncertainty")) {
            //                uncertainty = true;
        } else if (pair[0].equals("sel")) {
            try {
                highlight = URLDecoder.decode(s.substring(4), "UTF-8").replace("%3B", ";");
            } catch (Exception e) {
            }
        } else if (pair[0].equals("colormode")) {
            colourMode = pair[1];
        }
    }

    double[] bbox = new double[4];
    int i;
    i = 0;
    for (String s : bboxString.split(",")) {
        try {
            bbox[i] = Double.parseDouble(s);
            i++;
        } catch (Exception e) {
            logger.error("error converting bounding box value to double: " + s, e);
        }
    }
    try {

        //adjust bbox extents with half pixel width/height
        double pixelWidth = (bbox[2] - bbox[0]) / width;
        double pixelHeight = (bbox[3] - bbox[1]) / height;
        bbox[0] += pixelWidth / 2;
        bbox[2] -= pixelWidth / 2;
        bbox[1] += pixelHeight / 2;
        bbox[3] -= pixelHeight / 2;

        //offset for points bounding box by size
        double xoffset = (bbox[2] - bbox[0]) / (double) width
                * (size + (highlight != null ? HIGHLIGHT_RADIUS * 2 + size * 0.2 : 0) + 5);
        double yoffset = (bbox[3] - bbox[1]) / (double) height
                * (size + (highlight != null ? HIGHLIGHT_RADIUS * 2 + size * 0.2 : 0) + 5);

        //check offset for points bb by maximum uncertainty (?? 30k ??)
        if (uncertainty) {
            double xuoffset = 30000;
            double yuoffset = 30000;
            if (xoffset < xuoffset) {
                xoffset = xuoffset;
            }
            if (yoffset < yuoffset) {
                yoffset = yuoffset;
            }
        }

        //adjust offset for pixel height/width
        xoffset += pixelWidth;
        yoffset += pixelHeight;

        double[][] bb = {
                { SpatialUtils.convertMetersToLng(bbox[0] - xoffset),
                        SpatialUtils.convertMetersToLat(bbox[1] - yoffset) },
                { SpatialUtils.convertMetersToLng(bbox[2] + xoffset),
                        SpatialUtils.convertMetersToLat(bbox[3] + yoffset) } };

        double[] pbbox = new double[4]; //pixel bounding box
        pbbox[0] = SpatialUtils.convertLngToPixel(SpatialUtils.convertMetersToLng(bbox[0]));
        pbbox[1] = SpatialUtils.convertLatToPixel(SpatialUtils.convertMetersToLat(bbox[1]));
        pbbox[2] = SpatialUtils.convertLngToPixel(SpatialUtils.convertMetersToLng(bbox[2]));
        pbbox[3] = SpatialUtils.convertLatToPixel(SpatialUtils.convertMetersToLat(bbox[3]));

        String lsid = null;
        int p1 = 0;
        int p2 = cql_filter.indexOf('&', p1 + 1);
        if (p2 < 0) {
            p2 = cql_filter.indexOf(';', p1 + 1);
        }
        if (p2 < 0) {
            p2 = cql_filter.length();
        }
        if (p1 >= 0) {
            lsid = cql_filter.substring(0, p2);
        }

        double[] points = null;
        ArrayList<QueryField> listHighlight = null;
        QueryField colours = null;
        double[] pointsBB = null;
        Facet facet = null;
        String[] facetFields = null;
        if (highlight != null && !(colourMode != null && colourMode.equals("grid"))) {
            facet = Facet.parseFacet(highlight);
            facetFields = facet.getFields();
            listHighlight = new ArrayList<QueryField>();
        }

        int[] idx = null;
        if (lsid != null) {
            Object[] data = (Object[]) RecordsLookup.getData(lsid);
            points = (double[]) data[1];
            pointsBB = (double[]) data[4];
            idx = (int[]) data[5];

            if (points == null || points.length == 0 || pointsBB[0] > bb[1][0] || pointsBB[2] < bb[0][0]
                    || pointsBB[1] > bb[1][1] || pointsBB[3] < bb[0][1]) {
                setImageBlank(response);
                return;
            }

            ArrayList<QueryField> fields = (ArrayList<QueryField>) data[2];

            for (int j = 0; j < fields.size(); j++) {
                if (facet != null) {
                    for (int k = 0; k < facetFields.length; k++) {
                        if (facetFields[k].equals(fields.get(j).getName())) {
                            listHighlight.add(fields.get(j));
                        }
                    }
                }
                if (colourMode != null) {
                    if (fields.get(j).getName().equals(colourMode)) {
                        synchronized (fields.get(j)) {
                            //need to resize 'colours' facet to the correct length and store as new QueryField
                            for (int k = 0; k < fields.size(); k++) {
                                if (fields.get(k).getName().equals(colourMode + " resized")) {
                                    colours = fields.get(k);
                                }
                            }

                            if (colours == null) {
                                colours = fields.get(j);

                                //does it need to be rebuilt to the correct length?
                                int count = colours.getIntData() != null ? colours.getIntData().length
                                        : colours.getLongData() != null ? colours.getLongData().length
                                                : colours.getFloatData() != null ? colours.getFloatData().length
                                                        : colours.getDoubleData() != null
                                                                ? colours.getDoubleData().length
                                                                : 0;
                                if (count != points.length / 2) {
                                    QueryField qf = new QueryField();
                                    qf.setDisplayName(colours.getDisplayName());
                                    qf.setName(colours.getName() + " resized");
                                    for (int k = 0; k < idx.length; k++) {
                                        qf.add(colours.getAsString(idx[k]));
                                    }
                                    qf.store();

                                    fields.add(qf);

                                    colours = qf;
                                }
                            }
                        }
                    }
                }
            }
        }

        /* TODO: make this a copy instead of create */
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = (Graphics2D) img.getGraphics();
        g.setColor(new Color(0, 0, 0, 0));
        g.fillRect(0, 0, width, height);

        g.setColor(new Color(red, green, blue, alpha));
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        int x, y;
        int pointWidth = size * 2 + 1;
        double width_mult = (width / (pbbox[2] - pbbox[0]));
        double height_mult = (height / (pbbox[1] - pbbox[3]));

        if (colourMode != null && colourMode.equals("grid")) {
            int divs = 16;
            double grid_width_mult = (width / (pbbox[2] - pbbox[0])) / (256 / divs);
            double grid_height_mult = (height / (pbbox[1] - pbbox[3])) / (256 / divs);
            int[][] gridCounts = new int[divs][divs];
            for (i = 0; i < points.length; i += 2) {
                x = (int) ((SpatialUtils.convertLngToPixel(points[i]) - pbbox[0]) * grid_width_mult);
                y = (int) ((SpatialUtils.convertLatToPixel(points[i + 1]) - pbbox[3]) * grid_height_mult);
                if (x >= 0 && x < divs && y >= 0 && y < divs) {
                    gridCounts[x][y]++;
                }
            }
            int xstep = 256 / divs;
            int ystep = 256 / divs;
            for (x = 0; x < divs; x++) {
                for (y = 0; y < divs; y++) {
                    int v = gridCounts[x][y];
                    if (v > 0) {
                        if (v > 500) {
                            v = 500;
                        }
                        int colour = Legend.getLinearColour(v, 0, 500, 0xFFFFFF00, 0xFFFF0000);
                        g.setColor(new Color(colour));
                        g.fillRect(x * xstep, y * ystep, xstep, ystep);
                    }
                }
            }
        } else {
            //circle type
            if (name.equals("circle")) {
                if (colours == null) {
                    for (i = 0; i < points.length; i += 2) {
                        if (points[i] >= bb[0][0] && points[i] <= bb[1][0] && points[i + 1] >= bb[0][1]
                                && points[i + 1] <= bb[1][1]) {
                            x = (int) ((SpatialUtils.convertLngToPixel(points[i]) - pbbox[0]) * width_mult);
                            y = (int) ((SpatialUtils.convertLatToPixel(points[i + 1]) - pbbox[3])
                                    * height_mult);
                            g.fillOval(x - size, y - size, pointWidth, pointWidth);
                        }
                    }
                } else {
                    int prevColour = -1; //!= colours[0]
                    g.setColor(new Color(prevColour));
                    for (i = 0; i < points.length; i += 2) {
                        if (points[i] >= bb[0][0] && points[i] <= bb[1][0] && points[i + 1] >= bb[0][1]
                                && points[i + 1] <= bb[1][1]) {
                            //colours is made the correct length, see above
                            int thisColour = colours.getColour(i / 2);
                            if (thisColour != prevColour) {
                                g.setColor(new Color(thisColour));
                                prevColour = thisColour;
                            }
                            x = (int) ((SpatialUtils.convertLngToPixel(points[i]) - pbbox[0]) * width_mult);
                            y = (int) ((SpatialUtils.convertLatToPixel(points[i + 1]) - pbbox[3])
                                    * height_mult);
                            g.fillOval(x - size, y - size, pointWidth, pointWidth);
                        }
                    }
                }
            }

            if (highlight != null && facet != null) {
                g.setStroke(new BasicStroke(2));
                g.setColor(new Color(255, 0, 0, 255));
                int sz = size + HIGHLIGHT_RADIUS;
                int w = sz * 2 + 1;

                for (i = 0; i < points.length; i += 2) {
                    if (points[i] >= bb[0][0] && points[i] <= bb[1][0] && points[i + 1] >= bb[0][1]
                            && points[i + 1] <= bb[1][1]) {

                        if (facet.isValid(listHighlight, idx[i / 2])) {
                            x = (int) ((SpatialUtils.convertLngToPixel(points[i]) - pbbox[0]) * width_mult);
                            y = (int) ((SpatialUtils.convertLatToPixel(points[i + 1]) - pbbox[3])
                                    * height_mult);
                            g.drawOval(x - sz, y - sz, w, w);
                        }
                    }
                }
            }
        }

        g.dispose();

        try {
            OutputStream os = response.getOutputStream();
            ImageIO.write(img, "png", os);
            os.flush();
            os.close();
        } catch (IOException e) {
            logger.error("error in outputting wms/reflect image as png", e);
        }
    } catch (Exception e) {
        logger.error("error generating wms/reflect tile", e);
    }

    //logger.debug("[wms tile: " + (System.currentTimeMillis() - start) + "ms]");
}