public synchronized ImageResource get(final String uri, final int width, final int height) {
    if (ImageUtil.isEmbeddedBase64Image(uri)) {
      ImageResource resource = loadEmbeddedBase64ImageResource(uri);
      BufferedImage newImg = ((AWTFSImage) resource.getImage()).getImage();
      return new ImageResource(
          resource.getImageUri(),
          AWTFSImage.createImage(ImageUtils.scaleImage(newImg, width, height)));
    } else {
      CacheKey key = new CacheKey(uri, width, height);
      ImageResource ir = (ImageResource) _imageCache.get(key);
      if (ir == null) {
        // not loaded, or not loaded at target size

        // loaded a base size?
        ir = (ImageResource) _imageCache.get(new CacheKey(uri, -1, -1));

        // no: loaded
        if (ir == null) {
          if (isImmediateLoadUri(uri)) {
            XRLog.load(Level.FINE, "Load immediate: " + uri);
            ir = loadImageResourceFromUri(uri);
            FSImage awtfsImage = ir.getImage();
            BufferedImage newImg = ((AWTFSImage) awtfsImage).getImage();
            loaded(ir, -1, -1);
            if (width > -1 && height > -1) {
              XRLog.load(Level.FINE, this + ", scaling " + uri + " to " + width + ", " + height);
              newImg = ImageUtils.scaleImage(newImg, width, height);
              ir = new ImageResource(ir.getImageUri(), AWTFSImage.createImage(newImg));
              loaded(ir, width, height);
            }
          } else {
            XRLog.load(Level.FINE, "Image cache miss, URI not yet loaded, queueing: " + uri);
            MutableFSImage mfsi = new MutableFSImage(_repaintListener);
            ir = new ImageResource(uri, mfsi);
            _loadQueue.addToQueue(this, uri, mfsi, width, height);
          }

          _imageCache.put(key, ir);
        } else {
          // loaded at base size, need to scale
          XRLog.load(Level.FINE, this + ", scaling " + uri + " to " + width + ", " + height);
          FSImage awtfsImage = ir.getImage();
          BufferedImage newImg = ((AWTFSImage) awtfsImage).getImage();

          newImg = ImageUtils.scaleImage(newImg, width, height);
          ir = new ImageResource(ir.getImageUri(), AWTFSImage.createImage(newImg));
          loaded(ir, width, height);
        }
      }
      return ir;
    }
  }
  public static ImageResource loadImageResourceFromUri(final String uri) {
    if (ImageUtil.isEmbeddedBase64Image(uri)) {
      return loadEmbeddedBase64ImageResource(uri);
    } else {
      StreamResource sr = new StreamResource(uri);
      InputStream is;
      ImageResource ir = null;
      try {
        sr.connect();
        is = sr.bufferedStream();
        try {
          BufferedImage img = ImageIO.read(is);
          if (img == null) {
            throw new IOException("ImageIO.read() returned null");
          }
          ir = createImageResource(uri, img);
        } catch (FileNotFoundException e) {
          XRLog.exception("Can't read image file; image at URI '" + uri + "' not found");
        } catch (IOException e) {
          XRLog.exception("Can't read image file; unexpected problem for URI '" + uri + "'", e);
        } finally {
          sr.close();
        }
      } catch (IOException e) {
        // couldnt open stream at URI...
        XRLog.exception("Can't open stream for URI '" + uri + "': " + e.getMessage());
      }

      // When we do this we return null which will raise an exception on layout/render, which
      // will allow us to use the fallback discover page in cases when the network/site are
      // unavailable
      //            if (ir == null) {
      //                ir = createImageResource(uri, null);
      //            }
      return ir;
    }
  }