Skip to content

Commit

Permalink
Merge pull request #61 from klippa-app/feature/fix-jpg-background
Browse files Browse the repository at this point in the history
Fix background on JPG rendering
  • Loading branch information
jerbob92 authored Sep 22, 2022
2 parents cf3590f + 9945dae commit 618cc01
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 5 deletions.
47 changes: 42 additions & 5 deletions internal/implementation/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"errors"
"fmt"
"image"
"image/color"
"image/draw"
"image/jpeg"
"image/png"
"io/ioutil"
Expand Down Expand Up @@ -328,11 +330,12 @@ func (p *PdfiumImplementation) renderPages(pages []renderPage, padding int) (*re
X: 0,
Y: currentOffset,
}
index, err := p.renderPage(bitmap, pages[i].Page, pages[i].Width, pages[i].Height, currentOffset, pages[i].Flags)
index, hasTransparency, err := p.renderPage(bitmap, pages[i].Page, pages[i].Width, pages[i].Height, currentOffset, pages[i].Flags)
if err != nil {
return nil, err
}
pagesInfo[i].Page = index
pagesInfo[i].HasTransparency = hasTransparency
currentOffset += pages[i].Height + padding
}

Expand All @@ -349,19 +352,21 @@ func (p *PdfiumImplementation) renderPages(pages []renderPage, padding int) (*re
}

// renderPage renders a specific page in a specific size on a bitmap.
func (p *PdfiumImplementation) renderPage(bitmap C.FPDF_BITMAP, page requests.Page, width, height, offset int, flags enums.FPDF_RENDER_FLAG) (int, error) {
func (p *PdfiumImplementation) renderPage(bitmap C.FPDF_BITMAP, page requests.Page, width, height, offset int, flags enums.FPDF_RENDER_FLAG) (int, bool, error) {
pageHandle, err := p.loadPage(page)
if err != nil {
return 0, err
return 0, false, err
}

alpha := C.FPDFPage_HasTransparency(pageHandle.handle)

// White
fillColor := 0xFFFFFFFF

hasTransparency := int(alpha) == 1

// When the page has transparency, fill with black, not white.
if int(alpha) == 1 {
if hasTransparency {
// Black
fillColor = 0x00000000
}
Expand All @@ -373,20 +378,23 @@ func (p *PdfiumImplementation) renderPage(bitmap C.FPDF_BITMAP, page requests.Pa
// in reverse order so that BGRA becomes RGBA.
C.FPDF_RenderPageBitmap(bitmap, pageHandle.handle, 0, C.int(offset), C.int(width), C.int(height), 0, C.int(flags)|C.FPDF_REVERSE_BYTE_ORDER)

return pageHandle.index, nil
return pageHandle.index, hasTransparency, nil
}

func (p *PdfiumImplementation) RenderToFile(request *requests.RenderToFile) (*responses.RenderToFile, error) {
var renderedImage *image.RGBA

var myResp *responses.RenderToFile
hasTransparency := false

if request.RenderPageInDPI != nil {
resp, err := p.RenderPageInDPI(request.RenderPageInDPI)
if err != nil {
return nil, err
}

renderedImage = resp.Result.Image
hasTransparency = resp.Result.HasTransparency
myResp = &responses.RenderToFile{
Width: resp.Result.Width,
Height: resp.Result.Height,
Expand All @@ -399,6 +407,7 @@ func (p *PdfiumImplementation) RenderToFile(request *requests.RenderToFile) (*re
Height: resp.Result.Image.Bounds().Max.Y,
X: 0,
Y: 0,
HasTransparency: resp.Result.HasTransparency,
},
},
}
Expand All @@ -409,6 +418,13 @@ func (p *PdfiumImplementation) RenderToFile(request *requests.RenderToFile) (*re
}

renderedImage = resp.Result.Image

for _, page := range resp.Result.Pages {
if page.HasTransparency {
hasTransparency = true
}
}

myResp = &responses.RenderToFile{
Width: resp.Result.Width,
Height: resp.Result.Height,
Expand All @@ -421,6 +437,7 @@ func (p *PdfiumImplementation) RenderToFile(request *requests.RenderToFile) (*re
}

renderedImage = resp.Result.Image
hasTransparency = resp.Result.HasTransparency
myResp = &responses.RenderToFile{
Width: resp.Result.Width,
Height: resp.Result.Height,
Expand All @@ -433,6 +450,7 @@ func (p *PdfiumImplementation) RenderToFile(request *requests.RenderToFile) (*re
Height: resp.Result.Image.Bounds().Max.Y,
X: 0,
Y: 0,
HasTransparency: resp.Result.HasTransparency,
},
},
}
Expand All @@ -443,6 +461,13 @@ func (p *PdfiumImplementation) RenderToFile(request *requests.RenderToFile) (*re
}

renderedImage = resp.Result.Image

for _, page := range resp.Result.Pages {
if page.HasTransparency {
hasTransparency = true
}
}

myResp = &responses.RenderToFile{
Width: resp.Result.Width,
Height: resp.Result.Height,
Expand All @@ -458,6 +483,18 @@ func (p *PdfiumImplementation) RenderToFile(request *requests.RenderToFile) (*re
var opt jpeg.Options
opt.Quality = 95

// If any of the pages have transparency, place a white background under
// the image. When you render a JPG image in Go, it will make the transparent
// background black. With the added background we make sure that the
// rendered PDF will look the same as in a PDF viewer, those generally
// have a white background on the page viewer.
if hasTransparency {
imageWithWhiteBackground := image.NewRGBA(renderedImage.Bounds())
draw.Draw(imageWithWhiteBackground, imageWithWhiteBackground.Bounds(), image.NewUniform(color.White), image.Point{}, draw.Src)
draw.Draw(imageWithWhiteBackground, imageWithWhiteBackground.Bounds(), renderedImage, renderedImage.Bounds().Min, draw.Over)
renderedImage = imageWithWhiteBackground
}

for {
err := jpeg.Encode(&imgBuf, renderedImage, &opt)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions responses/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type RenderPage struct {
Image *image.RGBA // The rendered image.
Width int // The width of the rendered image.
Height int // The height of the rendered image.
HasTransparency bool // Whether the page has transparency.
}

type RenderPagesPage struct {
Expand All @@ -19,6 +20,7 @@ type RenderPagesPage struct {
Height int // The height of the rendered page inside the image.
X int // The X start position of this page inside the image.
Y int // The Y start position of this page inside the image.
HasTransparency bool // Whether the page has transparency.
}

type RenderPages struct {
Expand Down

0 comments on commit 618cc01

Please sign in to comment.