Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way to output an image file rather than a pdf? #73

Open
Jo3McCarthy opened this issue Feb 23, 2017 · 8 comments
Open

Is there a way to output an image file rather than a pdf? #73

Jo3McCarthy opened this issue Feb 23, 2017 · 8 comments

Comments

@Jo3McCarthy
Copy link

Hi, All;

I think the process of rendering has some interim processing steps where content is converted into images. Is there a method to output the images directly? Or, could you please point me to a point in the code where I could implement that function?

Thanks,

Jo3

@danfickle
Copy link
Owner

Hi @Jo3McCarthy

There is a Java2D output device in the core. See the swing package I think. Unfortunately, it is broken at the moment. Also see #63
If you'd like to work on it, I'd be happy to help. I think as a start we should work on moving it to its own module.

Regards,
Daniel.

@rototor
Copy link
Contributor

rototor commented Feb 26, 2017

Just saw this issue. With #74 I started to implement something similar to the PdfRendererBuilder. If you just want to quick render some HTML as Image you could use Graphics2DRenderer.renderToImageAutoSize(). But you need a URL (e.g. file.toURL().toExternalURI()) for that to work. With the Java2DRendererBuilder (name can still change) you can also render in memory HTML string as image. In the midterm I think we should get rid of the old Graphics2DRenderer and Java2DRenderer. The later does not even work at the moment.

danfickle added a commit that referenced this issue Mar 5, 2017
…r paged output.

For now, I’ve copied accross the files I needed to alter to the java2d
sub-module to avoid breaking things. Eventually we can get rid of all
Java2D and Swing code from the core.

Currently the renderer and builder in the sub-module are for paged
output only but I think we can combine both paged and continuous in the
one builder/renderer.
@danfickle
Copy link
Owner

OK, I've implemented a new renderer and worked on the builder by @rototor (in a copy) to output to paged images. One can incorporate the java2d sub-module and use it thus (but it is likely to change):

		BufferedImage bf = new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR);
		final Graphics2D g2d = bf.createGraphics();
		
		Java2DRendererBuilder builder = new Java2DRendererBuilder();
		
		builder.withUri("file:///Users/me/Documents/pdftests/image-output-device-test.htm");
		builder.useLayoutGraphics(g2d);
		builder.usePageProcessor(new DefaultPageProcessor("/Users/me/Documents/pdftests/images/%page-number%.png"));
		builder.useSVGDrawer(new BatikSVGDrawer());
		
		Java2DRenderer renderer = builder.buildJava2DRenderer();
		
		renderer.layout();
		renderer.writePages(0);

		g2d.dispose();

which will output a PNG image for each page of the document in the correct size.

@danfickle
Copy link
Owner

danfickle commented Mar 5, 2017

Start of a checklist for the Java2D (or any new) output device:

  • Output simple raster images
  • Output simple SVG images (with no text or embedded images)
  • Output raster images referenced by data URIs.
  • Import font-face rule fonts.
  • Test font fallback including in justified text.
  • Test font-face rule fonts in SVG images.
  • Test embedded raster images inside SVG images.
  • Correct RTL and BIDI support.
  • Should default background color be white?

danfickle added a commit that referenced this issue Mar 6, 2017
… (Still unstable and mostly unimplemented) [ci skip]
@Jo3McCarthy
Copy link
Author

Jo3McCarthy commented Mar 10, 2017

Thank you all for the input. Your suggestions have led to a partial solution, but I have mutually exclusive requirements at the moment. I can use the Graphics2DRenderer.renderToImageAutoSize() to render some of an image, but as I mentioned in Issue #71 the content I receive has HTML Entities from HTML5 (like " " and such). So, although I can use jsoup to parse the URL to a Document, I can not then feed that Document into Graphics2DRenderer.renderToImageAutoSize() because it requires a URL. By hand-tweaking the content before rendering, I get the full image at the requested size. But, hand-tweaking will not suffice for the use case. If anybody has already encountered this and has a solution, please share. Otherwise, I may have to go into the Graphics2DRenderer and implement another method that supports my requirement -- in which case, pray for me...

@danfickle
Copy link
Owner

danfickle commented Apr 3, 2017

RC10 has been released with image output in alpha state.
Current limitations:

  • RTL is not supported properly.
  • Custom object drawer support not implemented. Implemented in RC11.
  • Font fallback is not implemented for justified text.
  • Fonts can only be specified via font-face rules and not the builder.

The builder code can be found here.

You'll also need to include the Java2D submodule:

<dependency>
  		<groupId>com.openhtmltopdf</groupId>
  		<artifactId>openhtmltopdf-java2d</artifactId>
  		<version>${openhtml.version}</version>
  	</dependency>

Here is a simple example:

		DefaultPageProcessor processor = new DefaultPageProcessor(new FSPageOutputStreamSupplier() {
			@Override
			public OutputStream supply(int zeroBasedPageNumber) throws IOException {
				return new FileOutputStream("/Users/you/Documents/pdftests/images/%page-number%.png".replace("%page-number%", String.valueOf(zeroBasedPageNumber)));
			}
		}, BufferedImage.TYPE_3BYTE_BGR, "png");
		
		Graphics2D g2d = processor.createLayoutGraphics();
		
		Java2DRendererBuilder builder = new Java2DRendererBuilder();
		builder.withUri("file:///Users/you/Documents/pdftests/showcase.htm");
		builder.useLayoutGraphics(g2d);
		builder.useSVGDrawer(new BatikSVGDrawer()); // Optional
		builder.toPageProcessor(processor);
		builder.runPaged();

		g2d.dispose();

@danfickle
Copy link
Owner

I think this is the correct place to note that the layout for continuous image output mode is using "print" rather than "screen" media. This should be set by the builder, probably on the SharedContent object.

@conlaoch1
Copy link

conlaoch1 commented Jun 25, 2020

hi, @danfickle. the created image has a very low resolution / is very pixelated. is there a way to up the quality? thanks!

File file = new File("test");
            DefaultPageProcessor processor = new DefaultPageProcessor(new FSPageOutputStreamSupplier() {
                @Override
                public OutputStream supply(int zeroBasedPageNumber) throws IOException {
                    return new FileOutputStream(file);
                }
            }, BufferedImage.TYPE_3BYTE_BGR, "png");

            Graphics2D g2d = processor.createLayoutGraphics();

            Java2DRendererBuilder java2DRendererBuilder = new Java2DRendererBuilder();
            java2DRendererBuilder.withHtmlContent(filledOutTemplate, PDFUtil.class.getResource("/fonts/").toExternalForm() + "../");;
            java2DRendererBuilder.useEnvironmentFonts(true);
            java2DRendererBuilder.useLayoutGraphics(g2d);
            java2DRendererBuilder.useFastMode();
            java2DRendererBuilder.buildJava2DRenderer();
            java2DRendererBuilder.toPageProcessor(processor);
            java2DRendererBuilder.runFirstPage();

            g2d.dispose();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants