]> gerrit.simantics Code Review - simantics/district.git/blobdiff - org.simantics.district.maps/src/org/simantics/maps/eclipse/DiskCachingTileProvider.java
Share some projects for Simantics District
[simantics/district.git] / org.simantics.district.maps / src / org / simantics / maps / eclipse / DiskCachingTileProvider.java
diff --git a/org.simantics.district.maps/src/org/simantics/maps/eclipse/DiskCachingTileProvider.java b/org.simantics.district.maps/src/org/simantics/maps/eclipse/DiskCachingTileProvider.java
new file mode 100644 (file)
index 0000000..2bef3ee
--- /dev/null
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.maps.eclipse;
+
+import java.awt.Image;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.RenderedImage;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+
+import javax.imageio.ImageIO;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+import org.simantics.maps.ProvisionException;
+import org.simantics.maps.tile.ITileProvider;
+import org.simantics.maps.tile.TileKey;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class DiskCachingTileProvider implements ITileProvider {
+
+    private final String CACHED_IMAGE_FORMAT = "png";
+
+    ITileProvider provider;
+
+    IPath         cachePath;
+
+    boolean supportAlpha;
+
+//  private ImageWriter writer;
+//
+//    private ImageReader reader;
+//
+//    private ImageTypeSpecifier noAlphaType = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR);
+//
+//    private ImageTypeSpecifier alphaType = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR);
+
+
+    public DiskCachingTileProvider(ITileProvider provider, Boolean supportAlpha) {
+        this.provider = provider;
+        this.supportAlpha = supportAlpha;
+        initCache();
+    }
+
+    @Override
+    public URI getSource() {
+        return provider.getSource();
+    }
+
+    @Override
+    public Rectangle2D getExtent() {
+        return provider.getExtent();
+    }
+
+    private void initCache() {
+        Bundle b = Platform.getBundle("org.simantics.maps");
+        if (b == null)
+            return;
+        IPath statePath = Platform.getStateLocation(b);
+        URI source = provider.getSource();
+        IPath cache = statePath.append("cache").append(source.getScheme()).append(source.getHost());
+
+        // Create the cache directory if it doesn't exist.
+        File f = cache.toFile();
+        if (!f.exists()) {
+            f.mkdirs();
+        } else if (!f.isDirectory()) {
+// FIXME
+//            ErrorLogger.defaultLogError("Cache directory " + f.toString() + " already exists as a file, cannot use it for cache", new Exception());
+            return;
+        }
+
+        this.cachePath = cache;
+//        System.out.println("MAP DATA CACHE: " + cachePath);
+        
+//        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(CACHED_IMAGE_FORMAT);
+//        writer = writers.next();
+//        Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(CACHED_IMAGE_FORMAT);
+//        reader = readers.next();
+    }
+
+    private IPath toTileCachePath(TileKey key) {
+        return cachePath.append(key.getLevel() + "." + key.getX() + "." + key.getY());
+    }
+
+    private Image lookupFromDisk(TileKey key) {
+        if (cachePath == null)
+            return null;
+
+        IPath cachePath = toTileCachePath(key).addFileExtension(CACHED_IMAGE_FORMAT);
+        File f = cachePath.toFile();
+        if (f.exists()) {
+//            ImageInputStream iis = null;
+            try {
+//                iis = ImageIO.createImageInputStream(f);
+//                ImageReadParam param = reader.getDefaultReadParam();
+//                param.setDestinationType(supportAlpha ? alphaType : noAlphaType);
+//                reader.setInput(iis, true, true);
+//                BufferedImage img = reader.read(0, param);
+                BufferedImage img = ImageIO.read(f);
+                if (img != null) {
+                    //System.out.println("[" + provider + "] Disk cache hit: " + key);
+                    //System.out.println("[" + provider + "]     image:   " + img);
+                    // Need to make sure that the type of the loaded image is
+                    // something that can be rendered in an accelerated fashion.
+                    if (img.getType() != BufferedImage.TYPE_CUSTOM)
+                        return img;
+
+                    BufferedImage img2 = null;
+                    if (img.getAlphaRaster() != null) {
+                        img2 = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
+                    } else {
+                        img2 = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
+                    }
+                    //System.out.println("[" + provider + "]     image2:  " + img2);
+
+                    img.copyData(img2.getRaster());
+                    return img2;
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+//                try {
+//                    iis.close();
+//                } catch (IOException e) {
+//                }
+            }
+            // Data is most likely corrupted, just destroy it.
+            f.delete();
+        }
+//        System.out.println("Disk cache miss: " + key);
+        return null;
+    }
+
+    private void cacheToDisk(TileKey key, Image img) {
+        if (cachePath == null)
+            return;
+
+        if (!(img instanceof RenderedImage))
+            return;
+
+        IPath cachePath = toTileCachePath(key).addFileExtension(CACHED_IMAGE_FORMAT);
+        File f = cachePath.toFile();
+        try {
+            if (ImageIO.write((RenderedImage) img, CACHED_IMAGE_FORMAT, f)) {
+                //System.out.println("[" + provider + "] Disk cache write: " + key);
+            }
+        } catch (IOException e) {
+            // Caching failed, be silent about it.
+        }
+    }
+
+    @Override
+    public Image get(final TileKey key) throws ProvisionException {
+        Image img = lookupFromDisk(key);
+        if (img == null) {
+            img = provider.get(key);
+            final Image image = img;
+
+            // Write image to disk in the background
+            // TODO: use somekind of worker executor system instead of just threads.
+            new Thread() {
+                @Override
+                public void run() {
+                    cacheToDisk(key, image);
+                }
+            }.start();
+        }
+        return img;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + " [" + provider.toString() + "]";
+    }
+
+}