diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/ClassificationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/ClassificationService.java index 4362a97f..13f3d366 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/ClassificationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/ClassificationService.java @@ -1,5 +1,6 @@ package com.iqser.red.service.redaction.v1.server.classification.service; +import com.iqser.red.service.redaction.v1.model.Point; import com.iqser.red.service.redaction.v1.server.classification.model.Document; import com.iqser.red.service.redaction.v1.server.classification.model.Orientation; import com.iqser.red.service.redaction.v1.server.classification.model.Page; @@ -12,6 +13,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; import java.util.List; import java.util.Locale; import java.util.regex.Matcher; @@ -36,12 +39,49 @@ public class ClassificationService { for (Page page : document.getPages()) { Rectangle btf = page.isLandscape() ? landscapeBodyTextFrame : bodyTextFrame; + +// if (page.getRotation() == 180 || page.getRotation() == 270){ +// var nBtf = getRectangle(btf.x, btf.y, btf.width, btf.height, page.getRotation(),((TextBlock) page.getTextBlocks().get(0)).getSequences().get(0).getPageWidth(),((TextBlock) page.getTextBlocks().get(0)).getSequences().get(0).getPageHeight()); +// btf = new Rectangle(nBtf.getTopLeft().getX(), nBtf.getTopLeft().getY(), nBtf.getWidth(), nBtf.getHeight()); +// } + page.setBodyTextFrame(btf); classifyPage(btf, page, document, headlineFontSizes); } } + + public com.iqser.red.service.redaction.v1.model.Rectangle getRectangle(float x, float y, float width, float height, int rotation, float pageWidth, float pageHeight) { + + + Point2D bottomLeft = new Point2D.Double(x, pageHeight - y); + Point2D topRight = new Point2D.Double(x + width,pageHeight - y - height); + + AffineTransform transform = new AffineTransform(); + if (rotation == 0 || rotation == 180) { + transform.rotate(Math.toRadians(rotation), pageWidth / 2f, pageHeight / 2f); + transform.translate(0f, pageHeight); + transform.scale(1., -1.); + } else if (rotation == 90) { + transform.rotate(Math.toRadians(rotation), pageWidth / 2f, pageWidth / 2f); + transform.translate(0f, pageWidth); + transform.scale(1., -1.); + } else { + transform.rotate(Math.toRadians(rotation), pageHeight / 2f, pageHeight / 2f); + transform.translate(0f, pageWidth); + transform.scale(1., -1.); + } + + bottomLeft = transform.transform(bottomLeft, null); + topRight = transform.transform(topRight, null); + + return new com.iqser.red.service.redaction.v1.model.Rectangle( // + new Point((float) bottomLeft.getX(), (float) bottomLeft.getY()), (float) (topRight.getX() - bottomLeft.getX()), (float) (topRight.getY() - bottomLeft.getY()), 0); + } + + + public void classifyPage(Rectangle bodyTextFrame, Page page, Document document, List headlineFontSizes) { for (AbstractTextContainer textBlock : page.getTextBlocks()) { @@ -92,7 +132,7 @@ public class ClassificationService { document.setHeadlines(true); } - else if (PositionUtils.isOverBodyTextFrame(bodyTextFrame, textBlock, page.isRotated()) && (document.getFontSizeCounter() + else if (PositionUtils.isOverBodyTextFrame(bodyTextFrame, textBlock) && (document.getFontSizeCounter() .getMostPopular() == null || textBlock.getHighestFontSize() <= document.getFontSizeCounter() .getMostPopular())) { textBlock.setClassification("Header"); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/PositionUtils.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/PositionUtils.java index 98117bbe..bc71dbbd 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/PositionUtils.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/PositionUtils.java @@ -31,16 +31,16 @@ public class PositionUtils { } - public boolean isOverBodyTextFrame(Rectangle btf, TextBlock textBlock, boolean rotated) { + public boolean isOverBodyTextFrame(Rectangle btf, TextBlock textBlock) { if (btf == null || textBlock == null) { return false; } - if (rotated && textBlock.getMinX() < btf.getX()) { + if ((textBlock.getRotation() == 0 || textBlock.getRotation() == 180) && textBlock.getMinX() < btf.getX()) { // Its very strange, P{0,0} is on top left in this case, instead of lower left. return true; - } else if (!rotated && textBlock.getMinY() > btf.getY() + btf.getHeight()) { + } else if ((textBlock.getRotation() == 90 || textBlock.getRotation() == 270) && textBlock.getMinY() > btf.getY() + btf.getHeight()) { return true; } else { return false; @@ -89,6 +89,9 @@ public class PositionUtils { public Float getApproxLineCount(TextBlock textBlock) { + +// float height = textBlock.getRotation() == 0 || textBlock.getRotation() == 180 ? textBlock.getHeight() : textBlock.getWidth(); + return textBlock.getHeight() / textBlock.getMostPopularWordHeight(); } } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/segmentation/PdfSegmentationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/segmentation/PdfSegmentationService.java index c9fad942..ea13b605 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/segmentation/PdfSegmentationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/segmentation/PdfSegmentationService.java @@ -93,9 +93,11 @@ public class PdfSegmentationService { stripper.getText(pdDocument); PDRectangle pdr = pdPage.getMediaBox(); - boolean isLandscape = pdr.getWidth() > pdr.getHeight(); - int rotation = pdPage.getRotation(); + boolean isLandscape = pdr.getWidth() > pdr.getHeight() && (rotation == 0 || rotation == 180) || + pdr.getHeight() > pdr.getWidth() && (rotation == 90 || rotation == 270); + + System.out.println("PageNr: " + pageNumber + " rotation: "+rotation); @@ -125,7 +127,7 @@ public class PdfSegmentationService { page.setCropBoxArea(cropboxArea); page.setRotation(rotation); - page.setLandscape(isLandscape || isRotated); + page.setLandscape(isLandscape); page.setPageNumber(pageNumber); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/PdfVisualisationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/PdfVisualisationService.java index 0b0f121f..e0a54b08 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/PdfVisualisationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/PdfVisualisationService.java @@ -1,9 +1,13 @@ package com.iqser.red.service.redaction.v1.server.visualization.service; +import com.iqser.red.service.redaction.v1.model.Point; +import com.iqser.red.service.redaction.v1.model.Rectangle; import com.iqser.red.service.redaction.v1.server.classification.model.Document; import com.iqser.red.service.redaction.v1.server.classification.model.Page; import com.iqser.red.service.redaction.v1.server.classification.model.Paragraph; import com.iqser.red.service.redaction.v1.server.classification.model.TextBlock; +import com.iqser.red.service.redaction.v1.server.parsing.model.RedTextPosition; +import com.iqser.red.service.redaction.v1.server.parsing.model.TextDirection; import com.iqser.red.service.redaction.v1.server.tableextraction.model.AbstractTextContainer; import com.iqser.red.service.redaction.v1.server.tableextraction.model.Cell; import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table; @@ -16,6 +20,8 @@ import org.apache.pdfbox.pdmodel.font.PDType1Font; import org.springframework.stereotype.Service; import java.awt.Color; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; import java.io.IOException; import java.util.List; @@ -85,7 +91,11 @@ public class PdfVisualisationService { contentStream.setStrokingColor(Color.YELLOW); - contentStream.addRect((float) analyzedPage.getBodyTextFrame().getX(), (float) analyzedPage.getBodyTextFrame().getY(), (float) analyzedPage.getBodyTextFrame().getWidth(), (float) analyzedPage.getBodyTextFrame().getHeight()); + + var rect = getRectangle((float) analyzedPage.getBodyTextFrame().getX(),(float) analyzedPage.getBodyTextFrame().getY(),(float) analyzedPage.getBodyTextFrame().getWidth(), (float) analyzedPage.getBodyTextFrame().getHeight(), pdPage.getRotation(), pdPage.getCropBox().getWidth(), pdPage.getCropBox().getHeight()); + + contentStream.addRect(rect.getTopLeft().getX(), rect.getTopLeft().getY(), rect.getWidth(), rect.getHeight()); + contentStream.stroke(); contentStream.close(); @@ -97,7 +107,9 @@ public class PdfVisualisationService { contentStream.setStrokingColor(Color.RED); - contentStream.addRect(textBlock.getMinX(), textBlock.getMinY(), textBlock.getWidth(), textBlock.getHeight()); + var rect = getRectangle(textBlock.getMinX(), textBlock.getMinY(), textBlock.getWidth(), textBlock.getHeight(), textBlock.getRotation(), textBlock.getSequences().get(0).getPageWidth(), textBlock.getSequences().get(0).getPageHeight()); + + contentStream.addRect(rect.getTopLeft().getX(), rect.getTopLeft().getY(), rect.getWidth(), rect.getHeight()); contentStream.stroke(); if (textBlock.getClassification() != null) { @@ -106,7 +118,7 @@ public class PdfVisualisationService { contentStream.setNonStrokingColor(Color.BLUE); contentStream.setFont(PDType1Font.TIMES_ROMAN, 6f); - contentStream.newLineAtOffset(textBlock.getMinX(), textBlock.getMaxY()); + contentStream.newLineAtOffset(rect.getTopLeft().getX(), rect.getTopLeft().getY()); contentStream.showText(textBlock.getClassification() /*" textBlock.getOrientation() + "--> "*/ + number); @@ -115,6 +127,39 @@ public class PdfVisualisationService { } + + public Rectangle getRectangle(float x, float y, float width, float height, int rotation, float pageWidth, float pageHeight) { + + + Point2D bottomLeft = new Point2D.Double(x, pageHeight - y); + Point2D topRight = new Point2D.Double(x + width,pageHeight - y - height); + + AffineTransform transform = new AffineTransform(); + if (rotation == 0 || rotation == 180) { + transform.rotate(Math.toRadians(rotation), pageWidth / 2f, pageHeight / 2f); + transform.translate(0f, pageHeight); + transform.scale(1., -1.); + } else if (rotation == 90) { + transform.rotate(Math.toRadians(rotation), pageWidth / 2f, pageWidth / 2f); + transform.translate(0f, pageWidth); + transform.scale(1., -1.); + } else { + transform.rotate(Math.toRadians(rotation), pageHeight / 2f, pageHeight / 2f); + transform.translate(0f, pageWidth); + transform.scale(1., -1.); + } + + bottomLeft = transform.transform(bottomLeft, null); + topRight = transform.transform(topRight, null); + + return new Rectangle( // + new Point((float) bottomLeft.getX(), (float) bottomLeft.getY()), (float) (topRight.getX() - bottomLeft.getX()), (float) (topRight.getY() - bottomLeft.getY()), 0); + } + + + + + private void visualizeTable(Table table, PDPageContentStream contentStream) throws IOException { for (List row : table.getRows()) { for (Cell cell : row) { diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java index a4c20fe3..8c882e28 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java +++ b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java @@ -336,7 +336,7 @@ public class RedactionIntegrationTest { System.out.println("Detailed quantitative and qualitative information on the composition of the plant ".length()); - ClassPathResource pdfFileResource = new ClassPathResource("files/Trinexapac/91 Trinexapac-ethyl_RAR_01_Volume_1_2018-02-23.pdf"); + ClassPathResource pdfFileResource = new ClassPathResource("files/Metolachlor/S-Metolachlor_RAR_02_Volume_2_2018-09-06.pdf"); AnalyzeRequest request = prepareStorage(pdfFileResource.getInputStream()); analyzeService.analyzeDocumentStructure(new StructureAnalyzeRequest(request.getDossierId(), request.getFileId())); @@ -1096,7 +1096,7 @@ public class RedactionIntegrationTest { public void classificationTest() throws IOException { System.out.println("classificationTest"); - ClassPathResource pdfFileResource = new ClassPathResource("files/Trinexapac/91 Trinexapac-ethyl_RAR_01_Volume_1_2018-02-23.pdf"); + ClassPathResource pdfFileResource = new ClassPathResource("files/RSS/02 - A22833B - Acute Oral (Up and Down) - Final Report.pdf"); AnalyzeRequest request = prepareStorage(pdfFileResource.getInputStream()); diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/resources/files/RSS/S91.pdf b/redaction-service-v1/redaction-service-server-v1/src/test/resources/files/RSS/S91.pdf new file mode 100644 index 00000000..5b265a96 Binary files /dev/null and b/redaction-service-v1/redaction-service-server-v1/src/test/resources/files/RSS/S91.pdf differ