@Override
  public BufferedImage composeImageForSector(
      Sector sector,
      int canvasWidth,
      int canvasHeight,
      double aspectRatio,
      int levelNumber,
      String mimeType,
      boolean abortOnError,
      BufferedImage image,
      int timeout)
      throws Exception {
    if (sector == null) {
      String message = Logging.getMessage("nullValue.SectorIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    ComposeImageTile tile =
        new ComposeImageTile(
            sector, mimeType, this.getLevels().getLastLevel(), canvasWidth, canvasHeight);
    try {
      if (image == null)
        image = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_RGB);

      downloadImage(tile, mimeType, timeout);
      Thread.sleep(1); // generates InterruptedException if thread has been interupted

      BufferedImage tileImage = ImageIO.read(tile.getFile());
      Thread.sleep(1); // generates InterruptedException if thread has been interupted

      ImageUtil.mergeImage(sector, tile.getSector(), aspectRatio, tileImage, image);
      Thread.sleep(1); // generates InterruptedException if thread has been interupted

      this.firePropertyChange(AVKey.PROGRESS, 0d, 1d);
    } catch (InterruptedIOException e) {
      throw e;
    } catch (Exception e) {
      if (abortOnError) throw e;

      String message = Logging.getMessage("generic.ExceptionWhileRequestingImage", tile.getPath());
      Logging.logger().log(java.util.logging.Level.WARNING, message, e);
    }

    return image;
  }
  private static void addSprites(Compositor sh) throws IOException, QTException {
    File matchFile =
        QTFactory.findAbsolutePath("images/Ship01.pct"); // this file must exist in the directory!!!
    ImageDataSequence isp = ImageUtil.createSequence(matchFile);
    ImageDataSequence seq = ImageUtil.makeTransparent(isp, QDColor.blue);

    // Build Sprites
    Matrix matrix1 = new Matrix();
    matrix1.setTx(20);
    matrix1.setTy(20);
    matrix1.setSx(0.8F);
    matrix1.setSy(0.8F);
    TwoDSprite s1 = new TwoDSprite(seq, 4, matrix1, true, 1);
    sh.addMember(s1);

    Matrix matrix2 = new Matrix();
    matrix2.setTx(4);
    matrix2.setTy(4);
    TwoDSprite s2 = new TwoDSprite(seq, 1, matrix2, true, 10);
    sh.addMember(s2);

    // This needs to be a 32bit QDGraphics so the blend mode will
    // be applied correctly to this sprite
    File shipFile = QTFactory.findAbsolutePath("images/Ship10.pct");
    GraphicsImporterDrawer ip = new GraphicsImporterDrawer(new QTFile(shipFile));
    QDRect r = new QDRect(ip.getDescription().getWidth(), ip.getDescription().getHeight());
    ImageSpec si =
        ImageUtil.makeTransparent(
            ip, QDColor.blue, new QDGraphics(QDGraphics.kDefaultPixelFormat, r));
    Matrix matrix3 = new Matrix();
    matrix3.setTx(50);
    matrix3.setTy(50);
    TwoDSprite s3 =
        new TwoDSprite(si, matrix3, true, 8, new GraphicsMode(QDConstants.blend, QDColor.green));
    sh.addMember(s3);

    // Add Dragger (DEPRECATED CODE)
    /*		Dragger dragger = new Dragger (InputEvent.SHIFT_MASK);
    SWController controller = new SWController (dragger, true);
    sh.addController (controller);*/

    QTMouseTargetController shipController = new QTMouseTargetController(true);
    shipController.addQTMouseListener(
        new DragAction(new TranslateMatrix()) {
          // only activates when the shift modifier is pressed
          public boolean matchModifierFilter(int mods) {
            if ((mods & 0xF) == QTConstants.kJavaShiftMask) return true;
            return false;
          }
        });
    sh.addController(shipController);

    // Add Controllers
    // Build ActionList
    SimpleActionList al = new SimpleActionList();
    ImageSequencer is = new ImageSequencer(seq);
    is.setLooping(ImageSequencer.kLoopForwards);
    al.addMember(new NextImageAction(10, 1, is, s1));
    al.addMember(new BounceAction(5, 1, sh, s1, 3, 2));
    ImageSequencer is2 = new ImageSequencer(seq);
    is2.setLooping(ImageSequencer.kLoopForwards);
    al.addMember(new NextImageAction(20, 1, is2, s2));
    al.addMember(new BounceAction(20, 1, sh, s2, 4, 3));
    sh.addController(al);
  }