]> gerrit.simantics Code Review - simantics/district.git/blob - 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
1 /*******************************************************************************
2  * Copyright (c) 2012 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.maps.eclipse;
13
14 import java.awt.Image;
15 import java.awt.geom.Rectangle2D;
16 import java.awt.image.BufferedImage;
17 import java.awt.image.RenderedImage;
18 import java.io.File;
19 import java.io.IOException;
20 import java.net.URI;
21
22 import javax.imageio.ImageIO;
23
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;
30
31 /**
32  * @author Tuukka Lehtonen
33  */
34 public class DiskCachingTileProvider implements ITileProvider {
35
36     private final String CACHED_IMAGE_FORMAT = "png";
37
38     ITileProvider provider;
39
40     IPath         cachePath;
41
42     boolean supportAlpha;
43
44 //  private ImageWriter writer;
45 //
46 //    private ImageReader reader;
47 //
48 //    private ImageTypeSpecifier noAlphaType = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR);
49 //
50 //    private ImageTypeSpecifier alphaType = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR);
51
52
53     public DiskCachingTileProvider(ITileProvider provider, Boolean supportAlpha) {
54         this.provider = provider;
55         this.supportAlpha = supportAlpha;
56         initCache();
57     }
58
59     @Override
60     public URI getSource() {
61         return provider.getSource();
62     }
63
64     @Override
65     public Rectangle2D getExtent() {
66         return provider.getExtent();
67     }
68
69     private void initCache() {
70         Bundle b = Platform.getBundle("org.simantics.maps");
71         if (b == null)
72             return;
73         IPath statePath = Platform.getStateLocation(b);
74         URI source = provider.getSource();
75         IPath cache = statePath.append("cache").append(source.getScheme()).append(source.getHost());
76
77         // Create the cache directory if it doesn't exist.
78         File f = cache.toFile();
79         if (!f.exists()) {
80             f.mkdirs();
81         } else if (!f.isDirectory()) {
82 // FIXME
83 //            ErrorLogger.defaultLogError("Cache directory " + f.toString() + " already exists as a file, cannot use it for cache", new Exception());
84             return;
85         }
86
87         this.cachePath = cache;
88 //        System.out.println("MAP DATA CACHE: " + cachePath);
89         
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();
94     }
95
96     private IPath toTileCachePath(TileKey key) {
97         return cachePath.append(key.getLevel() + "." + key.getX() + "." + key.getY());
98     }
99
100     private Image lookupFromDisk(TileKey key) {
101         if (cachePath == null)
102             return null;
103
104         IPath cachePath = toTileCachePath(key).addFileExtension(CACHED_IMAGE_FORMAT);
105         File f = cachePath.toFile();
106         if (f.exists()) {
107 //            ImageInputStream iis = null;
108             try {
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);
115                 if (img != null) {
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)
121                         return img;
122
123                     BufferedImage img2 = null;
124                     if (img.getAlphaRaster() != null) {
125                         img2 = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
126                     } else {
127                         img2 = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
128                     }
129                     //System.out.println("[" + provider + "]     image2:  " + img2);
130
131                     img.copyData(img2.getRaster());
132                     return img2;
133                 }
134             } catch (IOException e) {
135                 e.printStackTrace();
136             } finally {
137 //                try {
138 //                    iis.close();
139 //                } catch (IOException e) {
140 //                }
141             }
142             // Data is most likely corrupted, just destroy it.
143             f.delete();
144         }
145 //        System.out.println("Disk cache miss: " + key);
146         return null;
147     }
148
149     private void cacheToDisk(TileKey key, Image img) {
150         if (cachePath == null)
151             return;
152
153         if (!(img instanceof RenderedImage))
154             return;
155
156         IPath cachePath = toTileCachePath(key).addFileExtension(CACHED_IMAGE_FORMAT);
157         File f = cachePath.toFile();
158         try {
159             if (ImageIO.write((RenderedImage) img, CACHED_IMAGE_FORMAT, f)) {
160                 //System.out.println("[" + provider + "] Disk cache write: " + key);
161             }
162         } catch (IOException e) {
163             // Caching failed, be silent about it.
164         }
165     }
166
167     @Override
168     public Image get(final TileKey key) throws ProvisionException {
169         Image img = lookupFromDisk(key);
170         if (img == null) {
171             img = provider.get(key);
172             final Image image = img;
173
174             // Write image to disk in the background
175             // TODO: use somekind of worker executor system instead of just threads.
176             new Thread() {
177                 @Override
178                 public void run() {
179                     cacheToDisk(key, image);
180                 }
181             }.start();
182         }
183         return img;
184     }
185
186     @Override
187     public String toString() {
188         return getClass().getSimpleName() + " [" + provider.toString() + "]";
189     }
190
191 }