/**
  * Renders the image at the proper size into <code>bgImage</code>. This method assumes that <code>
  * bgImage</code> is not <code>null</code>.
  *
  * @param width The width of the volatile image to render into.
  * @param height The height of the volatile image to render into.
  * @param hint The scaling hint to use.
  */
 protected void renderImage(int width, int height, int hint) {
   Image master = getMasterImage();
   if (master != null) {
     do {
       Image i = master.getScaledInstance(width, height, hint);
       tracker.addImage(i, 1);
       try {
         tracker.waitForID(1);
       } catch (InterruptedException e) {
         e.printStackTrace();
         bgImage = null;
         return;
       } finally {
         tracker.removeImage(i, 1);
       }
       bgImage.getGraphics().drawImage(i, 0, 0, null);
       tracker.addImage(bgImage, 0);
       try {
         tracker.waitForID(0);
       } catch (InterruptedException e) {
         e.printStackTrace();
         bgImage = null;
         return;
       } finally {
         tracker.removeImage(bgImage, 0);
       }
     } while (bgImage.contentsLost());
   } // End of if (master!=null).
   else {
     bgImage = null;
   }
 }
 /**
  * Paints the image at the specified location. This method assumes scaling has already been done,
  * and simply paints the background image "as-is."
  *
  * @param g The graphics context.
  * @param x The x-coordinate at which to paint.
  * @param y The y-coordinate at which to paint.
  */
 protected void paintImage(Graphics g, int x, int y) {
   if (bgImage != null) {
     do {
       int rc = bgImage.validate(null); // getGraphicsConfiguration());
       if (rc == VolatileImage.IMAGE_RESTORED) {
         // FIXME:  If the image needs to be restored are its width
         // and height still valid??  If not, we'll need to cache
         // these values...
         renderImage(bgImage.getWidth(), bgImage.getHeight(), getScalingHint());
       }
       g.drawImage(bgImage, x, y, null);
     } while (bgImage.contentsLost());
   }
 }
 private static void test(BufferedImage bi, int type) throws IOException {
   GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
   GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
   VolatileImage vi = gc.createCompatibleVolatileImage(511, 255, type);
   BufferedImage gold = gc.createCompatibleImage(511, 255, type);
   // draw to compatible Image
   Graphics2D big = gold.createGraphics();
   // force scaled blit
   big.drawImage(bi, 7, 11, 127, 111, 7, 11, 127 * 2, 111, null);
   big.dispose();
   // draw to volatile image
   BufferedImage snapshot;
   while (true) {
     vi.validate(gc);
     if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
       try {
         Thread.sleep(100);
       } catch (final InterruptedException ignored) {
       }
       continue;
     }
     Graphics2D vig = vi.createGraphics();
     // force scaled blit
     vig.drawImage(bi, 7, 11, 127, 111, 7, 11, 127 * 2, 111, null);
     vig.dispose();
     snapshot = vi.getSnapshot();
     if (vi.contentsLost()) {
       try {
         Thread.sleep(100);
       } catch (final InterruptedException ignored) {
       }
       continue;
     }
     break;
   }
   // validate images
   for (int x = 7; x < 127; ++x) {
     for (int y = 11; y < 111; ++y) {
       if (gold.getRGB(x, y) != snapshot.getRGB(x, y)) {
         ImageIO.write(gold, "png", new File("gold.png"));
         ImageIO.write(snapshot, "png", new File("bi.png"));
         throw new RuntimeException("Test failed.");
       }
     }
   }
 }