/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package com.bc.ceres.jai.tilecache; import javax.imageio.stream.FileImageInputStream; import javax.imageio.stream.FileImageOutputStream; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStream; import java.awt.Point; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferDouble; import java.awt.image.DataBufferFloat; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferShort; import java.awt.image.Raster; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; final class SwappedTile { private final File file; private final long fileSize; private final SampleModel sampleModel; private final boolean writable; private final Point location; private final Object tileCacheMetric; SwappedTile(MemoryTile mt, File cacheDir) { this.file = new File(cacheDir, mt.getKeyAsString()); this.fileSize = mt.getTileSize(); this.sampleModel = mt.getTile().getSampleModel(); this.location = (Point) mt.getTile().getBounds().getLocation().clone(); this.writable = mt.getTile() instanceof WritableRaster; this.tileCacheMetric = mt.getTileCacheMetric(); } public boolean isAvailable() { return file.length() == fileSize; } public File getFile() { return file; } public SampleModel getSampleModel() { return sampleModel; } public boolean isWritable() { return writable; } public Point getLocation() { return location; } public Object getTileCacheMetric() { return tileCacheMetric; } public boolean delete() { return file.delete(); } public Raster restoreTile() throws IOException { final ImageInputStream stream = new FileImageInputStream(file); final DataBuffer dataBuffer; try { dataBuffer = readTileData(stream, sampleModel); } finally { stream.close(); } final Raster tile; if (writable) { tile = Raster.createWritableRaster(sampleModel, dataBuffer, location); } else { tile = Raster.createRaster(sampleModel, dataBuffer, location); } return tile; } public void storeTile(Raster tile) throws IOException { final ImageOutputStream stream = new FileImageOutputStream(file); try { writeTileData(stream, tile.getDataBuffer()); } finally { stream.close(); } } private static DataBuffer readTileData(ImageInputStream stream, SampleModel sampleModel) throws IOException { final int dataType = sampleModel.getDataType(); final int arrayLength = stream.readInt(); final int bufferSize = stream.readInt(); final int bufferOffset = stream.readInt(); if (dataType == DataBuffer.TYPE_BYTE) { byte[] data = new byte[arrayLength]; stream.readFully(data, 0, arrayLength); return new DataBufferByte(data, bufferSize, bufferOffset); } else if (dataType == DataBuffer.TYPE_SHORT || dataType == DataBuffer.TYPE_USHORT) { short[] data = new short[arrayLength]; stream.readFully(data, 0, arrayLength); return new DataBufferShort(data, bufferSize, bufferOffset); } else if (dataType == DataBuffer.TYPE_INT) { int[] data = new int[arrayLength]; stream.readFully(data, 0, arrayLength); return new DataBufferInt(data, bufferSize, bufferOffset); } else if (dataType == DataBuffer.TYPE_FLOAT) { float[] data = new float[arrayLength]; stream.readFully(data, 0, arrayLength); return new DataBufferFloat(data, bufferSize, bufferOffset); } else if (dataType == DataBuffer.TYPE_DOUBLE) { double[] data = new double[arrayLength]; stream.readFully(data, 0, arrayLength); return new DataBufferDouble(data, bufferSize, bufferOffset); } else { throw new IllegalStateException(); } } private static void writeTileData(ImageOutputStream stream, DataBuffer dataBuffer) throws IOException { final Object data; try { final Method method = dataBuffer.getClass().getMethod("getData"); data = method.invoke(dataBuffer); } catch (Exception e) { throw new IllegalArgumentException("illegal dataBuffer: " + dataBuffer.getClass(), e); } if (data instanceof byte[]) { final byte[] array = (byte[]) data; stream.writeInt(array.length); stream.writeInt(dataBuffer.getSize()); stream.writeInt(dataBuffer.getOffset()); stream.write(array, dataBuffer.getOffset(), dataBuffer.getSize()); } else if (data instanceof short[]) { final short[] array = (short[]) data; stream.writeInt(array.length); stream.writeInt(dataBuffer.getSize()); stream.writeInt(dataBuffer.getOffset()); stream.writeShorts(array, dataBuffer.getOffset(), dataBuffer.getSize()); } else if (data instanceof int[]) { final int[] array = (int[]) data; stream.writeInt(array.length); stream.writeInt(dataBuffer.getSize()); stream.writeInt(dataBuffer.getOffset()); stream.writeInts(array, dataBuffer.getOffset(), dataBuffer.getSize()); } else if (data instanceof float[]) { final float[] array = (float[]) data; stream.writeInt(array.length); stream.writeInt(dataBuffer.getSize()); stream.writeInt(dataBuffer.getOffset()); stream.writeFloats(array, dataBuffer.getOffset(), dataBuffer.getSize()); } else if (data instanceof double[]) { final double[] array = (double[]) data; stream.writeInt(array.length); stream.writeInt(dataBuffer.getSize()); stream.writeInt(dataBuffer.getOffset()); stream.writeDoubles(array, dataBuffer.getOffset(), dataBuffer.getSize()); } else { throw new IllegalArgumentException("illegal dataBuffer: " + dataBuffer.getClass()); } } }