Files
mesh-catalog/modules/brother/cmd/brother/pdf.go
T

52 lines
1.9 KiB
Go

package main
import (
"bytes"
"fmt"
"image/color"
"image/jpeg"
)
// PDF writes a one-page PDF holding the JPEG as it is (DCTDecode), the page as large as the image really is:
// pixels over dpi, in points (72 to the inch).
func PDF(jpegBytes []byte, dpi int) ([]byte, error) {
if dpi <= 0 {
return nil, fmt.Errorf("resolution %d dpi is no resolution", dpi)
}
cfg, err := jpeg.DecodeConfig(bytes.NewReader(jpegBytes))
if err != nil {
return nil, fmt.Errorf("the image cannot be read: %w", err)
}
space := "DeviceRGB"
if cfg.ColorModel == color.GrayModel {
space = "DeviceGray"
}
wpt := float64(cfg.Width) / float64(dpi) * 72
hpt := float64(cfg.Height) / float64(dpi) * 72
content := fmt.Sprintf("q %.2f 0 0 %.2f 0 0 cm /Im0 Do Q\n", wpt, hpt)
var b bytes.Buffer
var offsets []int
obj := func(body string) {
offsets = append(offsets, b.Len())
fmt.Fprintf(&b, "%d 0 obj\n%s\nendobj\n", len(offsets), body)
}
b.WriteString("%PDF-1.4\n%\xE2\xE3\xCF\xD3\n")
obj("<< /Type /Catalog /Pages 2 0 R >>")
obj("<< /Type /Pages /Kids [3 0 R] /Count 1 >>")
obj(fmt.Sprintf("<< /Type /Page /Parent 2 0 R /MediaBox [0 0 %.2f %.2f] /Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>", wpt, hpt))
offsets = append(offsets, b.Len())
fmt.Fprintf(&b, "4 0 obj\n<< /Type /XObject /Subtype /Image /Width %d /Height %d /ColorSpace /%s /BitsPerComponent 8 /Filter /DCTDecode /Length %d >>\nstream\n",
cfg.Width, cfg.Height, space, len(jpegBytes))
b.Write(jpegBytes)
b.WriteString("\nendstream\nendobj\n")
obj(fmt.Sprintf("<< /Length %d >>\nstream\n%sendstream", len(content), content))
xref := b.Len()
fmt.Fprintf(&b, "xref\n0 %d\n0000000000 65535 f \n", len(offsets)+1)
for _, o := range offsets {
fmt.Fprintf(&b, "%010d 00000 n \n", o)
}
fmt.Fprintf(&b, "trailer\n<< /Size %d /Root 1 0 R >>\nstartxref\n%d\n%%%%EOF\n", len(offsets)+1, xref)
return b.Bytes(), nil
}