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

I need sample code to insert an Image into a page. #92

Closed
nonchan7720 opened this issue Aug 17, 2023 · 13 comments · Fixed by #94
Closed

I need sample code to insert an Image into a page. #92

nonchan7720 opened this issue Aug 17, 2023 · 13 comments · Fixed by #94

Comments

@nonchan7720
Copy link

Hello.

I am trying to create a new PDF document and create a one page PDF with one image.
I have created a page in the wasm version of pdfium and inserted an image, but it just shows a blank page and no image.

The procedure is as follows

  • Generate a new PDF document with FPDF_CreateNewDocument
  • Creation of Image object with FPDFPageObj_NewImageObj
  • Specify jpeg byte array and length in FPDFImageObj_LoadJpegFile
  • Get size from FPDFImageObj_GetImagePixelSize
  • Set Matrix from the size obtained by FPDFImageObj_SetMatrix
  • Generate page with FPDFPage_New
  • Specify Image object in FPDFPage_InsertObject
  • Generate content with FPDFPage_GenerateContent

I am trying to do the above, but it is not working properly, so I would like to have a sample code made.

@jerbob92
Copy link
Contributor

Hi! Can you give me your Go code so I can see what's wrong with it?

@nonchan7720
Copy link
Author

nonchan7720 commented Aug 18, 2023

@jerbob92
Thanks for the reply.
This is the kind of code we are working on.

type matrix struct {
	a float32
	b float32
	c float32
	d float32
	e float32
	f float32
}

func newMatrix(a, b, c, d, e, f float32) *matrix {
	m := matrix{
		a: a,
		b: b,
		c: c,
		d: d,
		e: e,
		f: f,
	}
	if m.a == 0 {
		m.a = 1
	}
	if m.d == 0 {
		m.d = 1
	}

	return &m
}

func newDefaultMatrix() *matrix {
	return newMatrix(0, 0, 0, 0, 0, 0)
}

func (m *matrix) multiply(other *matrix) *matrix {
	return newMatrix(
		m.a*other.a+m.b*other.c,
		m.a*other.b+m.b*other.d,
		m.c*other.a+m.d*other.c,
		m.c*other.b+m.d*other.d,
		m.e*other.a+m.f*other.c+other.e,
		m.e*other.b+m.f*other.d+other.f,
	)
}

func (m *matrix) scale(x, y float32) *matrix {
	return m.multiply(newMatrix(x, 0, 0, y, 0, 0))
}

func newImageToPage(ctx context.Context, doc references.FPDF_DOCUMENT, imageBuffer []byte) error {
	instance := GetInstance(ctx)
	img, err := instance.FPDFPageObj_NewImageObj(&requests.FPDFPageObj_NewImageObj{
		Document: doc,
	})
	if err != nil {
		return err
	}
	imgObject := img.PageObject
	defer closePageObject(ctx, imgObject)
	_, err = instance.FPDFImageObj_LoadJpegFile(&requests.FPDFImageObj_LoadJpegFile{
		ImageObject:    imgObject,
		FileReader:     bytes.NewReader(imageBuffer),
		FileReaderSize: int64(len(imageBuffer)),
	})
	if err != nil {
		return err
	}
	size, err := instance.FPDFImageObj_GetImagePixelSize(&requests.FPDFImageObj_GetImagePixelSize{
		ImageObject: imgObject,
	})
	if err != nil {
		return err
	}
	m := newDefaultMatrix().scale(float32(size.Width), float32(size.Height))
	_, err = instance.FPDFImageObj_SetMatrix(&requests.FPDFImageObj_SetMatrix{
		ImageObject: imgObject,
		Transform: structs.FPDF_FS_MATRIX{
			A: m.a,
			B: m.b,
			C: m.c,
			D: m.d,
			E: m.e,
			F: m.f,
		},
	})
	if err != nil {
		return err
	}
	page, err := instance.FPDFPage_New(&requests.FPDFPage_New{
		Document: doc,
		Width:    float64(size.Width),
		Height:   float64(size.Height),
	})
	if err != nil {
		return err
	}
	defer ClosePage(ctx, page.Page)
	_, err = instance.FPDFPage_InsertObject(&requests.FPDFPage_InsertObject{
		Page: requests.Page{
			ByReference: &page.Page,
		},
		PageObject: imgObject,
	})
	if err != nil {
		return err
	}
	_, err = instance.FPDFPage_GenerateContent(&requests.FPDFPage_GenerateContent{
		Page: requests.Page{
			ByReference: &page.Page,
		},
	})
	if err != nil {
		return err
	}
	if err != nil {
		return err
	}
	return nil
}

@nonchan7720
Copy link
Author

@jerbob92
I'd be happy to check 🙏.

@jerbob92
Copy link
Contributor

I have looked into it and this seems to be an issue with the WebAssembly version, when I try it in the CGO version it does work, I will investigate a bit more and add some tests for it.

@nonchan7720
Copy link
Author

Thank you for investigating this.
Is this not supported on the Wasm side and there is nothing I can do with this library?

@jerbob92
Copy link
Contributor

Everything is supported in both implementations, WASM and CGO, that it is not working is a bug.

@nonchan7720
Copy link
Author

I wish I could help, but my lack of skills makes it difficult to modify this library yet.

@jerbob92
Copy link
Contributor

I haven't figured it out yet, but:

  • It can load the image fine in WebAssembly, I have validated this by checking the pixel size with FPDFImageObj_GetImagePixelSize and actually rendering the bitmap in Go with FPDFImageObj_GetBitmap/FPDFBitmap_GetBuffer, and the image looks like what it should be
  • The image object is added to the PDF content
  • The image object content (XObject) is not added to the PDF content

@jerbob92
Copy link
Contributor

This should be fixed in v1.6.1!

@nonchan7720
Copy link
Author

Thank you!
If I have any problems I will let you know👍

@jerbob92
Copy link
Contributor

What I do want to add:
You seem to be mixing pixel sizes (from FPDFImageObj_GetImagePixelSize) with point sizes (in the matrix and FPDFPage_New). This should work, but it will make a very big PDF (in terms of inches), and if you want to add anything else to the page it might give you some issues.

@nonchan7720
Copy link
Author

I see, thanks.
I was referring to this.
https://github.com/pypdfium2-team/pypdfium2

@jerbob92
Copy link
Contributor

Ah I see, yes that example has the same issue.

Basically it just makes the page the same size in points (inches) as the image is in pixels. Normally you would have something like 72 dots (pixels) per inch. I think they just make them the same to make the example very easy to use/read, but it might look a little odd if you mix it with normally sized pages and/or add other things to the same page.

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

Successfully merging a pull request may close this issue.

2 participants