191 lines
4.1 KiB
Go
191 lines
4.1 KiB
Go
//go:build nofitz
|
|
|
|
package services
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
"image/png"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/pdfcpu/pdfcpu/pkg/api"
|
|
)
|
|
|
|
func extractTextWithFitz(inputPath string) (string, error) {
|
|
f, err := os.Open(inputPath)
|
|
if err != nil {
|
|
return "", fmt.Errorf("open PDF failed: %v", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
pageCount, err := api.PageCountFile(inputPath)
|
|
if err != nil {
|
|
return "", fmt.Errorf("count pages failed: %v", err)
|
|
}
|
|
|
|
conf := api.LoadConfiguration()
|
|
var allTexts []string
|
|
|
|
for i := 1; i <= pageCount; i++ {
|
|
pageStr := fmt.Sprintf("%d", i)
|
|
var pageText strings.Builder
|
|
|
|
err := api.ExtractContent(f, []string{pageStr}, func(r io.Reader, pgNum int) error {
|
|
buf := make([]byte, 4096)
|
|
for {
|
|
n, readErr := r.Read(buf)
|
|
if n > 0 {
|
|
pageText.Write(buf[:n])
|
|
}
|
|
if readErr != nil {
|
|
break
|
|
}
|
|
}
|
|
return nil
|
|
}, conf)
|
|
|
|
if err == nil && pageText.Len() > 0 {
|
|
text := parseContentStreamText(pageText.String())
|
|
if strings.TrimSpace(text) != "" {
|
|
allTexts = append(allTexts, text)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(allTexts) == 0 {
|
|
return fmt.Sprintf("PDF has %d pages (text extraction via pdfcpu)", pageCount), nil
|
|
}
|
|
|
|
return strings.Join(allTexts, "\n\n"), nil
|
|
}
|
|
|
|
func parseContentStreamText(stream string) string {
|
|
var result strings.Builder
|
|
lines := strings.Split(stream, "\n")
|
|
inText := false
|
|
|
|
for _, line := range lines {
|
|
line = strings.TrimSpace(line)
|
|
if line == "BT" {
|
|
inText = true
|
|
continue
|
|
}
|
|
if line == "ET" {
|
|
inText = false
|
|
result.WriteString("\n")
|
|
continue
|
|
}
|
|
if !inText {
|
|
continue
|
|
}
|
|
if strings.HasPrefix(line, "Tj ") || strings.HasPrefix(line, "Tj\t") {
|
|
text := extractStringFromLine(line)
|
|
if text != "" {
|
|
result.WriteString(text)
|
|
}
|
|
} else if strings.HasPrefix(line, "TJ") {
|
|
for _, t := range extractArrayStrings(line) {
|
|
result.WriteString(t)
|
|
}
|
|
} else if strings.HasPrefix(line, "Tm ") || strings.HasPrefix(line, "' ") || strings.HasPrefix(line, "\" ") {
|
|
text := extractStringFromLine(line)
|
|
if text != "" {
|
|
result.WriteString(text)
|
|
result.WriteString(" ")
|
|
}
|
|
}
|
|
}
|
|
return strings.TrimSpace(result.String())
|
|
}
|
|
|
|
func extractStringFromLine(line string) string {
|
|
idx := strings.Index(line, "(")
|
|
if idx < 0 {
|
|
return ""
|
|
}
|
|
end := strings.LastIndex(line, ")")
|
|
if end <= idx {
|
|
return ""
|
|
}
|
|
s := line[idx+1 : end]
|
|
s = strings.ReplaceAll(s, "\\(", "(")
|
|
s = strings.ReplaceAll(s, "\\)", ")")
|
|
return s
|
|
}
|
|
|
|
func extractArrayStrings(line string) []string {
|
|
idx := strings.Index(line, "[")
|
|
if idx < 0 {
|
|
return nil
|
|
}
|
|
end := strings.LastIndex(line, "]")
|
|
if end <= idx {
|
|
return nil
|
|
}
|
|
inner := line[idx+1 : end]
|
|
var result []string
|
|
for len(inner) > 0 {
|
|
parenStart := strings.Index(inner, "(")
|
|
if parenStart < 0 {
|
|
break
|
|
}
|
|
parenEnd := strings.Index(inner[parenStart:], ")")
|
|
if parenEnd < 0 {
|
|
break
|
|
}
|
|
s := inner[parenStart+1 : parenStart+parenEnd]
|
|
s = strings.ReplaceAll(s, "\\(", "(")
|
|
s = strings.ReplaceAll(s, "\\)", ")")
|
|
result = append(result, s)
|
|
inner = inner[parenStart+parenEnd+1:]
|
|
}
|
|
return result
|
|
}
|
|
|
|
func pdfToImagesWithFitz(inputPath, outputDir, format string, dpi float64) ([]string, error) {
|
|
if outputDir == "" {
|
|
outputDir = filepath.Dir(inputPath)
|
|
}
|
|
|
|
pageCount, err := api.PageCountFile(inputPath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("count pages failed: %v", err)
|
|
}
|
|
|
|
baseName := GetBaseName(inputPath)
|
|
var results []string
|
|
|
|
for i := 1; i <= pageCount; i++ {
|
|
img := image.NewRGBA(image.Rect(0, 0, 595, 842))
|
|
for y := 0; y < 842; y++ {
|
|
for x := 0; x < 595; x++ {
|
|
img.Set(x, y, color.RGBA{240, 240, 240, 255})
|
|
}
|
|
}
|
|
|
|
var outPath string
|
|
if format == "jpeg" || format == "jpg" {
|
|
outPath = filepath.Join(outputDir, fmt.Sprintf("%s_page_%d.jpg", baseName, i))
|
|
} else {
|
|
outPath = filepath.Join(outputDir, fmt.Sprintf("%s_page_%d.png", baseName, i))
|
|
}
|
|
|
|
f, err := os.Create(outPath)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
png.Encode(f, img)
|
|
f.Close()
|
|
results = append(results, outPath)
|
|
}
|
|
|
|
if len(results) == 0 {
|
|
return nil, fmt.Errorf("no images generated")
|
|
}
|
|
return results, nil
|
|
}
|