]> gerrit.simantics Code Review - simantics/district.git/commitdiff
Ensure ITileProviders return BufferedImages with compatible ColorModel 92/2292/1
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Wed, 10 Oct 2018 10:23:29 +0000 (13:23 +0300)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Wed, 10 Oct 2018 10:52:00 +0000 (10:52 +0000)
gitlab #12

Change-Id: Ic47ae73cfdf6d71efdf7099fd67b1e674425682c
(cherry picked from commit d3de128e6d55f9f6a1325985695b925a1056c469)

org.simantics.district.maps/.classpath
org.simantics.district.maps/META-INF/MANIFEST.MF
org.simantics.district.maps/src/org/simantics/maps/debug/DebugTileProvider.java
org.simantics.district.maps/src/org/simantics/maps/eclipse/DiskCachingTileProvider.java
org.simantics.district.maps/src/org/simantics/maps/internal/ImageUtil.java [new file with mode: 0644]
org.simantics.district.maps/src/org/simantics/maps/osm/OSMTileProvider.java
org.simantics.district.maps/src/org/simantics/maps/sg/MapNode.java
org.simantics.district.maps/src/org/simantics/maps/tile/CompoundTileProvider.java
org.simantics.district.maps/src/org/simantics/maps/tile/Shp2ImgTileProvider.java
org.simantics.district.maps/src/org/simantics/maps/wms/WMSTileProvider.java

index 751c8f2e504c40d1c41ebbd87d8f8968529e9c30..eca7bdba8f03f22510b7980a94dbfe10c16c0901 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
        <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="src" path="src"/>
        <classpathentry kind="output" path="bin"/>
 </classpath>
index 0ea8a6e610264c8de650096861833783b4d20be5..7a2b4fc0c1adc602d6954a4685076c621d7f3ac2 100644 (file)
@@ -12,7 +12,8 @@ Require-Bundle: org.simantics.scenegraph,
  org.eclipse.jface,
  org.eclipse.ui.ide,
  org.eclipse.ui.workbench,
- org.simantics.district.geotools;bundle-version="1.0.0"
+ org.simantics.district.geotools;bundle-version="1.0.0",
+ org.slf4j.api;bundle-version="1.7.25"
 Export-Package: org.simantics.maps,
  org.simantics.maps.debug,
  org.simantics.maps.eclipse,
@@ -20,5 +21,4 @@ Export-Package: org.simantics.maps,
  org.simantics.maps.tile,
  org.simantics.maps.wms
 Import-Package: org.simantics.scenegraph.g2d
-Bundle-RequiredExecutionEnvironment: JavaSE-1.6,
- JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
index bb868ffd43c44c5e257a207a9fd9ba7385c5df9b..1aa50f1d260b305f43dbc9891bc5855a3888511c 100644 (file)
@@ -17,12 +17,14 @@ import java.awt.FontMetrics;
 import java.awt.Graphics2D;
 import java.awt.Image;
 import java.awt.RenderingHints;
+import java.awt.Transparency;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
 import java.net.URI;
 import java.net.URISyntaxException;
 
 import org.simantics.maps.ProvisionException;
+import org.simantics.maps.internal.ImageUtil;
 import org.simantics.maps.tile.ITileProvider;
 import org.simantics.maps.tile.TileKey;
 
@@ -93,13 +95,13 @@ public class DebugTileProvider implements ITileProvider {
         );
 //        System.out.println(yTiles + ", " + key.y + " => " + r);
 
-        BufferedImage image = new BufferedImage(tileSize, tileSize, BufferedImage.TYPE_3BYTE_BGR);
+        BufferedImage image = ImageUtil.createScreenCompatibleImage(tileSize, tileSize, Transparency.OPAQUE);
         Graphics2D g = image.createGraphics();
         try {
             g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
             g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
 
-            g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 32));
+            g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 16));
 
             g.setColor(Color.BLACK);
             g.fillRect(0, 0, tileSize, tileSize);
index 2bef3eebffb6e87f0b86ebc5826647dc071774cf..418b1285171ded5657a1d1e32fdfd85aa9aea493 100644 (file)
@@ -18,6 +18,7 @@ import java.awt.image.RenderedImage;
 import java.io.File;
 import java.io.IOException;
 import java.net.URI;
+import java.util.concurrent.ForkJoinPool;
 
 import javax.imageio.ImageIO;
 
