protected void drawPointLegend( VPFSymbolAttributes attr, Graphics2D g2, int width, int height, int margin) { if (attr.getIconImageSource() == null) return; BufferedImage icon = getImage(attr.getIconImageSource()); if (icon != null) { // icon width / height int iw = icon.getWidth(); int ih = icon.getHeight(); // draw area width / height int dw = width - margin * 2; int dh = height - margin * 2; // draw scale to fit icon inside draw area float sx = iw > dw ? (float) dw / iw : 1f; // shrink only float sy = ih > dh ? (float) dh / ih : 1f; float scale = Math.min(sx, sy); iw = (int) ((float) iw * scale); ih = (int) ((float) ih * scale); // Center image and draw int x1 = iw < dw ? margin + (dw - iw) / 2 : margin; int y1 = ih < dh ? margin + (dh - ih) / 2 : margin; g2.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2.drawImage(icon, x1, y1, iw, ih, null); } }
@SuppressWarnings({"UnusedDeclaration"}) protected Paint getFillPaint(VPFSymbolAttributes attr, int width, int height) { if (attr.getImageSource() == null) return attr.getInteriorMaterial().getDiffuse(); // int patternSize = Math.min(width, height); // fit one pattern tiles BufferedImage pattern = getImage(attr.getImageSource()); if (pattern != null) return new TexturePaint( pattern, new Rectangle(0, 0, pattern.getWidth(), pattern.getHeight())); return attr.getInteriorMaterial().getDiffuse(); }
public BufferedImage createLegendImage( VPFSymbolAttributes attr, int width, int height, int margin) { BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); Graphics2D g2 = image.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); switch (attr.getFeatureType()) { case POINT: this.drawPointLegend(attr, g2, width, height, margin); break; case LINE: this.drawLineLegend(attr, g2, width, height, margin); break; case AREA: this.drawAreaLegend(attr, g2, width, height, margin); break; } return image; }
private void makeNoDataTransparent( BufferedImage image, short missingDataSignal, short missingDataReplacement) { WritableRaster raster = null; if (null != image && (image.getType() == BufferedImage.TYPE_4BYTE_ABGR || image.getType() == BufferedImage.TYPE_INT_ARGB) && null != (raster = image.getRaster())) { int nodata_r = missingDataSignal & 0xff; int nodata_g = missingDataSignal & 0xff; int nodata_b = missingDataSignal & 0xff; int[] pixel = new int[4]; int[] transparentPixel = new int[] { 0xFF & missingDataReplacement /* red */, 0xFF & missingDataReplacement /* green */, 0xFF & missingDataReplacement, 0x00 /* alpha */ }; int width = image.getWidth(); int height = image.getHeight(); for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { // We know, by the nature of this source, that we are dealing with RGBA rasters... raster.getPixel(i, j, pixel); if (pixel[0] == nodata_r && pixel[1] == nodata_g && pixel[2] == nodata_b) { // pixel[0] = pixel[1] = pixel[2] = 0xFF & // missingDataReplacement; // pixel[3] = 0; // transparent raster.setPixel(i, j, transparentPixel); } else { pixel[3] = 0xff; // non-transparent raster.setPixel(i, j, pixel); } } } } }
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 BufferedImage composeImageForSector( Sector sector, int imageWidth, int imageHeight, int levelNumber, String mimeType, boolean abortOnError, BufferedImage image) { if (sector == null) { String message = Logging.getMessage("nullValue.SectorIsNull"); Logging.logger().severe(message); throw new IllegalStateException(message); } if (levelNumber < 0) { levelNumber = this.levels.getLastLevel().getLevelNumber(); } else if (levelNumber > this.levels.getLastLevel().getLevelNumber()) { Logging.logger() .warning( Logging.getMessage( "generic.LevelRequestedGreaterThanMaxLevel", levelNumber, this.levels.getLastLevel().getLevelNumber())); levelNumber = this.levels.getLastLevel().getLevelNumber(); } MercatorTextureTile[][] tiles = this.getTilesInSector(sector, levelNumber); if (tiles.length == 0 || tiles[0].length == 0) { Logging.logger().severe(Logging.getMessage("layers.TiledImageLayer.NoImagesAvailable")); return null; } if (image == null) image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); Graphics2D g = image.createGraphics(); for (MercatorTextureTile[] row : tiles) { for (MercatorTextureTile tile : row) { if (tile == null) continue; BufferedImage tileImage; try { tileImage = this.getImage(tile, mimeType); double sh = ((double) imageHeight / (double) tileImage.getHeight()) * (tile.getSector().getDeltaLat().divide(sector.getDeltaLat())); double sw = ((double) imageWidth / (double) tileImage.getWidth()) * (tile.getSector().getDeltaLon().divide(sector.getDeltaLon())); double dh = imageHeight * (-tile.getSector().getMaxLatitude().subtract(sector.getMaxLatitude()).degrees / sector.getDeltaLat().degrees); double dw = imageWidth * (tile.getSector().getMinLongitude().subtract(sector.getMinLongitude()).degrees / sector.getDeltaLon().degrees); AffineTransform txf = g.getTransform(); g.translate(dw, dh); g.scale(sw, sh); g.drawImage(tileImage, 0, 0, null); g.setTransform(txf); } catch (Exception e) { if (abortOnError) throw new RuntimeException(e); String message = Logging.getMessage("generic.ExceptionWhileRequestingImage", tile.getPath()); Logging.logger().log(java.util.logging.Level.WARNING, message, e); } } } return image; }
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); }
private void writeGrayscaleImage(BufferedImage image, AVList params) throws IOException { int type = image.getType(); int bitsPerSample = (BufferedImage.TYPE_USHORT_GRAY == type) ? Tiff.BitsPerSample.MONOCHROME_UINT16 : Tiff.BitsPerSample.MONOCHROME_UINT8; int numBands = image.getSampleModel().getNumBands(); // well, numBands for GrayScale images must be 1 int bytesPerSample = numBands * bitsPerSample / Byte.SIZE; this.writeTiffHeader(); // write the image data... int numRows = image.getHeight(); int numCols = image.getWidth(); int[] stripCounts = new int[numRows]; int[] stripOffsets = new int[numRows]; ByteBuffer dataBuff = ByteBuffer.allocateDirect(numCols * bytesPerSample); Raster rast = image.getRaster(); for (int i = 0; i < numRows; i++) { stripOffsets[i] = (int) this.theChannel.position(); stripCounts[i] = numCols * bytesPerSample; int[] rowData = rast.getPixels(0, i, image.getWidth(), 1, (int[]) null); dataBuff.clear(); if (BufferedImage.TYPE_USHORT_GRAY == type) { for (int j = 0; j < numCols * numBands; j++) { this.putUnsignedShort(dataBuff, rowData[j]); } } else if (BufferedImage.TYPE_BYTE_GRAY == type) { for (int j = 0; j < numCols * numBands; j++) { this.putUnsignedByte(dataBuff, rowData[j]); } } dataBuff.flip(); this.theChannel.write(dataBuff); } // write out values for the tiff tags and build up the IFD. These are supposed to be sorted; for // now // do this manually here. ArrayList<TiffIFDEntry> ifds = new ArrayList<TiffIFDEntry>(10); ifds.add(new TiffIFDEntry(Tiff.Tag.IMAGE_WIDTH, Tiff.Type.LONG, 1, numCols)); ifds.add(new TiffIFDEntry(Tiff.Tag.IMAGE_LENGTH, Tiff.Type.LONG, 1, numRows)); ifds.add(new TiffIFDEntry(Tiff.Tag.BITS_PER_SAMPLE, Tiff.Type.SHORT, 1, bitsPerSample)); ifds.add(new TiffIFDEntry(Tiff.Tag.COMPRESSION, Tiff.Type.LONG, 1, Tiff.Compression.NONE)); ifds.add( new TiffIFDEntry( Tiff.Tag.PHOTO_INTERPRETATION, Tiff.Type.SHORT, 1, Tiff.Photometric.Grayscale_BlackIsZero)); ifds.add( new TiffIFDEntry(Tiff.Tag.SAMPLE_FORMAT, Tiff.Type.SHORT, 1, Tiff.SampleFormat.UNSIGNED)); long offset = this.theChannel.position(); dataBuff = ByteBuffer.allocateDirect(stripOffsets.length * INTEGER_SIZEOF); for (int stripOffset : stripOffsets) { dataBuff.putInt(stripOffset); } dataBuff.flip(); this.theChannel.write(dataBuff); ifds.add(new TiffIFDEntry(Tiff.Tag.STRIP_OFFSETS, Tiff.Type.LONG, stripOffsets.length, offset)); ifds.add(new TiffIFDEntry(Tiff.Tag.SAMPLES_PER_PIXEL, Tiff.Type.SHORT, 1, numBands)); ifds.add(new TiffIFDEntry(Tiff.Tag.ROWS_PER_STRIP, Tiff.Type.LONG, 1, 1)); offset = this.theChannel.position(); dataBuff.clear(); // stripOffsets and stripCounts are same length by design; can reuse the // ByteBuffer... for (int stripCount : stripCounts) { dataBuff.putInt(stripCount); } dataBuff.flip(); this.theChannel.write(dataBuff); ifds.add( new TiffIFDEntry(Tiff.Tag.STRIP_BYTE_COUNTS, Tiff.Type.LONG, stripCounts.length, offset)); this.appendGeoTiff(ifds, params); this.writeIFDs(ifds); }
private void writeColorImage(BufferedImage image, AVList params) throws IOException { int numBands = image.getRaster().getNumBands(); long offset; this.writeTiffHeader(); // write the image data... int numRows = image.getHeight(); int numCols = image.getWidth(); int[] stripCounts = new int[numRows]; int[] stripOffsets = new int[numRows]; ByteBuffer dataBuff = ByteBuffer.allocateDirect(numCols * numBands); Raster rast = image.getRaster(); for (int i = 0; i < numRows; i++) { stripOffsets[i] = (int) this.theChannel.position(); stripCounts[i] = numCols * numBands; int[] rowData = rast.getPixels(0, i, image.getWidth(), 1, (int[]) null); dataBuff.clear(); for (int j = 0; j < numCols * numBands; j++) { putUnsignedByte(dataBuff, rowData[j]); } dataBuff.flip(); this.theChannel.write(dataBuff); } // write out values for the tiff tags and build up the IFD. These are supposed to be sorted; for // now // do this manually here. ArrayList<TiffIFDEntry> ifds = new ArrayList<TiffIFDEntry>(10); ifds.add(new TiffIFDEntry(Tiff.Tag.IMAGE_WIDTH, Tiff.Type.LONG, 1, numCols)); ifds.add(new TiffIFDEntry(Tiff.Tag.IMAGE_LENGTH, Tiff.Type.LONG, 1, numRows)); ifds.add( new TiffIFDEntry( Tiff.Tag.PLANAR_CONFIGURATION, Tiff.Type.SHORT, 1, Tiff.PlanarConfiguration.CHUNKY)); ifds.add(new TiffIFDEntry(Tiff.Tag.SAMPLES_PER_PIXEL, Tiff.Type.SHORT, 1, numBands)); ifds.add(new TiffIFDEntry(Tiff.Tag.COMPRESSION, Tiff.Type.LONG, 1, Tiff.Compression.NONE)); ifds.add( new TiffIFDEntry( Tiff.Tag.PHOTO_INTERPRETATION, Tiff.Type.SHORT, 1, Tiff.Photometric.Color_RGB)); ifds.add(new TiffIFDEntry(Tiff.Tag.ORIENTATION, Tiff.Type.SHORT, 1, Tiff.Orientation.DEFAULT)); offset = this.theChannel.position(); short[] bps = new short[numBands]; for (int i = 0; i < numBands; i++) { bps[i] = Tiff.BitsPerSample.MONOCHROME_BYTE; } this.theChannel.write(ByteBuffer.wrap(this.getBytes(bps))); ifds.add(new TiffIFDEntry(Tiff.Tag.BITS_PER_SAMPLE, Tiff.Type.SHORT, numBands, offset)); offset = this.theChannel.position(); dataBuff = ByteBuffer.allocateDirect(stripOffsets.length * INTEGER_SIZEOF); for (int stripOffset : stripOffsets) { dataBuff.putInt(stripOffset); } dataBuff.flip(); this.theChannel.write(dataBuff); ifds.add(new TiffIFDEntry(Tiff.Tag.STRIP_OFFSETS, Tiff.Type.LONG, stripOffsets.length, offset)); ifds.add(new TiffIFDEntry(Tiff.Tag.ROWS_PER_STRIP, Tiff.Type.LONG, 1, 1)); offset = this.theChannel.position(); dataBuff.clear(); // stripOffsets and stripCounts are same length by design; can reuse the ByteBuffer... for (int stripCount : stripCounts) { dataBuff.putInt(stripCount); } dataBuff.flip(); this.theChannel.write(dataBuff); ifds.add( new TiffIFDEntry(Tiff.Tag.STRIP_BYTE_COUNTS, Tiff.Type.LONG, stripCounts.length, offset)); this.appendGeoTiff(ifds, params); this.writeIFDs(ifds); }
public void write(BufferedImage image, AVList params) throws IOException { if (image == null) { String msg = Logging.getMessage("nullValue.ImageSource"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } if (0 == image.getWidth() || 0 == image.getHeight()) { String msg = Logging.getMessage("generic.InvalidImageSize", image.getWidth(), image.getHeight()); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } if (null == params || 0 == params.getValues().size()) { String reason = Logging.getMessage("nullValue.AVListIsNull"); Logging.logger().finest(Logging.getMessage("GeotiffWriter.GeoKeysMissing", reason)); params = new AVListImpl(); } else { this.validateParameters(params, image.getWidth(), image.getHeight()); } // how we proceed in part depends upon the image type... int type = image.getType(); // handle CUSTOM type which comes from our GeoTiffreader (for now) if (BufferedImage.TYPE_CUSTOM == type) { int numColorComponents = 0, numComponents = 0, pixelSize = 0, dataType = 0, csType = 0; boolean hasAlpha = false; if (null != image.getColorModel()) { ColorModel cm = image.getColorModel(); numColorComponents = cm.getNumColorComponents(); numComponents = cm.getNumComponents(); pixelSize = cm.getPixelSize(); hasAlpha = cm.hasAlpha(); ColorSpace cs = cm.getColorSpace(); if (null != cs) csType = cs.getType(); } if (null != image.getSampleModel()) { SampleModel sm = image.getSampleModel(); dataType = sm.getDataType(); } if (dataType == DataBuffer.TYPE_FLOAT && pixelSize == Float.SIZE && numComponents == 1) { type = BufferedImage_TYPE_ELEVATION_FLOAT32; } else if (dataType == DataBuffer.TYPE_SHORT && pixelSize == Short.SIZE && numComponents == 1) { type = BufferedImage_TYPE_ELEVATION_SHORT16; } else if (ColorSpace.CS_GRAY == csType && pixelSize == Byte.SIZE) { type = BufferedImage.TYPE_BYTE_GRAY; } else if (dataType == DataBuffer.TYPE_USHORT && ColorSpace.CS_GRAY == csType && pixelSize == Short.SIZE) { type = BufferedImage.TYPE_USHORT_GRAY; } else if (ColorSpace.TYPE_RGB == csType && pixelSize == 3 * Byte.SIZE && numColorComponents == 3) { type = BufferedImage.TYPE_3BYTE_BGR; } else if (ColorSpace.TYPE_RGB == csType && hasAlpha && pixelSize == 4 * Byte.SIZE && numComponents == 4) { type = BufferedImage.TYPE_4BYTE_ABGR; } } switch (type) { case BufferedImage.TYPE_3BYTE_BGR: case BufferedImage.TYPE_4BYTE_ABGR: case BufferedImage.TYPE_4BYTE_ABGR_PRE: case BufferedImage.TYPE_INT_RGB: case BufferedImage.TYPE_INT_BGR: case BufferedImage.TYPE_INT_ARGB: case BufferedImage.TYPE_INT_ARGB_PRE: { this.writeColorImage(image, params); } break; case BufferedImage.TYPE_USHORT_GRAY: case BufferedImage.TYPE_BYTE_GRAY: { this.writeGrayscaleImage(image, params); } break; case BufferedImage_TYPE_ELEVATION_SHORT16: case BufferedImage_TYPE_ELEVATION_FLOAT32: { String msg = Logging.getMessage("GeotiffWriter.FeatureNotImplementedd", type); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } // break; case BufferedImage.TYPE_CUSTOM: default: { ColorModel cm = image.getColorModel(); SampleModel sm = image.getSampleModel(); StringBuffer sb = new StringBuffer(Logging.getMessage("GeotiffWriter.UnsupportedType", type)); sb.append("\n"); sb.append("NumBands=").append(sm.getNumBands()).append("\n"); sb.append("NumDataElements=").append(sm.getNumDataElements()).append("\n"); sb.append("NumColorComponents=").append(cm.getNumColorComponents()).append("\n"); sb.append("NumComponents=").append(cm.getNumComponents()).append("\n"); sb.append("PixelSize=").append(cm.getPixelSize()).append("\n"); sb.append("hasAlpha=").append(cm.hasAlpha()); String msg = sb.toString(); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } } }