List of usage examples for javax.imageio ImageReadParam getSourceXSubsampling
public int getSourceXSubsampling()
From source file:ch5ImageReader.java
/** * read in the input image specified by index imageIndex using the * parameters specified by the ImageReadParam object param */// ww w .j ava2 s .c o m public BufferedImage read(int imageIndex, ImageReadParam param) { checkIndex(imageIndex); if (isSeekForwardOnly()) minIndex = imageIndex; else minIndex = 0; BufferedImage bimage = null; WritableRaster raster = null; /* * this method sets the image metadata so that we can use the getWidth * and getHeight methods */ setImageMetadata(iis, imageIndex); int srcWidth = getWidth(imageIndex); int srcHeight = getHeight(imageIndex); // initialize values to -1 int dstWidth = -1; int dstHeight = -1; int srcRegionWidth = -1; int srcRegionHeight = -1; int srcRegionXOffset = -1; int srcRegionYOffset = -1; int xSubsamplingFactor = -1; int ySubsamplingFactor = -1; if (param == null) param = getDefaultReadParam(); Iterator imageTypes = getImageTypes(imageIndex); try { /* * get the destination BufferedImage which will be filled using the * input image's pixel data */ bimage = getDestination(param, imageTypes, srcWidth, srcHeight); /* * get Rectangle object which will be used to clip the source * image's dimensions. */ Rectangle srcRegion = param.getSourceRegion(); if (srcRegion != null) { srcRegionWidth = (int) srcRegion.getWidth(); srcRegionHeight = (int) srcRegion.getHeight(); srcRegionXOffset = (int) srcRegion.getX(); srcRegionYOffset = (int) srcRegion.getY(); /* * correct for overextended source regions */ if (srcRegionXOffset + srcRegionWidth > srcWidth) dstWidth = srcWidth - srcRegionXOffset; else dstWidth = srcRegionWidth; if (srcRegionYOffset + srcRegionHeight > srcHeight) dstHeight = srcHeight - srcRegionYOffset; else dstHeight = srcRegionHeight; } else { dstWidth = srcWidth; dstHeight = srcHeight; srcRegionXOffset = srcRegionYOffset = 0; } /* * get subsampling factors */ xSubsamplingFactor = param.getSourceXSubsampling(); ySubsamplingFactor = param.getSourceYSubsampling(); /** * dstWidth and dstHeight should be equal to bimage.getWidth() and * bimage.getHeight() after these next two instructions */ dstWidth = (dstWidth - 1) / xSubsamplingFactor + 1; dstHeight = (dstHeight - 1) / ySubsamplingFactor + 1; } catch (IIOException e) { System.err.println("Can't create destination BufferedImage"); } raster = bimage.getWritableTile(0, 0); /* * using the parameters specified by the ImageReadParam object, read the * image image data into the destination BufferedImage */ byte[] srcBuffer = new byte[srcWidth]; byte[] dstBuffer = new byte[dstWidth]; int jj; int index; try { for (int j = 0; j < srcHeight; j++) { iis.readFully(srcBuffer, 0, srcWidth); jj = j - srcRegionYOffset; if (jj % ySubsamplingFactor == 0) { jj /= ySubsamplingFactor; if ((jj >= 0) && (jj < dstHeight)) { for (int i = 0; i < dstWidth; i++) { index = srcRegionXOffset + i * xSubsamplingFactor; dstBuffer[i] = srcBuffer[index]; } raster.setDataElements(0, jj, dstWidth, 1, dstBuffer); } } } } catch (IOException e) { bimage = null; } return bimage; }
From source file:nitf.imageio.NITFReader.java
@Override public Raster readRaster(int imageIndex, ImageReadParam param) throws IOException { checkIndex(imageIndex);/* w w w.ja v a2 s . co m*/ Rectangle sourceRegion = new Rectangle(); Rectangle destRegion = new Rectangle(); computeRegions(param, getWidth(imageIndex), getHeight(imageIndex), null, sourceRegion, destRegion); // Set everything to default values int sourceXSubsampling = param != null ? param.getSourceXSubsampling() : 1; int sourceYSubsampling = param != null ? param.getSourceYSubsampling() : 1; Point destinationOffset = param != null ? param.getDestinationOffset() : new Point(0, 0); ImageSubheader subheader; try { subheader = record.getImages()[imageIndex].getSubheader(); } catch (NITFException e) { throw new IOException(ExceptionUtils.getStackTrace(e)); } String irep = subheader.getImageRepresentation().getStringData().trim(); String pvType = subheader.getPixelValueType().getStringData().trim(); int nbpp = subheader.getNumBitsPerPixel().getIntData(); int bandCount = subheader.getBandCount(); // make the band offsets array, for the output int[] bandOffsets = null; int[] sourceBands = param != null ? param.getSourceBands() : null; if (param != null && param.getDestinationBands() != null) bandOffsets = param.getDestinationBands(); else if (param != null && sourceBands != null) { bandOffsets = new int[sourceBands.length]; for (int i = 0; i < bandOffsets.length; i++) bandOffsets[i] = sourceBands[i]; } else { // Setup band offsets -- TODO should we really read ALL bands by // default? bandOffsets = new int[bandCount]; for (int i = 0; i < bandOffsets.length; i++) bandOffsets[i] = i; } int nBytes = ((nbpp - 1) / 8) + 1; int bufType = -1; // byte if (nBytes == 1) { bufType = DataBuffer.TYPE_BYTE; } // short else if (nBytes == 2) { bufType = DataBuffer.TYPE_USHORT; } // float else if (nBytes == 4 && pvType.equals("R")) { bufType = DataBuffer.TYPE_FLOAT; } // double else if (nBytes == 8 && pvType.equals("R")) { bufType = DataBuffer.TYPE_DOUBLE; } else { throw new NotImplementedException("not yet implemented"); } WritableRaster ras = ImageIOUtils.makeGenericPixelInterleavedWritableRaster(destRegion.width, destRegion.height, bandOffsets.length, bufType); checkReadParamBandSettings(param, bandCount, ras.getSampleModel().getNumBands()); readRaster(imageIndex, sourceRegion, destRegion, sourceXSubsampling, sourceYSubsampling, bandOffsets, nBytes, destinationOffset, ras); return ras; }
From source file:org.geotools.gce.imagemosaic.GranuleDescriptor.java
/** * Load a specified a raster as a portion of the granule describe by this {@link GranuleDescriptor}. * * @param imageReadParameters the {@link ImageReadParam} to use for reading. * @param index the index to use for the {@link ImageReader}. * @param cropBBox the bbox to use for cropping. * @param mosaicWorldToGrid the cropping grid to world transform. * @param request the incoming request to satisfy. * @param hints {@link Hints} to be used for creating this raster. * @return a specified a raster as a portion of the granule describe by this {@link GranuleDescriptor}. * @throws IOException in case an error occurs. *//*from w w w .ja va 2 s . c o m*/ public GranuleLoadingResult loadRaster(final ImageReadParam imageReadParameters, final int index, final ReferencedEnvelope cropBBox, final MathTransform2D mosaicWorldToGrid, final RasterLayerRequest request, final Hints hints) throws IOException { if (LOGGER.isLoggable(java.util.logging.Level.FINER)) { final String name = Thread.currentThread().getName(); LOGGER.finer("Thread:" + name + " Loading raster data for granuleDescriptor " + this.toString()); } ImageReadParam readParameters = null; int imageIndex; final boolean useFootprint = roiProvider != null && request.getFootprintBehavior() != FootprintBehavior.None; Geometry inclusionGeometry = useFootprint ? roiProvider.getFootprint() : null; final ReferencedEnvelope bbox = useFootprint ? new ReferencedEnvelope(granuleBBOX.intersection(inclusionGeometry.getEnvelopeInternal()), granuleBBOX.getCoordinateReferenceSystem()) : granuleBBOX; boolean doFiltering = false; if (filterMe && useFootprint) { doFiltering = Utils.areaIsDifferent(inclusionGeometry, baseGridToWorld, granuleBBOX); } // intersection of this tile bound with the current crop bbox final ReferencedEnvelope intersection = new ReferencedEnvelope(bbox.intersection(cropBBox), cropBBox.getCoordinateReferenceSystem()); if (intersection.isEmpty()) { if (LOGGER.isLoggable(java.util.logging.Level.FINE)) { LOGGER.fine(new StringBuilder("Got empty intersection for granule ").append(this.toString()) .append(" with request ").append(request.toString()) .append(" Resulting in no granule loaded: Empty result").toString()); } return null; } // check if the requested bbox intersects or overlaps the requested area if (useFootprint && inclusionGeometry != null && !JTS.toGeometry(cropBBox).intersects(inclusionGeometry)) { if (LOGGER.isLoggable(java.util.logging.Level.FINE)) { LOGGER.fine(new StringBuilder("Got empty intersection for granule ").append(this.toString()) .append(" with request ").append(request.toString()) .append(" Resulting in no granule loaded: Empty result").toString()); } return null; } ImageInputStream inStream = null; ImageReader reader = null; try { // //get info about the raster we have to read // // get a stream assert cachedStreamSPI != null : "no cachedStreamSPI available!"; inStream = cachedStreamSPI.createInputStreamInstance(granuleUrl, ImageIO.getUseCache(), ImageIO.getCacheDirectory()); if (inStream == null) return null; // get a reader and try to cache the relevant SPI if (cachedReaderSPI == null) { reader = ImageIOExt.getImageioReader(inStream); if (reader != null) cachedReaderSPI = reader.getOriginatingProvider(); } else reader = cachedReaderSPI.createReaderInstance(); if (reader == null) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.warning(new StringBuilder("Unable to get s reader for granuleDescriptor ") .append(this.toString()).append(" with request ").append(request.toString()) .append(" Resulting in no granule loaded: Empty result").toString()); } return null; } // set input customizeReaderInitialization(reader, hints); reader.setInput(inStream); // Checking for heterogeneous granules if (request.isHeterogeneousGranules()) { // create read parameters readParameters = new ImageReadParam(); //override the overviews controller for the base layer imageIndex = ReadParamsController.setReadParams( request.spatialRequestHelper.getRequestedResolution(), request.getOverviewPolicy(), request.getDecimationPolicy(), readParameters, request.rasterManager, overviewsController); } else { imageIndex = index; readParameters = imageReadParameters; } //get selected level and base level dimensions final GranuleOverviewLevelDescriptor selectedlevel = getLevel(imageIndex, reader); // now create the crop grid to world which can be used to decide // which source area we need to crop in the selected level taking // into account the scale factors imposed by the selection of this // level together with the base level grid to world transformation AffineTransform2D cropWorldToGrid = new AffineTransform2D(selectedlevel.gridToWorldTransformCorner); cropWorldToGrid = (AffineTransform2D) cropWorldToGrid.inverse(); // computing the crop source area which lives into the // selected level raster space, NOTICE that at the end we need to // take into account the fact that we might also decimate therefore // we cannot just use the crop grid to world but we need to correct // it. final Rectangle sourceArea = CRS.transform(cropWorldToGrid, intersection).toRectangle2D().getBounds(); //gutter if (selectedlevel.baseToLevelTransform.isIdentity()) { sourceArea.grow(2, 2); } XRectangle2D.intersect(sourceArea, selectedlevel.rasterDimensions, sourceArea);//make sure roundings don't bother us // is it empty?? if (sourceArea.isEmpty()) { if (LOGGER.isLoggable(java.util.logging.Level.FINE)) { LOGGER.fine("Got empty area for granuleDescriptor " + this.toString() + " with request " + request.toString() + " Resulting in no granule loaded: Empty result"); } return null; } else if (LOGGER.isLoggable(java.util.logging.Level.FINER)) { LOGGER.finer("Loading level " + imageIndex + " with source region: " + sourceArea + " subsampling: " + readParameters.getSourceXSubsampling() + "," + readParameters.getSourceYSubsampling() + " for granule:" + granuleUrl); } // Setting subsampling int newSubSamplingFactor = 0; final String pluginName = cachedReaderSPI.getPluginClassName(); if (pluginName != null && pluginName.equals(ImageUtilities.DIRECT_KAKADU_PLUGIN)) { final int ssx = readParameters.getSourceXSubsampling(); final int ssy = readParameters.getSourceYSubsampling(); newSubSamplingFactor = ImageIOUtilities.getSubSamplingFactor2(ssx, ssy); if (newSubSamplingFactor != 0) { if (newSubSamplingFactor > maxDecimationFactor && maxDecimationFactor != -1) { newSubSamplingFactor = maxDecimationFactor; } readParameters.setSourceSubsampling(newSubSamplingFactor, newSubSamplingFactor, 0, 0); } } // set the source region readParameters.setSourceRegion(sourceArea); RenderedImage raster; try { // read raster = request.getReadType().read(readParameters, imageIndex, granuleUrl, selectedlevel.rasterDimensions, reader, hints, false); } catch (Throwable e) { if (LOGGER.isLoggable(java.util.logging.Level.FINE)) { LOGGER.log(java.util.logging.Level.FINE, "Unable to load raster for granuleDescriptor " + this.toString() + " with request " + request.toString() + " Resulting in no granule loaded: Empty result", e); } return null; } // use fixed source area sourceArea.setRect(readParameters.getSourceRegion()); // // setting new coefficients to define a new affineTransformation // to be applied to the grid to world transformation // ----------------------------------------------------------------------------------- // // With respect to the original envelope, the obtained planarImage // needs to be rescaled. The scaling factors are computed as the // ratio between the cropped source region sizes and the read // image sizes. // // place it in the mosaic using the coords created above; double decimationScaleX = ((1.0 * sourceArea.width) / raster.getWidth()); double decimationScaleY = ((1.0 * sourceArea.height) / raster.getHeight()); final AffineTransform decimationScaleTranform = XAffineTransform.getScaleInstance(decimationScaleX, decimationScaleY); // keep into account translation to work into the selected level raster space final AffineTransform afterDecimationTranslateTranform = XAffineTransform .getTranslateInstance(sourceArea.x, sourceArea.y); // now we need to go back to the base level raster space final AffineTransform backToBaseLevelScaleTransform = selectedlevel.baseToLevelTransform; // now create the overall transform final AffineTransform finalRaster2Model = new AffineTransform(baseGridToWorld); finalRaster2Model.concatenate(CoverageUtilities.CENTER_TO_CORNER); if (!XAffineTransform.isIdentity(backToBaseLevelScaleTransform, Utils.AFFINE_IDENTITY_EPS)) finalRaster2Model.concatenate(backToBaseLevelScaleTransform); if (!XAffineTransform.isIdentity(afterDecimationTranslateTranform, Utils.AFFINE_IDENTITY_EPS)) finalRaster2Model.concatenate(afterDecimationTranslateTranform); if (!XAffineTransform.isIdentity(decimationScaleTranform, Utils.AFFINE_IDENTITY_EPS)) finalRaster2Model.concatenate(decimationScaleTranform); // adjust roi if (useFootprint) { ROIGeometry transformed; try { transformed = roiProvider.getTransformedROI(finalRaster2Model.createInverse()); if (transformed.getAsGeometry().isEmpty()) { // inset might have killed the geometry fully return null; } PlanarImage pi = PlanarImage.wrapRenderedImage(raster); if (!transformed.intersects(pi.getBounds())) { return null; } pi.setProperty("ROI", transformed); raster = pi; } catch (NoninvertibleTransformException e) { if (LOGGER.isLoggable(java.util.logging.Level.INFO)) LOGGER.info("Unable to create a granuleDescriptor " + this.toString() + " due to a problem when managing the ROI"); return null; } } // keep into account translation factors to place this tile finalRaster2Model.preConcatenate((AffineTransform) mosaicWorldToGrid); final Interpolation interpolation = request.getInterpolation(); //paranoiac check to avoid that JAI freaks out when computing its internal layouT on images that are too small Rectangle2D finalLayout = ImageUtilities.layoutHelper(raster, (float) finalRaster2Model.getScaleX(), (float) finalRaster2Model.getScaleY(), (float) finalRaster2Model.getTranslateX(), (float) finalRaster2Model.getTranslateY(), interpolation); if (finalLayout.isEmpty()) { if (LOGGER.isLoggable(java.util.logging.Level.INFO)) LOGGER.info("Unable to create a granuleDescriptor " + this.toString() + " due to jai scale bug creating a null source area"); return null; } // apply the affine transform conserving indexed color model final RenderingHints localHints = new RenderingHints(JAI.KEY_REPLACE_INDEX_COLOR_MODEL, interpolation instanceof InterpolationNearest ? Boolean.FALSE : Boolean.TRUE); if (XAffineTransform.isIdentity(finalRaster2Model, Utils.AFFINE_IDENTITY_EPS)) { return new GranuleLoadingResult(raster, null, granuleUrl, doFiltering, pamDataset); } else { // // In case we are asked to use certain tile dimensions we tile // also at this stage in case the read type is Direct since // buffered images comes up untiled and this can affect the // performances of the subsequent affine operation. // final Dimension tileDimensions = request.getTileDimensions(); if (tileDimensions != null && request.getReadType().equals(ReadType.DIRECT_READ)) { final ImageLayout layout = new ImageLayout(); layout.setTileHeight(tileDimensions.width).setTileWidth(tileDimensions.height); localHints.add(new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout)); } else { if (hints != null && hints.containsKey(JAI.KEY_IMAGE_LAYOUT)) { final Object layout = hints.get(JAI.KEY_IMAGE_LAYOUT); if (layout != null && layout instanceof ImageLayout) { localHints .add(new RenderingHints(JAI.KEY_IMAGE_LAYOUT, ((ImageLayout) layout).clone())); } } } if (hints != null && hints.containsKey(JAI.KEY_TILE_CACHE)) { final Object cache = hints.get(JAI.KEY_TILE_CACHE); if (cache != null && cache instanceof TileCache) localHints.add(new RenderingHints(JAI.KEY_TILE_CACHE, (TileCache) cache)); } if (hints != null && hints.containsKey(JAI.KEY_TILE_SCHEDULER)) { final Object scheduler = hints.get(JAI.KEY_TILE_SCHEDULER); if (scheduler != null && scheduler instanceof TileScheduler) localHints.add(new RenderingHints(JAI.KEY_TILE_SCHEDULER, (TileScheduler) scheduler)); } boolean addBorderExtender = true; if (hints != null && hints.containsKey(JAI.KEY_BORDER_EXTENDER)) { final Object extender = hints.get(JAI.KEY_BORDER_EXTENDER); if (extender != null && extender instanceof BorderExtender) { localHints.add(new RenderingHints(JAI.KEY_BORDER_EXTENDER, (BorderExtender) extender)); addBorderExtender = false; } } // BORDER extender if (addBorderExtender) { localHints.add(ImageUtilities.BORDER_EXTENDER_HINTS); } ImageWorker iw = new ImageWorker(raster); iw.setRenderingHints(localHints); iw.affine(finalRaster2Model, interpolation, request.getBackgroundValues()); return new GranuleLoadingResult(iw.getRenderedImage(), null, granuleUrl, doFiltering, pamDataset); } } catch (IllegalStateException e) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.log(java.util.logging.Level.WARNING, new StringBuilder("Unable to load raster for granuleDescriptor ").append(this.toString()) .append(" with request ").append(request.toString()) .append(" Resulting in no granule loaded: Empty result").toString(), e); } return null; } catch (org.opengis.referencing.operation.NoninvertibleTransformException e) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.log(java.util.logging.Level.WARNING, new StringBuilder("Unable to load raster for granuleDescriptor ").append(this.toString()) .append(" with request ").append(request.toString()) .append(" Resulting in no granule loaded: Empty result").toString(), e); } return null; } catch (TransformException e) { if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) { LOGGER.log(java.util.logging.Level.WARNING, new StringBuilder("Unable to load raster for granuleDescriptor ").append(this.toString()) .append(" with request ").append(request.toString()) .append(" Resulting in no granule loaded: Empty result").toString(), e); } return null; } finally { try { if (request.getReadType() != ReadType.JAI_IMAGEREAD && inStream != null) { inStream.close(); } } finally { if (request.getReadType() != ReadType.JAI_IMAGEREAD && reader != null) { reader.dispose(); } } } }
From source file:org.geotools.gce.imagemosaic.OverviewsControllerTest.java
/** * Tests the {@link OverviewsController} with support for different * resolutions/different number of overviews. * /*from w w w .j a v a 2s . co m*/ * world_a.tif => Pixel Size = (0.833333333333333,-0.833333333333333); 4 overviews * world_b.tif => Pixel Size = (1.406250000000000,-1.406250000000000); 2 overviews * * @throws IOException * @throws MismatchedDimensionException * @throws FactoryException * @throws TransformException */ @Test public void testHeterogeneousGranules() throws IOException, MismatchedDimensionException, FactoryException, TransformException { // // // // Initialize mosaic variables // // // final AbstractGridFormat format = getFormat(heterogeneousGranulesURL); final ImageMosaicReader reader = getReader(heterogeneousGranulesURL, format); final int nOv = reader.getNumberOfOvervies(); final double[] hRes = reader.getHighestRes(); final RasterManager rasterManager = new RasterManager(reader); // // // // Initialize granules related variables // // // final File g1File = new File(DataUtilities.urlToFile(heterogeneousGranulesURL), "world_a.tif"); final File g2File = new File(DataUtilities.urlToFile(heterogeneousGranulesURL), "world_b.tif"); final ImageReadParam readParamsG1 = new ImageReadParam(); final ImageReadParam readParamsG2 = new ImageReadParam(); int imageIndexG1 = 0; int imageIndexG2 = 0; final GranuleDescriptor granuleDescriptor1 = new GranuleDescriptor(g1File.getAbsolutePath(), TEST_BBOX_A, spi, (Geometry) null, true); final GranuleDescriptor granuleDescriptor2 = new GranuleDescriptor(g2File.getAbsolutePath(), TEST_BBOX_B, spi, (Geometry) null, true); assertNotNull(granuleDescriptor1.toString()); assertNotNull(granuleDescriptor2.toString()); final OverviewsController ovControllerG1 = granuleDescriptor1.overviewsController; final OverviewsController ovControllerG2 = granuleDescriptor2.overviewsController; // // // // Initializing read request // // // final GeneralEnvelope envelope = reader.getOriginalEnvelope(); final GridEnvelope originalRange = reader.getOriginalGridRange(); final Rectangle rasterArea = new Rectangle(0, 0, (int) Math.ceil(originalRange.getSpan(0) / 9.0), (int) Math.ceil(originalRange.getSpan(1) / 9.0)); final GridEnvelope2D range = new GridEnvelope2D(rasterArea); final GridToEnvelopeMapper geMapper = new GridToEnvelopeMapper(range, envelope); geMapper.setPixelAnchor(PixelInCell.CELL_CENTER); final AffineTransform gridToWorld = geMapper.createAffineTransform(); final double requestedResolution[] = new double[] { XAffineTransform.getScaleX0(gridToWorld), XAffineTransform.getScaleY0(gridToWorld) }; TestSet at = null; if (nOv == 4 && Math.abs(hRes[0] - 0.833333333333) <= THRESHOLD) { at = at1; } else if (nOv == 2 && Math.abs(hRes[0] - 1.40625) <= THRESHOLD) { at = at2; } else { return; } // // // // Starting OverviewsController tests // // // final OverviewPolicy[] ovPolicies = new OverviewPolicy[] { OverviewPolicy.QUALITY, OverviewPolicy.SPEED, OverviewPolicy.NEAREST, OverviewPolicy.IGNORE }; for (int i = 0; i < ovPolicies.length; i++) { OverviewPolicy ovPolicy = ovPolicies[i]; LOGGER.info("Testing with OverviewPolicy = " + ovPolicy.toString()); imageIndexG1 = ReadParamsController.setReadParams(requestedResolution, ovPolicy, DecimationPolicy.ALLOW, readParamsG1, rasterManager, ovControllerG1); imageIndexG2 = ReadParamsController.setReadParams(requestedResolution, ovPolicy, DecimationPolicy.ALLOW, readParamsG2, rasterManager, ovControllerG2); assertSame(at.ot[i].g1.imageIndex, imageIndexG1); assertSame(at.ot[i].g2.imageIndex, imageIndexG2); assertSame(at.ot[i].g1.ssx, readParamsG1.getSourceXSubsampling()); assertSame(at.ot[i].g1.ssy, readParamsG1.getSourceYSubsampling()); assertSame(at.ot[i].g2.ssx, readParamsG2.getSourceXSubsampling()); assertSame(at.ot[i].g2.ssy, readParamsG2.getSourceYSubsampling()); } }
From source file:org.geotools.imageio.netcdf.NetCDFImageReader.java
/** * @see javax.imageio.ImageReader#read(int, javax.imageio.ImageReadParam) *//*from w w w . j ava2s . co m*/ @Override public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException { clearAbortRequest(); final Slice2DIndex slice2DIndex = getSlice2DIndex(imageIndex); final String variableName = slice2DIndex.getVariableName(); final VariableAdapter wrapper = getCoverageDescriptor(new NameImpl(variableName)); /* * Fetches the parameters that are not already processed by utility * methods like 'getDestination' or 'computeRegions' (invoked below). */ final int strideX, strideY; // final int[] srcBands; final int[] dstBands; if (param != null) { strideX = param.getSourceXSubsampling(); strideY = param.getSourceYSubsampling(); // srcBands = param.getSourceBands(); dstBands = param.getDestinationBands(); } else { strideX = 1; strideY = 1; // srcBands = null; dstBands = null; } /* * Gets the destination image of appropriate size. We create it now * since it is a convenient way to get the number of destination bands. */ final int width = wrapper.getWidth(); final int height = wrapper.getHeight(); /* * Computes the source region (in the NetCDF file) and the destination * region (in the buffered image). Copies those informations into UCAR * Range structure. */ final Rectangle srcRegion = new Rectangle(); final Rectangle destRegion = new Rectangle(); computeRegions(param, width, height, null, srcRegion, destRegion); // Flipping is needed only when the input latitude coordinate is ordered // from min to max if (needsFlipping) { flipVertically(param, height, srcRegion); } int destWidth = destRegion.x + destRegion.width; int destHeight = destRegion.y + destRegion.height; /* * build the ranges that need to be read from each * dimension based on the source region */ final List<Range> ranges = new LinkedList<Range>(); try { // add the ranges the COARDS way: T, Z, Y, X // T int first = slice2DIndex.getTIndex(); int length = 1; int stride = 1; if (first != -1) { ranges.add(new Range(first, first + length - 1, stride)); } // Z first = slice2DIndex.getZIndex(); if (first != -1) { ranges.add(new Range(first, first + length - 1, stride)); } // Y first = srcRegion.y; length = srcRegion.height; stride = strideY; ranges.add(new Range(first, first + length - 1, stride)); // X first = srcRegion.x; length = srcRegion.width; stride = strideX; ranges.add(new Range(first, first + length - 1, stride)); } catch (InvalidRangeException e) { throw netcdfFailure(e); } /* * create the section of multidimensional array indices * that defines the exact data that need to be read * for this image index and parameters */ final Section section = new Section(ranges); /* * Setting SampleModel and ColorModel. */ final SampleModel sampleModel = wrapper.getSampleModel().createCompatibleSampleModel(destWidth, destHeight); final ColorModel colorModel = ImageIOUtilities.createColorModel(sampleModel); final WritableRaster raster = Raster.createWritableRaster(sampleModel, new Point(0, 0)); final BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null); CoordinateAxis axis = wrapper.variableDS.getCoordinateSystems().get(0).getLatAxis(); boolean flipYAxis = false; try { Array yAxisStart = axis.read(new Section().appendRange(2)); float y1 = yAxisStart.getFloat(0); float y2 = yAxisStart.getFloat(1); if (y2 > y1) { flipYAxis = true; } } catch (InvalidRangeException e) { throw new RuntimeException(e); } /* * Reads the requested sub-region only. */ processImageStarted(imageIndex); final int numDstBands = 1; final float toPercent = 100f / numDstBands; final int type = raster.getSampleModel().getDataType(); final int xmin = destRegion.x; final int ymin = destRegion.y; final int xmax = destRegion.width + xmin; final int ymax = destRegion.height + ymin; for (int zi = 0; zi < numDstBands; zi++) { // final int srcBand = (srcBands == null) ? zi : srcBands[zi]; final int dstBand = (dstBands == null) ? zi : dstBands[zi]; final Array array; try { // TODO leak through array = wrapper.variableDS.read(section); } catch (InvalidRangeException e) { throw netcdfFailure(e); } if (flipYAxis) { final IndexIterator it = array.getIndexIterator(); for (int y = ymax; --y >= ymin;) { for (int x = xmin; x < xmax; x++) { switch (type) { case DataBuffer.TYPE_DOUBLE: { raster.setSample(x, y, dstBand, it.getDoubleNext()); break; } case DataBuffer.TYPE_FLOAT: { raster.setSample(x, y, dstBand, it.getFloatNext()); break; } case DataBuffer.TYPE_BYTE: { byte b = it.getByteNext(); // int myByte = (0x000000FF & ((int) b)); // short anUnsignedByte = (short) myByte; // raster.setSample(x, y, dstBand, anUnsignedByte); raster.setSample(x, y, dstBand, b); break; } default: { raster.setSample(x, y, dstBand, it.getIntNext()); break; } } } } } else { switch (type) { case DataBuffer.TYPE_DOUBLE: { DoubleBuffer doubleBuffer = array.getDataAsByteBuffer().asDoubleBuffer(); double[] samples = new double[destRegion.width * destRegion.height]; doubleBuffer.get(samples); raster.setSamples(xmin, ymin, destRegion.width, destRegion.height, dstBand, samples); break; } case DataBuffer.TYPE_FLOAT: float[] samples = new float[destRegion.width * destRegion.height]; FloatBuffer floatBuffer = array.getDataAsByteBuffer().asFloatBuffer(); floatBuffer.get(samples); raster.setSamples(xmin, ymin, destRegion.width, destRegion.height, dstBand, samples); break; case DataBuffer.TYPE_BYTE: //THIS ONLY WORKS FOR ONE BAND!! raster.setDataElements(xmin, ymin, destRegion.width, destRegion.height, array.getDataAsByteBuffer().array()); break; case DataBuffer.TYPE_INT: IntBuffer intBuffer = array.getDataAsByteBuffer().asIntBuffer(); int[] intSamples = new int[destRegion.width * destRegion.height]; intBuffer.get(intSamples); raster.setSamples(xmin, ymin, destRegion.width, destRegion.height, dstBand, intSamples); break; default: { final IndexIterator it = array.getIndexIterator(); for (int y = ymin; y < ymax; y++) { for (int x = xmin; x < xmax; x++) { raster.setSample(x, y, dstBand, it.getIntNext()); } } break; } } } /* * Checks for abort requests after reading. It would be a waste of a * potentially good image (maybe the abort request occurred after we * just finished the reading) if we didn't implemented the * 'isCancel()' method. But because of the later, which is checked * by the NetCDF library, we can't assume that the image is * complete. */ if (abortRequested()) { processReadAborted(); return image; } /* * Reports progress here, not in the deeper loop, because the costly * part is the call to 'variable.read(...)' which can't report * progress. The loop that copy pixel values is fast, so reporting * progress there would be pointless. */ processImageProgress(zi * toPercent); } processImageComplete(); return image; }
From source file:org.geotools.imageio.unidata.UnidataImageReader.java
/** * @see javax.imageio.ImageReader#read(int, javax.imageio.ImageReadParam) *//*from w ww . j av a 2 s . co m*/ @Override public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException { clearAbortRequest(); final UnidataSlice2DIndex slice2DIndex = getSlice2DIndex(imageIndex); final String variableName = slice2DIndex.getVariableName(); final UnidataVariableAdapter wrapper = getCoverageDescriptor(new NameImpl(variableName)); /* * Fetches the parameters that are not already processed by utility * methods like 'getDestination' or 'computeRegions' (invoked below). */ final int strideX, strideY; // final int[] srcBands; final int[] dstBands; if (param != null) { strideX = param.getSourceXSubsampling(); strideY = param.getSourceYSubsampling(); // srcBands = param.getSourceBands(); dstBands = param.getDestinationBands(); } else { strideX = 1; strideY = 1; // srcBands = null; dstBands = null; } /* * Gets the destination image of appropriate size. We create it now * since it is a convenient way to get the number of destination bands. */ final int width = wrapper.getWidth(); final int height = wrapper.getHeight(); /* * Computes the source region (in the NetCDF file) and the destination * region (in the buffered image). Copies those informations into UCAR * Range structure. */ final Rectangle srcRegion = new Rectangle(); final Rectangle destRegion = new Rectangle(); computeRegions(param, width, height, null, srcRegion, destRegion); flipVertically(param, height, srcRegion); int destWidth = destRegion.x + destRegion.width; int destHeight = destRegion.y + destRegion.height; /* * build the ranges that need to be read from each * dimension based on the source region */ final List<Range> ranges = new LinkedList<Range>(); try { // add the ranges the COARDS way: T, Z, Y, X // T int first = slice2DIndex.getTIndex(); int length = 1; int stride = 1; if (first != -1) { ranges.add(new Range(first, first + length - 1, stride)); } // Z first = slice2DIndex.getZIndex(); if (first != -1) { ranges.add(new Range(first, first + length - 1, stride)); } // Y first = srcRegion.y; length = srcRegion.height; stride = strideY; ranges.add(new Range(first, first + length - 1, stride)); // X first = srcRegion.x; length = srcRegion.width; stride = strideX; ranges.add(new Range(first, first + length - 1, stride)); } catch (InvalidRangeException e) { throw netcdfFailure(e); } /* * create the section of multidimensional array indices * that defines the exact data that need to be read * for this image index and parameters */ final Section section = new Section(ranges); /* * Setting SampleModel and ColorModel. */ final SampleModel sampleModel = wrapper.getSampleModel().createCompatibleSampleModel(destWidth, destHeight); final ColorModel colorModel = ImageIOUtilities.createColorModel(sampleModel); final WritableRaster raster = Raster.createWritableRaster(sampleModel, new Point(0, 0)); final BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null); CoordinateAxis axis = wrapper.variableDS.getCoordinateSystems().get(0).getLatAxis(); boolean flipYAxis = false; try { Array yAxisStart = axis.read(new Section().appendRange(2)); float y1 = yAxisStart.getFloat(0); float y2 = yAxisStart.getFloat(1); if (y2 > y1) { flipYAxis = true; } } catch (InvalidRangeException e) { throw new RuntimeException(e); } /* * Reads the requested sub-region only. */ processImageStarted(imageIndex); final int numDstBands = 1; final float toPercent = 100f / numDstBands; final int type = raster.getSampleModel().getDataType(); final int xmin = destRegion.x; final int ymin = destRegion.y; final int xmax = destRegion.width + xmin; final int ymax = destRegion.height + ymin; for (int zi = 0; zi < numDstBands; zi++) { // final int srcBand = (srcBands == null) ? zi : srcBands[zi]; final int dstBand = (dstBands == null) ? zi : dstBands[zi]; final Array array; try { // TODO leak through array = wrapper.variableDS.read(section); } catch (InvalidRangeException e) { throw netcdfFailure(e); } if (flipYAxis) { final IndexIterator it = array.getIndexIterator(); for (int y = ymax; --y >= ymin;) { for (int x = xmin; x < xmax; x++) { switch (type) { case DataBuffer.TYPE_DOUBLE: { raster.setSample(x, y, dstBand, it.getDoubleNext()); break; } case DataBuffer.TYPE_FLOAT: { raster.setSample(x, y, dstBand, it.getFloatNext()); break; } case DataBuffer.TYPE_BYTE: { byte b = it.getByteNext(); // int myByte = (0x000000FF & ((int) b)); // short anUnsignedByte = (short) myByte; // raster.setSample(x, y, dstBand, anUnsignedByte); raster.setSample(x, y, dstBand, b); break; } default: { raster.setSample(x, y, dstBand, it.getIntNext()); break; } } } } } else { switch (type) { case DataBuffer.TYPE_DOUBLE: { DoubleBuffer doubleBuffer = array.getDataAsByteBuffer().asDoubleBuffer(); double[] samples = new double[destRegion.width * destRegion.height]; doubleBuffer.get(samples); raster.setSamples(xmin, ymin, destRegion.width, destRegion.height, dstBand, samples); break; } case DataBuffer.TYPE_FLOAT: float[] samples = new float[destRegion.width * destRegion.height]; FloatBuffer floatBuffer = array.getDataAsByteBuffer().asFloatBuffer(); floatBuffer.get(samples); raster.setSamples(xmin, ymin, destRegion.width, destRegion.height, dstBand, samples); break; case DataBuffer.TYPE_BYTE: //THIS ONLY WORKS FOR ONE BAND!! raster.setDataElements(xmin, ymin, destRegion.width, destRegion.height, array.getDataAsByteBuffer().array()); break; case DataBuffer.TYPE_INT: IntBuffer intBuffer = array.getDataAsByteBuffer().asIntBuffer(); int[] intSamples = new int[destRegion.width * destRegion.height]; intBuffer.get(intSamples); raster.setSamples(xmin, ymin, destRegion.width, destRegion.height, dstBand, intSamples); break; default: { final IndexIterator it = array.getIndexIterator(); for (int y = ymin; y < ymax; y++) { for (int x = xmin; x < xmax; x++) { raster.setSample(x, y, dstBand, it.getIntNext()); } } break; } } } /* * Checks for abort requests after reading. It would be a waste of a * potentially good image (maybe the abort request occurred after we * just finished the reading) if we didn't implemented the * 'isCancel()' method. But because of the later, which is checked * by the NetCDF library, we can't assume that the image is * complete. */ if (abortRequested()) { processReadAborted(); return image; } /* * Reports progress here, not in the deeper loop, because the costly * part is the call to 'variable.read(...)' which can't report * progress. The loop that copy pixel values is fast, so reporting * progress there would be pointless. */ processImageProgress(zi * toPercent); } processImageComplete(); return image; }