diff options
author | Erich Schubert <erich@debian.org> | 2012-06-02 17:47:03 +0200 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2019-03-09 22:30:32 +0000 |
commit | 593eae6c91717eb9f4ff5088ba460dd4210509c0 (patch) | |
tree | d97e8cefb48773a382542e9e9d4a6796202a044a /src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java | |
parent | e580e42664ca92fbf8792bc39b8d59383db829fe (diff) | |
parent | c36aa2a8fd31ca5e225ff30278e910070cd2c8c1 (diff) |
Import Debian changes 0.5.0~beta2-1
elki (0.5.0~beta2-1) unstable; urgency=low
* New upstream beta release.
* Needs GNU Trove 3, in NEW.
* Build with OpenJDK7, as OpenJDK6 complains.
elki (0.5.0~beta1-1) unstable; urgency=low
* New upstream beta release.
* Needs GNU Trove 3, not yet in Debian (private package)
* Build with OpenJDK7, as OpenJDK6 complains.
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java')
-rw-r--r-- | src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java new file mode 100644 index 00000000..dd844165 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java @@ -0,0 +1,249 @@ +package de.lmu.ifi.dbs.elki.visualization.batikutil; +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2012 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import gnu.trove.iterator.TIntObjectIterator; +import gnu.trove.map.TIntObjectMap; +import gnu.trove.map.hash.TIntObjectHashMap; + +import java.awt.image.RenderedImage; +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.SoftReference; +import java.util.Iterator; + +import org.apache.batik.ext.awt.image.GraphicsUtil; +import org.apache.batik.ext.awt.image.renderable.Filter; +import org.apache.batik.ext.awt.image.renderable.RedRable; +import org.apache.batik.ext.awt.image.spi.AbstractRegistryEntry; +import org.apache.batik.ext.awt.image.spi.ImageTagRegistry; +import org.apache.batik.ext.awt.image.spi.MagicNumberRegistryEntry; +import org.apache.batik.ext.awt.image.spi.URLRegistryEntry; +import org.apache.batik.svggen.ErrorConstants; +import org.apache.batik.util.ParsedURL; +import org.apache.batik.util.ParsedURLData; +import org.apache.batik.util.ParsedURLProtocolHandler; + +import de.lmu.ifi.dbs.elki.logging.Logging; + +/** + * Access images via an internal image registry. + * + * @author Erich Schubert + */ +public class ThumbnailRegistryEntry extends AbstractRegistryEntry implements URLRegistryEntry, ParsedURLProtocolHandler { + /** + * ELKI internal thumbnail protocol id. + */ + public static final String INTERNAL_PROTOCOL = "thumb"; + + /** + * ELKI internal thumbnail protocol prefix + */ + public static final String INTERNAL_PREFIX = INTERNAL_PROTOCOL + ":"; + + /** + * Mime type + */ + public static final String INTERNAL_MIME_TYPE = "internal/thumb"; + + /** + * The priority of this entry. + */ + public static final float PRIORITY = 1 * MagicNumberRegistryEntry.PRIORITY; + + /** + * The logger class. + */ + private static final Logging logger = Logging.getLogger(ThumbnailRegistryEntry.class); + + /** + * The image cache. + */ + private static final TIntObjectMap<SoftReference<RenderedImage>> images = new TIntObjectHashMap<SoftReference<RenderedImage>>(); + + /** + * Object counter + */ + private static int counter = 1; + + /** + * Constructor. + * + * Note: there will usually be two instances created. One for handling the + * image type, one for the URL handling. This is ok. + */ + public ThumbnailRegistryEntry() { + super("Internal", PRIORITY, new String[0], new String[] { INTERNAL_MIME_TYPE }); + if(logger.isDebuggingFiner()) { + logger.debugFiner("Registry initialized."); + } + } + + /** + * Put an image into the repository (note: the repository is only keeping a + * weak reference!) + * + * @param img Image to put + * @return Key + */ + public static int registerImage(RenderedImage img) { + synchronized(images) { + int key = counter; + counter++; + assert (images.get(key) == null); + images.put(key, new SoftReference<RenderedImage>(img)); + // Reorganize map, purge old entries + if(counter % 50 == 49) { + for(TIntObjectIterator<SoftReference<RenderedImage>> iter = images.iterator(); iter.hasNext();) { + iter.advance(); + if(iter.value() == null || iter.value().get() == null) { + iter.remove(); + } + } + } + if(logger.isDebuggingFiner()) { + logger.debugFiner("Registered image: " + key); + } + return key; + } + } + + @Override + public boolean isCompatibleURL(ParsedURL url) { + // logger.warning("isCompatible " + url.toString()); + return isCompatibleURLStatic(url); + } + + /** + * Test for a compatible URL. + * + * @param url URL + * @return Success code + */ + public static boolean isCompatibleURLStatic(ParsedURL url) { + return url.getProtocol().equals(INTERNAL_PROTOCOL); + } + + @Override + public Filter handleURL(ParsedURL url, boolean needRawData) { + Filter ret = handleURL(url); + if(ret != null) { + return ret; + } + // Image not found in registry. + return ImageTagRegistry.getBrokenLinkImage(ThumbnailRegistryEntry.this, ErrorConstants.ERR_IMAGE_DIR_DOES_NOT_EXIST, new Object[0]); + } + + /** + * Statically handle the URL access. + * + * @param url URL to access + * @return Image, or null + */ + public static Filter handleURL(ParsedURL url) { + if(logger.isDebuggingFiner()) { + logger.debugFiner("handleURL " + url.toString()); + } + if(!isCompatibleURLStatic(url)) { + return null; + } + int id; + try { + id = Integer.parseInt(url.getPath()); + } + catch(NumberFormatException e) { + return null; + } + SoftReference<RenderedImage> ref = images.get(id); + if(ref != null) { + RenderedImage ri = ref.get(); + if(ri == null) { + logger.warning("Referenced image has expired from the cache!"); + } + else { + return new RedRable(GraphicsUtil.wrap(ri)); + } + } + // Image not found in registry. + return null; + } + + /** + * URL representation for internal URLs. + * + * @author Erich Schubert + */ + class InternalParsedURLData extends ParsedURLData { + /** + * Constructor. + */ + public InternalParsedURLData(String id) { + super(); + this.protocol = INTERNAL_PROTOCOL; + this.contentType = INTERNAL_MIME_TYPE; + this.path = id; + } + + @Override + public String getContentType(String userAgent) { + return INTERNAL_MIME_TYPE; + } + + @Override + public boolean complete() { + return true; + } + + @SuppressWarnings("rawtypes") + @Override + public InputStream openStream(String userAgent, Iterator mimeTypes) throws IOException { + // Return null, since we don't want to use streams. + return null; + } + } + + @Override + public ParsedURLData parseURL(String urlStr) { + if(logger.isDebuggingFinest()) { + logger.debugFinest("parseURL: " + urlStr); + } + if(urlStr.startsWith(INTERNAL_PREFIX)) { + InternalParsedURLData ret = new InternalParsedURLData(urlStr.substring(INTERNAL_PREFIX.length())); + return ret; + } + return null; + } + + @Override + public ParsedURLData parseURL(ParsedURL basepurl, String urlStr) { + // Won't happen in a relative way anyway, and is not particularly + // supported (as the objects might be dropped from the cache) + return parseURL(urlStr); + } + + @Override + public String getProtocolHandled() { + return INTERNAL_PROTOCOL; + } +}
\ No newline at end of file |