1

Here is my code

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class FileConverterService {
  public void convertPptToImages() throws Exception {
    ClassLoader classLoader = getClass().getClassLoader();
    File file = new File(classLoader.getResource("Sylon_GuidedPath_Sprint22Deck.ppt").getFile());

    Document pdfDocument = new Document();
    //    PdfWriter pdfWriter = PdfWriter.getInstance(pdfDocument, new FileOutputStream(""));
    FileInputStream is = new FileInputStream(file);
    HSLFSlideShow ppt = new HSLFSlideShow(is);
    is.close();
    Dimension pgsize = ppt.getPageSize();
    pdfDocument.setPageSize(new Rectangle((float) pgsize.getWidth(), (float) pgsize.getHeight()));
    // convert to images
    int idx = 1;
    for (HSLFSlide slide : ppt.getSlides()) {
      BufferedImage img =
          new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_RGB);
      Graphics2D graphics = img.createGraphics();
      graphics.setRenderingHint(
          RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
      graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      graphics.setRenderingHint(
          RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
      graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
      graphics.setRenderingHint(
          RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
      graphics.setRenderingHint(
          RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
      // clear the drawing area
      graphics.setPaint(Color.white);
      graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
      // render
      slide.draw(graphics);
      // save the output
      ImageWriter jpgWriter = ImageIO.getImageWritersByFormatName("jpg").next();
      ImageWriteParam jpgWriteParam = jpgWriter.getDefaultWriteParam();
      jpgWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
      jpgWriteParam.setCompressionQuality(1f);
      jpgWriter.setOutput(new FileImageOutputStream(
        new File("slide-" + idx + ".jpg")));
      IIOImage outputImage = new IIOImage(img, null, null);
      jpgWriter.write(null, outputImage, jpgWriteParam);
      jpgWriter.dispose();
      idx++;
    }
  }

I based my code off this documentation, http://poi.apache.org/components/slideshow/how-to-shapes.html#Render

I have tried both jpeg and png, and the image seems to be fairly low resolution and the text is difficult to read compared to the original .ppt. Is there any way to increase the resolution/quality of the images?

  • As I saw you want to render to PDF, I've added that tonight to the POI trunk ... so how is that? ;) You'll need additional libraries and I need to rerun the documentation build to put the changes online – kiwiwings Nov 03 '20 at 00:44
  • @kiwiwings yeah I am only converting to images so I can create a pdf. So you are saying you will now be able to convert a powerpoint directly to a pdf with just POI? When is it expected to be in a release? Could you link me to the MR? – HelloWhatsMyName1234 Nov 03 '20 at 09:20

1 Answers1

1

What you can try

  1. Applying RenderingHints to the graphics, below is a sample I created comparing the image with/without rendering hint. You can see that the character looks better with rendering hint.
  2. Increase the compression quality for the jpeg image.

compare with and without rendering hint

Following program demonstrates how to generate image with/without rendering hint and create image with 100% compression quality.

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.FileImageOutputStream;

import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;

public class ImproveSlideConvertToImageQuality {
    public static void main(String[] args) throws Exception {
        convertPptToImages(true);
        convertPptToImages(false);
    }

    public static void convertPptToImages(boolean withRenderHint) throws Exception {
        File file = new File("test.ppt");
        String suffix = withRenderHint ? "-with-hint" : "-without-hint";
        try (FileInputStream is = new FileInputStream(file); HSLFSlideShow ppt = new HSLFSlideShow(is)) {
            Dimension pgsize = ppt.getPageSize();
            int idx = 1;
            for (HSLFSlide slide : ppt.getSlides()) {
                BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_RGB);
                Graphics2D graphics = img.createGraphics();
                if (withRenderHint) {
                    graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                            RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                    graphics.setRenderingHint(
                            RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
                    graphics.setRenderingHint(
                            RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    graphics.setRenderingHint(
                            RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                    graphics.setRenderingHint(
                            RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                    graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                            RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
                }
                // render
                slide.draw(graphics);
                final ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
                writer.setOutput(new FileImageOutputStream(
                        new File("slide-" + idx + suffix + ".jpeg")));
                JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
                jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                jpegParams.setCompressionQuality(1f);
                // writes the file with given compression level
                // from your JPEGImageWriteParam instance
                IIOImage image = new IIOImage(img, null, null);
                writer.write(null, image, jpegParams);
                writer.dispose();
                idx++;
            }
        }
    }
}

References:
Controlling Rendering Quality
Setting jpg compression level with ImageIO in Java

samabcde
  • 6,988
  • 2
  • 25
  • 41
  • Thanks, before I saw youe edit with the code I did pretty much the exact same code myself which is now in OP, and the image quality has been improved, but not by much. Are there any other options? – HelloWhatsMyName1234 Nov 02 '20 at 17:10
  • 1
    yes ... you can export to SVG too. Please check the [render documentation](http://poi.apache.org/components/slideshow/ppt-wmf-emf-renderer.html). If you need more support, you can contact me [directly](https://stackoverflow.com/users/2066598/kiwiwings?tab=profile) – kiwiwings Nov 02 '20 at 19:05