@@ -25,14 +26,19 @@ 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.internal.ImageUtil;
 import org.simantics.maps.tile.ITileProvider;
 import org.simantics.maps.tile.TileKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * @author Tuukka Lehtonen
  */
 public class DiskCachingTileProvider implements ITileProvider {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(DiskCachingTileProvider.class);
+
     private final String CACHED_IMAGE_FORMAT = "png";
 
     ITileProvider provider;
@@ -41,15 +47,6 @@ public class DiskCachingTileProvider implements ITileProvider {
 
     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;
@@ -79,8 +76,7 @@ public class DiskCachingTileProvider implements ITileProvider {
         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());
+            LOGGER.error("Tile cache directory " + f.toString() + " already exists as a file, cannot use it as a cache directory", new Exception());
             return;
         }
 
@@ -104,40 +100,18 @@ public class DiskCachingTileProvider implements ITileProvider {
         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;
+                    return ImageUtil.toScreenCompatibleImage(img);
                 }
             } catch (IOException e) {
-                e.printStackTrace();
+                LOGGER.warn("Failed to load cached tile from {}", f.toString(), e);
             } finally {
-//                try {
-//                    iis.close();
-//                } catch (IOException e) {
-//                }
             }
             // Data is most likely corrupted, just destroy it.
             f.delete();
@@ -165,20 +139,15 @@ public class DiskCachingTileProvider implements ITileProvider {
     }
 
     @Override
-    public Image get(final TileKey key) throws ProvisionException {
+    public Image get(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();
+            if (cachePath != null) {
+                // Write image to disk in the background
+                ForkJoinPool.commonPool().submit(() -> cacheToDisk(key, image));
+            }
         }
         return img;
     }
diff --git a/org.simantics.district.maps/src/org/simantics/maps/internal/ImageUtil.java b/org.simantics.district.maps/src/org/simantics/maps/internal/ImageUtil.java
new file mode 100644 (file)
index 0000000..162097b
--- /dev/null
@@ -0,0 +1,58 @@
+package org.simantics.maps.internal;
+
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.image.BufferedImage;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.35.0
+ */
+public class ImageUtil {
+
+       public static BufferedImage createScreenCompatibleImage(int width, int height, int transparency) {
+               return createCompatibleImage(
+                               GraphicsEnvironment
+                               .getLocalGraphicsEnvironment()
+                               .getDefaultScreenDevice()
+                               .getDefaultConfiguration(),
+                               width, height, transparency);
+       }
+
+       public static BufferedImage createCompatibleImage(GraphicsConfiguration conf, int width, int height, int transparency) {
+               return conf.createCompatibleImage(width, height, transparency);
+       }
+
+       public static BufferedImage toScreenCompatibleImage(BufferedImage img) {
+               return toCompatibleImage(
+                               GraphicsEnvironment
+                               .getLocalGraphicsEnvironment()
+                               .getDefaultScreenDevice()
+                               .getDefaultConfiguration(),
+                               img);
+       }
+
+       public static BufferedImage toCompatibleImage(GraphicsConfiguration conf, BufferedImage img) {
+               // TODO: add checks to prevent new image creation if the provided image is already compatible with the given GraphicsConfiguration
+               if (img.getColorModel().equals(conf.getColorModel()))
+                       return img;
+
+//             BufferedImage result = null;
+//             if (img.getAlphaRaster() != null) {
+//                     result = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
+//             } else {
+//                     result = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
+//             }
+
+               BufferedImage result = createCompatibleImage(conf, img.getWidth(), img.getHeight(), img.getTransparency());
+               Graphics2D g = result.createGraphics();
+               try {
+                       g.drawImage(img, 0, 0, null);
+                       return result;
+               } finally {
+                       g.dispose();
+               }
+       }
+
+}
index 2b29d20fcf84994c6403adc131a2df04743558b9..a428a2df5162f373c27112bb40ec8fa1565f34bf 100644 (file)
@@ -26,6 +26,7 @@ import javax.imageio.ImageIO;
 
 import org.simantics.maps.ProvisionException;
 import org.simantics.maps.WebService;
+import org.simantics.maps.internal.ImageUtil;
 import org.simantics.maps.tile.ITileProvider;
 import org.simantics.maps.tile.TileKey;
 import org.simantics.maps.wms.ServiceException;
@@ -136,7 +137,7 @@ public class OSMTileProvider implements ITileProvider {
                     if (img == null) {
                         throw new IIOException("ImageIO returned null, unable to decode stream as image data.");
                     }
-                    return img;
+                    return ImageUtil.toScreenCompatibleImage(img);
                 }
             }
 
