protected void imageImpl(PImage who,
                           float x1, float y1, float x2, float y2,
                           int u1, int v1, int u2, int v2) {
    // Image not ready yet, or an error
    if (who.width <= 0 || who.height <= 0) return;
    
    if (who.getCache(this) == null) {
      //System.out.println("making new image cache");
      who.setCache(this, new ImageCache(who));
      who.updatePixels();  // mark the whole thing for update
      who.modified = true;
    }

    ImageCache cash = (ImageCache) who.getCache(this);
    // if image previously was tinted, or the color changed
    // or the image was tinted, and tint is now disabled
    if ((tint && !cash.tinted) ||
        (tint && (cash.tintedColor != tintColor)) ||
        (!tint && cash.tinted)) {
      // for tint change, mark all pixels as needing update
      who.updatePixels();
    }

    if (who.modified) {
      cash.update(tint, tintColor);
      who.modified = false;
    }

    g2.drawImage(((ImageCache) who.getCache(this)).image,
                 (int) x1, (int) y1, (int) x2, (int) y2,
                 u1, v1, u2, v2, null);
  }