private static byte[] convertChartToByteArray(
      Chart chartDetails, JFreeChart chart, int width, int height)
      throws IOException, IIOInvalidTreeException {
    BufferedImage buffImg =
        chart.createBufferedImage(
            width, height, BufferedImage.BITMASK | BufferedImage.SCALE_SMOOTH, null);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageWriter writer = ImageIO.getImageWritersByFormatName("png").next();

    ImageWriteParam writeParam = writer.getDefaultWriteParam();
    ImageTypeSpecifier typeSpecifier =
        ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
    IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);

    if (chartDetails != null) {
      if (chartDetails.getId() == null) {
        chartDetails.setId("%ID%");
      }
      IIOMetadataNode textEntry = new IIOMetadataNode("tEXtEntry");
      textEntry.setAttribute("keyword", "chart-google-data");
      ByteArrayOutputStream bout = new ByteArrayOutputStream();
      ObjectOutputStream objectOutputStream = new ObjectOutputStream(bout);
      objectOutputStream.writeObject(chartDetails);
      objectOutputStream.flush();
      textEntry.setAttribute(
          "value",
          (String)
              ChartRendererFactory.getRendererForOutput(ChartRendererGoogleTools.TYPE)
                  .renderChart(chartDetails));

      IIOMetadataNode text = new IIOMetadataNode("tEXt");
      text.appendChild(textEntry);

      IIOMetadataNode root = new IIOMetadataNode("javax_imageio_png_1.0");
      root.appendChild(text);

      metadata.mergeTree("javax_imageio_png_1.0", root);
    }
    // setDPI(metadata);

    final ImageOutputStream stream = ImageIO.createImageOutputStream(baos);
    try {
      writer.setOutput(stream);
      writer.write(metadata, new IIOImage(buffImg, null, metadata), writeParam);
    } finally {
      stream.close();
    }

    byte[] bytes = baos.toByteArray(); // ChartUtilities.encodeAsPNG(buffImg, true, 9);
    return bytes;
  }
  public Iterator getImageTypes(int imageIndex) throws IOException {
    readFile();

    checkIndex(imageIndex);

    // Create a List of ImageTypeSpecifiers that identify the possible image
    // types to which the single JBIG2 image can be decoded. An
    // ImageTypeSpecifier is used with ImageReader's getDestination() method
    // to return an appropriate BufferedImage that contains the decoded
    // image, and is accessed by an application.

    List l = new ArrayList();

    // The JBIG2 reader only uses a single List entry. This entry describes
    // a
    // BufferedImage of TYPE_INT_RGB, which is a commonly used image type.

    l.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY));

    // Return an iterator that retrieves elements from the list.

    return l.iterator();
  }
  public Iterator<ImageTypeSpecifier> getImageTypes(int pIndex) throws IOException {
    checkBounds(pIndex);

    init(pIndex);

    // TODO: FIX ME!
    // - Use factory methods for ImageTypeSpecifier, create factory methods if necessary
    List<ImageTypeSpecifier> specs = new ArrayList<ImageTypeSpecifier>();
    try {
      ColorModel cm;
      // NOTE: These are all fall-through by intention
      switch (mImage.getImageType()) {
        case ImageType.BilevelType:
          specs.add(
              IndexedImageTypeSpecifier.createFromIndexColorModel(
                  MonochromeColorModel.getInstance()));
        case ImageType.GrayscaleType:
          //                    cm = MagickUtil.CM_GRAY_OPAQUE;
          //                    specs.add(new ImageTypeSpecifier(
          //                            cm,
          //                            cm.createCompatibleSampleModel(1, 1)
          //                    ));
          specs.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY));
        case ImageType.GrayscaleMatteType:
          cm = CM_GRAY_ALPHA;
          specs.add(new ImageTypeSpecifier(cm, cm.createCompatibleSampleModel(1, 1)));
        case ImageType.PaletteType:
          specs.add(
              IndexedImageTypeSpecifier.createFromIndexColorModel(
                  MagickUtil.createIndexColorModel(mImage.getColormap(), false)));
        case ImageType.PaletteMatteType:
          specs.add(
              IndexedImageTypeSpecifier.createFromIndexColorModel(
                  MagickUtil.createIndexColorModel(mImage.getColormap(), true)));
        case ImageType.TrueColorType:
          //                    cm = MagickUtil.CM_COLOR_OPAQUE;
          //                    specs.add(new ImageTypeSpecifier(
          //                            cm,
          //                            cm.createCompatibleSampleModel(1, 1)
          //                    ));
          specs.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR));
        case ImageType.TrueColorMatteType:
          //                    cm = MagickUtil.CM_COLOR_ALPHA;
          //                    specs.add(new ImageTypeSpecifier(
          //                            cm,
          //                            cm.createCompatibleSampleModel(1, 1)
          //                    ));
          specs.add(
              ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR_PRE));
          break;
        case ImageType.ColorSeparationType:
        case ImageType.ColorSeparationMatteType:
        case ImageType.OptimizeType:
        default:
          throw new MagickException("Unknown JMagick image type: " + mImage.getImageType());
      }
    } catch (MagickException e) {
      throw new IIOException(e.getMessage(), e);
    }

    return specs.iterator();
  }