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

No image using XObject with PageModifier #277

Open
KernelDeimos opened this issue May 6, 2018 · 6 comments
Open

No image using XObject with PageModifier #277

KernelDeimos opened this issue May 6, 2018 · 6 comments

Comments

@KernelDeimos
Copy link

I'm attempting to render a PNG on a context given to me by a PageModifier. I believe I need to use createFromXObjectFromPNG because I eventually need to get my image from a stream rather than a file (as it's base64-encoded). Right now I'm testing it with a regular png file.

I am not pausing the context because I don't know how to do that when using the page modifier. I tried using pdfWriter.pausePageContentContext, but this induces a segfault (I'm assuming because it was created with the modifier)

This is how I'm attempting to render the image:

	var imageXObject = pdfWriter.createFormXObjectFromPNG(
		// imageStream // please work ...
		"test.png"
	);
	var inX = 0;
	var inY = 0;
	var scaleX = pageWidth;
	var scaleY = pageHeight;
	// src/deps/PDFWriter/AbstractContentContext.cpp
	ctx.q().cm(scaleX,0,0,scaleY,inX,inY)
		.doXObject(imageXObject).Q();

This snippet of code is being called inside the renderPage function of the follow code which instantiates the page modifier. It also draws a test image which gets rendered successfully.

		var ins = new hummus.PDFRStreamForFile("./input.pdf");
		var ous = new hummus.PDFStreamForResponse(res);
		var pdfWriter = hummus.createWriterToModify(ins, ous);

		var pdfReader = pdfWriter.getModifiedFileParser();
		var pageCount = pdfReader.getPagesCount();

		console.log("rendering PDF with " + pageCount + " pages")
		for (var i=0; i < pageCount; i++) {
			// Start context for page modifier
			var pageModifier = new hummus.PDFPageModifier(pdfWriter, i);
			var ctx = pageModifier.startContext().getContext();
			var pageInfo = pdfReader.parsePage(i);

			// from left, from bottom
			ctx.drawImage(20,20,"test.png");

			renderPage(pdfWriter, ctx, i, pageInfo, parsedFormData, parsedSessData);

			// Write modified page to buffer (well, I hope it's a buffer)
			pageModifier.endContext().writePage();
		}

		// Finish writing pdf and send data
		pdfWriter.end();
		res.end()
@galkahana
Copy link
Owner

Wonderful question!
you can use pageModifier.endContext() to temporarily pause writing, and then continue with pageModifier.startContext().

read more here:
https://github.com/galkahana/HummusJS/wiki/Modification#adding-content-to-existing-pages

As an alternative you can make the call to creating the png form later, and use a previously allocated object ID that you allocate while writing the page content. i call this forward referencing, you can see an example here:
https://github.com/galkahana/HummusJS/blob/master/tests/ImagesAndFormsForwardReferenceTest.js

@KernelDeimos
Copy link
Author

Awesome, thanks! I think I'll use forward referencing since it'll make my code the cleanest. Is there any notable performance difference? I'm guessing the only difference is it changes the output slightly, putting all the images in one place in the binary - would that be correct?

@galkahana
Copy link
Owner

correct. nothing that should hurt you in terms of performance.

@KernelDeimos
Copy link
Author

I got it partially working. For now I'm just using the startContext() and endContext() functions. I made the assumption that I need to call getContext() again to update my context.

The problem I'm having now is that, instead of rendering my images, my code is rendering semi-transparent black boxes in the wrong locations.

This is how I'm getting a stream from my base64 image:

imageData = base64data.split(',')[1];
var imageBuffer = new Buffer(imageData, 'base64');
var imageStream = new hummus.PDFRStreamForBuffer(
	imageBuffer
);

pdf.pageModifier.endContext();
var imageXObject = pdf.writer.createFormXObjectFromPNG(
	imageStream
);

pdf.ctx = pdf.pageModifier.startContext().getContext();

pdf.ctx.q().cm(scaleX,0,0,scaleY,inX,inY)
	.doXObject(imageXObject).Q();

Is there anything obvious that I'm doing wrong? I tried writing a file using the same base64 data and that file works fine. I'm heading to sleep now but tomorrow I'll double-check that writing to a png file from the buffer I made works

@galkahana
Copy link
Owner

Try first to drop the cm. See that you get the images one on top of each other at top left corner. Continue fron there.

Also try adding true as second param wgen initting pagemodifier

@chunyenHuang
Copy link
Contributor

The problem I'm having now is that, instead of rendering my images, my code is rendering semi-transparent black boxes in the wrong locations.

Try first to drop the cm. See that you get the images one on top of each other at top left corner. Continue fron there.

If you find the image is placed in wrong place, can you check the mediaBox of your pdf file?
If it does not look like [0, 0, *, *], you will need to calibrate your inX, inY.

@mLuby mLuby mentioned this issue Jun 25, 2018
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

3 participants