1 /*******************************************************************************
2 * Copyright (c) 2012 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.maps.eclipse;
14 import java.awt.Image;
15 import java.awt.geom.Rectangle2D;
16 import java.awt.image.BufferedImage;
17 import java.awt.image.RenderedImage;
19 import java.io.IOException;
22 import javax.imageio.ImageIO;
24 import org.eclipse.core.runtime.IPath;
25 import org.eclipse.core.runtime.Platform;
26 import org.osgi.framework.Bundle;
27 import org.simantics.maps.ProvisionException;
28 import org.simantics.maps.tile.ITileProvider;
29 import org.simantics.maps.tile.TileKey;
32 * @author Tuukka Lehtonen
34 public class DiskCachingTileProvider implements ITileProvider {
36 private final String CACHED_IMAGE_FORMAT = "png";
38 ITileProvider provider;
44 // private ImageWriter writer;
46 // private ImageReader reader;
48 // private ImageTypeSpecifier noAlphaType = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR);
50 // private ImageTypeSpecifier alphaType = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR);
53 public DiskCachingTileProvider(ITileProvider provider, Boolean supportAlpha) {
54 this.provider = provider;
55 this.supportAlpha = supportAlpha;
60 public URI getSource() {
61 return provider.getSource();
65 public Rectangle2D getExtent() {
66 return provider.getExtent();
69 private void initCache() {
70 Bundle b = Platform.getBundle("org.simantics.maps");
73 IPath statePath = Platform.getStateLocation(b);
74 URI source = provider.getSource();
75 IPath cache = statePath.append("cache").append(source.getScheme()).append(source.getHost());
77 // Create the cache directory if it doesn't exist.
78 File f = cache.toFile();
81 } else if (!f.isDirectory()) {
83 // ErrorLogger.defaultLogError("Cache directory " + f.toString() + " already exists as a file, cannot use it for cache", new Exception());
87 this.cachePath = cache;
88 // System.out.println("MAP DATA CACHE: " + cachePath);
90 // Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(CACHED_IMAGE_FORMAT);
91 // writer = writers.next();
92 // Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(CACHED_IMAGE_FORMAT);
93 // reader = readers.next();
96 private IPath toTileCachePath(TileKey key) {
97 return cachePath.append(key.getLevel() + "." + key.getX() + "." + key.getY());
100 private Image lookupFromDisk(TileKey key) {
101 if (cachePath == null)
104 IPath cachePath = toTileCachePath(key).addFileExtension(CACHED_IMAGE_FORMAT);
105 File f = cachePath.toFile();
107 // ImageInputStream iis = null;
109 // iis = ImageIO.createImageInputStream(f);
110 // ImageReadParam param = reader.getDefaultReadParam();
111 // param.setDestinationType(supportAlpha ? alphaType : noAlphaType);
112 // reader.setInput(iis, true, true);
113 // BufferedImage img = reader.read(0, param);
114 BufferedImage img = ImageIO.read(f);
116 //System.out.println("[" + provider + "] Disk cache hit: " + key);
117 //System.out.println("[" + provider + "] image: " + img);
118 // Need to make sure that the type of the loaded image is
119 // something that can be rendered in an accelerated fashion.
120 if (img.getType() != BufferedImage.TYPE_CUSTOM)
123 BufferedImage img2 = null;
124 if (img.getAlphaRaster() != null) {
125 img2 = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
127 img2 = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
129 //System.out.println("[" + provider + "] image2: " + img2);
131 img.copyData(img2.getRaster());
134 } catch (IOException e) {
139 // } catch (IOException e) {
142 // Data is most likely corrupted, just destroy it.
145 // System.out.println("Disk cache miss: " + key);
149 private void cacheToDisk(TileKey key, Image img) {
150 if (cachePath == null)
153 if (!(img instanceof RenderedImage))
156 IPath cachePath = toTileCachePath(key).addFileExtension(CACHED_IMAGE_FORMAT);
157 File f = cachePath.toFile();
159 if (ImageIO.write((RenderedImage) img, CACHED_IMAGE_FORMAT, f)) {
160 //System.out.println("[" + provider + "] Disk cache write: " + key);
162 } catch (IOException e) {
163 // Caching failed, be silent about it.
168 public Image get(final TileKey key) throws ProvisionException {
169 Image img = lookupFromDisk(key);
171 img = provider.get(key);
172 final Image image = img;
174 // Write image to disk in the background
175 // TODO: use somekind of worker executor system instead of just threads.
179 cacheToDisk(key, image);
187 public String toString() {
188 return getClass().getSimpleName() + " [" + provider.toString() + "]";