@Override
  public byte[] getTilesMergedJpeg(List<TileInfo> tileList, int tileWidth, int tileHeight) {
    int width = Math.max(tileWidth, tileWidth * tileList.size());

    BufferedImage bufferedImage =
        new BufferedImage(width, tileHeight, BufferedImage.TYPE_3BYTE_BGR);
    Graphics2D g = bufferedImage.createGraphics();

    synchronized (offlineImage) {
      int i = 0;
      for (TileInfo tile : tileList) {
        Rectangle rc = tile.getTileRect();
        g.drawImage(
            offlineImage,
            i * tileWidth,
            0,
            i * tileWidth + rc.width,
            rc.height,
            rc.x,
            rc.y,
            rc.x + rc.width,
            rc.y + rc.height,
            null);
        i++;
      }
    }

    byte[] imgBits = null;
    try {
      imgBits = ImageHelper.jpegFromImage(bufferedImage);
    } catch (IOException e) {
      s_logger.info("[ignored] read error on image tiles", e);
    }
    return imgBits;
  }
  @Override
  public byte[] getFrameBufferJpeg() {
    int width = offlineImage.getWidth();
    int height = offlineImage.getHeight();

    BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
    Graphics2D g = bufferedImage.createGraphics();
    synchronized (offlineImage) {
      g.drawImage(offlineImage, 0, 0, width, height, 0, 0, width, height, null);
      g.dispose();
    }

    byte[] imgBits = null;
    try {
      imgBits = ImageHelper.jpegFromImage(bufferedImage);
    } catch (IOException e) {
      s_logger.info("[ignored] read error on image", e);
    }

    return imgBits;
  }