mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-03 05:10:16 +03:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e281e479a1 |
@@ -1,7 +1,10 @@
|
||||
package stirling.software.common.pdf;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -9,6 +12,10 @@ import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.jpdfium.PdfDocument;
|
||||
import stirling.software.jpdfium.PdfPage;
|
||||
import stirling.software.jpdfium.doc.ExtractedImage;
|
||||
@@ -30,6 +37,7 @@ import stirling.software.jpdfium.text.TextWord;
|
||||
* bullets) back into the line they belong to. Column layout and tables are derived from line/word
|
||||
* geometry directly.
|
||||
*/
|
||||
@Slf4j
|
||||
public class PdfMarkdownConverter {
|
||||
|
||||
private static final Pattern SOFT_HYPHEN = Pattern.compile("(\\w+)-\\n([a-z])");
|
||||
@@ -38,6 +46,10 @@ public class PdfMarkdownConverter {
|
||||
private static final float GLYPH_WIDTH = 7.5f;
|
||||
|
||||
public String convert(PdfDocument doc) throws IOException {
|
||||
return convert(doc, false);
|
||||
}
|
||||
|
||||
public String convert(PdfDocument doc, boolean includeImages) throws IOException {
|
||||
List<PageText> allPageText = PdfTextExtractor.extractAll(doc);
|
||||
float medianSize = HeadingDetector.medianFontSize(allPageText);
|
||||
float medianHeight = HeadingDetector.medianLineHeight(allPageText);
|
||||
@@ -60,7 +72,7 @@ public class PdfMarkdownConverter {
|
||||
// their host lines so paragraph assembly sees faithful, complete lines.
|
||||
List<Line> lines = stitchGlyphs(rawLines);
|
||||
if (lines.isEmpty()) {
|
||||
emitImages(doc, pageIndex, output);
|
||||
emitImages(doc, pageIndex, output, includeImages);
|
||||
prevPageTrailingTableHeader = null;
|
||||
continue;
|
||||
}
|
||||
@@ -138,7 +150,7 @@ public class PdfMarkdownConverter {
|
||||
}
|
||||
}
|
||||
|
||||
emitImages(doc, pageIndex, pageItems);
|
||||
emitImages(doc, pageIndex, pageItems, includeImages);
|
||||
|
||||
if (pageItems.isEmpty()) {
|
||||
continue;
|
||||
@@ -853,17 +865,34 @@ public class PdfMarkdownConverter {
|
||||
|
||||
// --- Page-level emission helpers ---------------------------------------
|
||||
|
||||
private static void emitImages(PdfDocument doc, int pageIndex, List<Object> pageItems)
|
||||
private static void emitImages(
|
||||
PdfDocument doc, int pageIndex, List<Object> pageItems, boolean includeImages)
|
||||
throws IOException {
|
||||
try (PdfPage page = doc.page(pageIndex)) {
|
||||
List<ExtractedImage> images =
|
||||
PdfImageExtractor.extract(page.rawDocHandle(), page.rawHandle(), pageIndex);
|
||||
for (ExtractedImage img : images) {
|
||||
pageItems.add(describeImage(img));
|
||||
pageItems.add(includeImages ? embedImage(img) : describeImage(img));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String embedImage(ExtractedImage img) {
|
||||
try {
|
||||
BufferedImage buffered = img.toBufferedImage();
|
||||
if (buffered != null) {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
if (ImageIO.write(buffered, "png", out)) {
|
||||
String data = Base64.getEncoder().encodeToString(out.toByteArray());
|
||||
return "";
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to embed image, using placeholder instead: {}", e.getMessage());
|
||||
}
|
||||
return describeImage(img);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an image placeholder annotated with whatever metadata JPDFium exposes: pixel
|
||||
* dimensions, on-page placement (points), effective DPI, encoded format, colour space and bit
|
||||
|
||||
+3
-4
@@ -16,7 +16,6 @@ import stirling.software.SPDF.config.swagger.MarkdownConversionResponse;
|
||||
import stirling.software.common.annotations.AutoJobPostMapping;
|
||||
import stirling.software.common.annotations.api.ConvertApi;
|
||||
import stirling.software.common.enumeration.ResourceWeight;
|
||||
import stirling.software.common.model.api.PDFFile;
|
||||
import stirling.software.common.pdf.PdfMarkdownConverter;
|
||||
import stirling.software.common.util.TempFile;
|
||||
import stirling.software.common.util.TempFileManager;
|
||||
@@ -38,9 +37,9 @@ public class ConvertPDFToMarkdown {
|
||||
summary = "Convert PDF to Markdown",
|
||||
description =
|
||||
"This endpoint converts a PDF file to Markdown format. Input:PDF Output:Markdown Type:SISO")
|
||||
public ResponseEntity<byte[]> processPdfToMarkdown(@ModelAttribute PDFFile file)
|
||||
public ResponseEntity<byte[]> processPdfToMarkdown(@ModelAttribute PdfToMarkdownRequest request)
|
||||
throws Exception {
|
||||
MultipartFile inputFile = file.getFileInput();
|
||||
MultipartFile inputFile = request.getFileInput();
|
||||
|
||||
String originalName = Filenames.toSimpleFileName(inputFile.getOriginalFilename());
|
||||
String baseName =
|
||||
@@ -52,7 +51,7 @@ public class ConvertPDFToMarkdown {
|
||||
try (TempFile tempInput = new TempFile(tempFileManager, ".pdf")) {
|
||||
inputFile.transferTo(tempInput.getFile());
|
||||
try (PdfDocument doc = PdfDocument.open(tempInput.getPath())) {
|
||||
markdown = new PdfMarkdownConverter().convert(doc);
|
||||
markdown = new PdfMarkdownConverter().convert(doc, request.isIncludeImages());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package stirling.software.SPDF.model.api.converters;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import stirling.software.common.model.api.PDFFile;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PdfToMarkdownRequest extends PDFFile {
|
||||
|
||||
@Schema(
|
||||
description = "Embed images from the PDF as base64 data URIs in the Markdown output",
|
||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
|
||||
example = "false")
|
||||
private boolean includeImages = false;
|
||||
}
|
||||
Reference in New Issue
Block a user