mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-27 13:48:51 +08:00

* Add render package * Add text state * Add more text operators * Remove unnecessary files * Add text font * Add custom text render method * Improve text rendering method * Rename text state methods * Refactor and document context interface * Refact text begin/end operators * Fix graphics state transformations * Keep original font when doing font substitution * Take page cropbox into account * Revert to substitution font if original font measurement is 0 * Add font substitution package * Implement addition transform.Point methods * Use transform.Point in the image context package * Remove unneeded functionality from the render image package * Fix golint notices in the image rendering package * Fix go vet notices in the render package * Fix golint notices in the top-level render package * Improve render context package documentation * Document context text state struct. * Document context text font struct. * Minor logging improvements * Add license disclaimer to the render package files * Avoid using package aliases where possible * Change style of section comments * Adapt render package import style to follow the developer guide * Improve documentation for the internal matrix implementation * Update render package dependency versions * Apply crop box post render * Account for offseted media boxes * Improve metrics of rendered characters * Fix text matrix translation * Change priority of fonts used for measuring rendered characters * Skip invalid m and l operators on image rendering * Small fix for v operator * Fix rendered characters spacing issues * Refactor naming of internal render packages
107 lines
2.4 KiB
Go
107 lines
2.4 KiB
Go
/*
|
|
* This file is subject to the terms and conditions defined in
|
|
* file 'LICENSE.md', which is part of this source code package.
|
|
*/
|
|
|
|
package render
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"image"
|
|
"image/draw"
|
|
"image/jpeg"
|
|
"image/png"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/unidoc/unipdf/v3/model"
|
|
"github.com/unidoc/unipdf/v3/render/internal/context/imagerender"
|
|
)
|
|
|
|
// ImageDevice is used to render PDF pages to image targets.
|
|
type ImageDevice struct {
|
|
renderer
|
|
}
|
|
|
|
// NewImageDevice returns a new image device.
|
|
func NewImageDevice() *ImageDevice {
|
|
return &ImageDevice{}
|
|
}
|
|
|
|
// Render converts the specified PDF page into an image and returns the result.
|
|
func (d *ImageDevice) Render(page *model.PdfPage) (image.Image, error) {
|
|
// Get page dimensions.
|
|
mbox, err := page.GetMediaBox()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Render page.
|
|
width, height := mbox.Llx+mbox.Width(), mbox.Lly+mbox.Height()
|
|
|
|
ctx := imagerender.NewContext(int(width), int(height))
|
|
if err := d.renderPage(ctx, page); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Apply crop box, if one exists.
|
|
img := ctx.Image()
|
|
if box := page.CropBox; box != nil {
|
|
// Calculate crop bounds and crop start position.
|
|
cropBounds := image.Rect(0, 0, int(box.Width()), int(box.Height()))
|
|
cropStart := image.Pt(int(box.Llx), int(height-box.Ury))
|
|
|
|
// Crop image.
|
|
cropImg := image.NewRGBA(cropBounds)
|
|
draw.Draw(cropImg, cropBounds, img, cropStart, draw.Src)
|
|
img = cropImg
|
|
}
|
|
|
|
return img, nil
|
|
}
|
|
|
|
// RenderToPath converts the specified PDF page into an image and saves the
|
|
// result at the specified location.
|
|
func (d *ImageDevice) RenderToPath(page *model.PdfPage, outputPath string) error {
|
|
image, err := d.Render(page)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
extension := strings.ToLower(filepath.Ext(outputPath))
|
|
if extension == "" {
|
|
return errors.New("could not recognize output file type")
|
|
}
|
|
|
|
switch extension {
|
|
case ".png":
|
|
return savePNG(outputPath, image)
|
|
case ".jpg", ".jpeg":
|
|
return saveJPG(outputPath, image, 100)
|
|
}
|
|
|
|
return fmt.Errorf("unrecognized output file type: %s", extension)
|
|
}
|
|
|
|
func savePNG(path string, image image.Image) error {
|
|
file, err := os.Create(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
|
|
return png.Encode(file, image)
|
|
}
|
|
|
|
func saveJPG(path string, image image.Image, quality int) error {
|
|
file, err := os.Create(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
|
|
return jpeg.Encode(file, image, &jpeg.Options{Quality: quality})
|
|
}
|