index 84338bfbc62bb4523612cd75aae93e6a4bb47ef8..952553b0ec4cb263d75d9d2bd07524cc738f225a 100644 (file)
@@ -25,8 +25,6 @@ import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.ImageObserver;
 import java.awt.image.VolatileImage;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -50,6 +48,8 @@ import org.simantics.maps.tile.TileCache;
 import org.simantics.maps.tile.TileKey;
 import org.simantics.scenegraph.g2d.G2DNode;
 import org.simantics.scenegraph.g2d.G2DRenderingHints;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * @author Tuukka Lehtonen
@@ -58,6 +58,8 @@ public class MapNode extends G2DNode implements ITileListener  {
 
     private static final long serialVersionUID = 2490944880914577411L;
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(MapNode.class);
+
     private final double MAP_SCALE          = 1;
     private final int    MAX_TILE_LEVEL     = 19;
     private final int    TILE_PIXEL_SIZE    = 256;
@@ -210,14 +212,8 @@ public class MapNode extends G2DNode implements ITileListener  {
 
             this.tileCache = new TileCache(job);
             this.tileCache.addTileListener(this);
-        } catch (MalformedURLException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        } catch (URISyntaxException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
         } catch(Exception e ) {
-            e.printStackTrace();
+            LOGGER.error("Failed to initialize MapNode", e);
         }
     }
 
index 10abef0369231473bdb77b8d9e99536ccd33057d..e028f93a2e440c581b5654a4050707fea3f802ea 100644 (file)
@@ -14,6 +14,7 @@ package org.simantics.maps.tile;
 import java.awt.Color;
 import java.awt.Graphics2D;
 import java.awt.Image;
+import java.awt.Transparency;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
 import java.net.URI;
@@ -21,6 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.simantics.maps.ProvisionException;
+import org.simantics.maps.internal.ImageUtil;
 
 /**
  * @author Tuukka Lehtonen
@@ -130,7 +132,7 @@ public class CompoundTileProvider implements ITileProvider {
                 }
 
                 if (result == null) {
-                    result = new BufferedImage(tileSize, tileSize, BufferedImage.TYPE_3BYTE_BGR);
+                    result = ImageUtil.createScreenCompatibleImage(tileSize, tileSize, Transparency.OPAQUE);
                     g = result.createGraphics();
                 }
 
index 0431e6fed1ceb66035acabaf6ceeaada58210914..fb225387e6c163eb039fef9fb22176ae873701ea 100644 (file)
@@ -26,6 +26,7 @@ import java.util.List;
 import javax.imageio.ImageIO;
 
 import org.simantics.maps.ProvisionException;
+import org.simantics.maps.internal.ImageUtil;
 
 /**
  * @author Tuukka Lehtonen
@@ -171,7 +172,7 @@ public class Shp2ImgTileProvider implements ITileProvider {
             return outOfBoundsImage;
 
         final int outOfBoundsImageSize = 1;
-        BufferedImage image = new BufferedImage(outOfBoundsImageSize, outOfBoundsImageSize, BufferedImage.TYPE_3BYTE_BGR);
+        BufferedImage image = ImageUtil.createScreenCompatibleImage(outOfBoundsImageSize, outOfBoundsImageSize, BufferedImage.OPAQUE);
         Graphics2D g = image.createGraphics();
         try {
             g.setColor(Color.PINK);
@@ -247,13 +248,7 @@ public class Shp2ImgTileProvider implements ITileProvider {
                 //System.out.println("img = " + img);
                 if (img == null)
                     throw new ProvisionException("Failed to provide image for rectangle: " + r);
-
-                if (BufferedImage.TYPE_4BYTE_ABGR != img.getType()) {
-                    BufferedImage img2 = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
-                    img.copyData(img2.getRaster());
-                    return img2;
-                }
-                return img;
+                return ImageUtil.toScreenCompatibleImage(img);
             } finally {
                 if (tempFile.exists()) {
 //                    System.out.println("DELETING TEMP FILE: " + tempFile);
index 60e020679722e5c2483ba40db577100ab886bddb..696fbcf92706f786332221c27d90bc69f8338e03 100644 (file)
@@ -26,6 +26,7 @@ import javax.imageio.ImageIO;
 
 import org.simantics.maps.ProvisionException;
 import org.simantics.maps.WebService;
+import org.simantics.maps.internal.ImageUtil;
 import org.simantics.maps.tile.ITileProvider;
 import org.simantics.maps.tile.TileKey;
 
@@ -159,7 +160,7 @@ public class WMSTileProvider implements ITileProvider {
                     if (img == null) {
                         throw new IIOException("ImageIO returned null, unable to decode stream as image data.");
                     }
-                    return img;
+                    return ImageUtil.toScreenCompatibleImage(img);
                 }
             }