diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/Page.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/Page.java index 2cc88f86..333d1539 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/Page.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/Page.java @@ -34,8 +34,8 @@ public class Page { private StringFrequencyCounter fontCounter = new StringFrequencyCounter(); private StringFrequencyCounter fontStyleCounter = new StringFrequencyCounter(); - private double cropBoxArea; - private PDRectangle cropBox; + private float pageWidth; + private float pageHeight; public boolean isRotated() { diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/TextBlock.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/TextBlock.java index e74f5ec3..6c4b79e1 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/TextBlock.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/TextBlock.java @@ -51,7 +51,7 @@ public class TextBlock extends AbstractTextContainer { private String classification; - private TextDirection getDir() { + public TextDirection getDir() { return sequences.get(0).getDir(); } @@ -69,9 +69,19 @@ public class TextBlock extends AbstractTextContainer { } + /** + * Returns the minX value in pdf coordinate system. + * Note: This needs to use Pdf Coordinate System where {0,0} rotated with the page rotation. + * 0 -> LowerLeft + * 90 -> UpperLeft + * 180 -> UpperRight + * 270 -> LowerRight + * + * @return the minX value in pdf coordinate system + */ @JsonIgnore @JsonAttribute(ignore = true) - public float getX1() { + public float getPdfMinX() { if (getDir().getDegrees() == 90) { return minY; @@ -86,10 +96,19 @@ public class TextBlock extends AbstractTextContainer { } } - + /** + * Returns the maxX value in pdf coordinate system. + * Note: This needs to use Pdf Coordinate System where {0,0} rotated with the page rotation. + * 0 -> LowerLeft + * 90 -> UpperLeft + * 180 -> UpperRight + * 270 -> LowerRight + * + * @return the maxX value in pdf coordinate system + */ @JsonIgnore @JsonAttribute(ignore = true) - public float getX2() { + public float getPdfMaxX() { if (getDir().getDegrees() == 90) { return maxY; @@ -104,9 +123,19 @@ public class TextBlock extends AbstractTextContainer { } + /** + * Returns the minY value in pdf coordinate system. + * Note: This needs to use Pdf Coordinate System where {0,0} rotated with the page rotation. + * 0 -> LowerLeft + * 90 -> UpperLeft + * 180 -> UpperRight + * 270 -> LowerRight + * + * @return the minY value in pdf coordinate system + */ @JsonIgnore @JsonAttribute(ignore = true) - public float getY1() { + public float getPdfMinY() { if (getDir().getDegrees() == 90) { return minX; @@ -122,9 +151,19 @@ public class TextBlock extends AbstractTextContainer { } + /** + * Returns the maxY value in pdf coordinate system. + * Note: This needs to use Pdf Coordinate System where {0,0} rotated with the page rotation. + * 0 -> LowerLeft + * 90 -> UpperLeft + * 180 -> UpperRight + * 270 -> LowerRight + * + * @return the maxY value in pdf coordinate system + */ @JsonIgnore @JsonAttribute(ignore = true) - public float getY2() { + public float getPdfMaxY() { if (getDir().getDegrees() == 90) { return maxX; @@ -186,17 +225,17 @@ public class TextBlock extends AbstractTextContainer { public void add(TextPositionSequence r) { - if (r.getX1() < minX) { - minX = r.getX1(); + if (r.getMinXDirAdj() < minX) { + minX = r.getMinXDirAdj(); } - if (r.getX2() > maxX) { - maxX = r.getX2(); + if (r.getMaxXDirAdj() > maxX) { + maxX = r.getMaxXDirAdj(); } - if (r.getY1() < minY) { - minY = r.getY1(); + if (r.getMinYDirAdj() < minY) { + minY = r.getMinYDirAdj(); } - if (r.getY2() > maxY) { - maxY = r.getY2(); + if (r.getMaxYDirAdj() > maxY) { + maxY = r.getMaxYDirAdj(); } } @@ -251,7 +290,7 @@ public class TextBlock extends AbstractTextContainer { TextPositionSequence previous = null; for (TextPositionSequence word : sequences) { if (previous != null) { - if (Math.abs(previous.getRotationAdjustedY() - word.getRotationAdjustedY()) > word.getTextHeight()) { + if (Math.abs(previous.getMaxYDirAdj() - word.getMaxYDirAdj()) > word.getTextHeight()) { sb.append('\n'); } else { sb.append(' '); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/BlockificationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/BlockificationService.java index c7b49080..028be48b 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/BlockificationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/BlockificationService.java @@ -7,23 +7,17 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; -import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.springframework.stereotype.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.FloatFrequencyCounter; import com.iqser.red.service.redaction.v1.server.classification.model.Orientation; import com.iqser.red.service.redaction.v1.server.classification.model.Page; import com.iqser.red.service.redaction.v1.server.classification.model.StringFrequencyCounter; import com.iqser.red.service.redaction.v1.server.classification.model.TextBlock; -import com.iqser.red.service.redaction.v1.server.classification.utils.CoordSystemHelper; -import com.iqser.red.service.redaction.v1.server.classification.utils.PositionUtils; +import com.iqser.red.service.redaction.v1.server.classification.utils.RulingTextDirAdjustUtil; import com.iqser.red.service.redaction.v1.server.parsing.model.TextPositionSequence; 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.Ruling; -import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table; @Service @SuppressWarnings("all") @@ -32,9 +26,16 @@ public class BlockificationService { static final float THRESHOLD = 1f; - public Page blockify(List textPositions, List horizontalRulingLines, List verticalRulingLines, int rotation, PDRectangle cropbox) { - -// sortRotatedSequences(textPositions); + /** + * This method is building blocks by expanding the minX/maxX and minY/maxY value on each word that is not split by the conditions. + * This method must use text direction adjusted postions (DirAdj). Where {0,0} is on the upper left. Never try to change this! + * Rulings (Table lines) must be adjusted to the text directions as well, when checking if a block is split by a ruling. + * @param textPositions The words of a page. + * @param horizontalRulingLines Horizontal table lines. + * @param verticalRulingLines Vertical table lines. + * @return Page object that contains the Textblock and text statistics. + */ + public Page blockify(List textPositions, List horizontalRulingLines, List verticalRulingLines) { List chunkWords = new ArrayList<>(); List chunkBlockList1 = new ArrayList<>(); @@ -46,45 +47,15 @@ public class BlockificationService { Float splitX1 = null; for (TextPositionSequence word : textPositions) { - boolean lineSeparation = word.getY1() - maxY > word.getHeight() * 1.25; - boolean startFromTop = prev != null && word.getY1() < prev.getY1() - prev.getTextHeight(); - boolean splitByX = prev != null && maxX + 50 < word.getX1() && prev.getY1() == word.getY1(); - boolean xIsBeforeFirstX = prev != null && word.getX1() < minX; - boolean newLineAfterSplit = prev != null && word.getY1() != prev.getY1() && wasSplitted && splitX1 != word.getX1(); - boolean splittedByRuling = isSplittedByRuling(maxX, - minY, - word.getX1(), - word.getY1(), - verticalRulingLines, - word.getDir().getDegrees(), - cropbox.getWidth(), - cropbox.getHeight()) || isSplittedByRuling(minX, - minY, - word.getX1(), - word.getY2(), - horizontalRulingLines, - word.getDir().getDegrees(), - cropbox.getWidth(), - cropbox.getHeight()) - - || isSplittedByRuling(maxX, - minY, - word.getX1(), - word.getY1(), - horizontalRulingLines, - word.getDir().getDegrees(), - cropbox.getWidth(), - cropbox.getHeight()) || isSplittedByRuling(minX, - minY, - word.getX1(), - word.getY2(), - verticalRulingLines, - word.getDir().getDegrees(), - cropbox.getWidth(), - cropbox.getHeight()); + boolean lineSeparation = word.getMinYDirAdj() - maxY > word.getHeight() * 1.25; + boolean startFromTop = prev != null && word.getMinYDirAdj() < prev.getMinYDirAdj() - prev.getTextHeight(); + boolean splitByX = prev != null && maxX + 50 < word.getMinXDirAdj() && prev.getMinYDirAdj() == word.getMinYDirAdj(); + boolean xIsBeforeFirstX = prev != null && word.getMinXDirAdj() < minX; + boolean newLineAfterSplit = prev != null && word.getMinYDirAdj() != prev.getMinYDirAdj() && wasSplitted && splitX1 != word.getMinXDirAdj(); + boolean isSpitByRuling = isSpitByRuling(minX, minY, maxX, maxY, word, horizontalRulingLines, verticalRulingLines); boolean splitByDir = prev != null && !prev.getDir().equals(word.getDir()); - if (prev != null && (lineSeparation || startFromTop || splitByX || splitByDir || splittedByRuling)) { + if (prev != null && (lineSeparation || startFromTop || splitByX || splitByDir || isSpitByRuling)) { Orientation prevOrientation = null; if (!chunkBlockList1.isEmpty()) { @@ -95,15 +66,15 @@ public class BlockificationService { chunkBlockList1.add(cb1); chunkWords = new ArrayList<>(); - if (splitByX && !splittedByRuling) { + if (splitByX && !isSpitByRuling) { wasSplitted = true; cb1.setOrientation(Orientation.LEFT); - splitX1 = word.getX1(); - } else if (newLineAfterSplit && !splittedByRuling) { + splitX1 = word.getMinXDirAdj(); + } else if (newLineAfterSplit && !isSpitByRuling) { wasSplitted = false; cb1.setOrientation(Orientation.RIGHT); splitX1 = null; - } else if (prevOrientation != null && prevOrientation.equals(Orientation.RIGHT) && (lineSeparation || !startFromTop || !splitByX || !newLineAfterSplit || !splittedByRuling)) { + } else if (prevOrientation != null && prevOrientation.equals(Orientation.RIGHT) && (lineSeparation || !startFromTop || !splitByX || !newLineAfterSplit || !isSpitByRuling)) { cb1.setOrientation(Orientation.LEFT); } @@ -117,17 +88,17 @@ public class BlockificationService { chunkWords.add(word); prev = word; - if (word.getX1() < minX) { - minX = word.getX1(); + if (word.getMinXDirAdj() < minX) { + minX = word.getMinXDirAdj(); } - if (word.getX2() > maxX) { - maxX = word.getX2(); + if (word.getMaxXDirAdj() > maxX) { + maxX = word.getMaxXDirAdj(); } - if (word.getY1() < minY) { - minY = word.getY1(); + if (word.getMinYDirAdj() < minY) { + minY = word.getMinYDirAdj(); } - if (word.getY2() > maxY) { - maxY = word.getY2(); + if (word.getMaxYDirAdj() > maxY) { + maxY = word.getMaxYDirAdj(); } } @@ -211,7 +182,7 @@ public class BlockificationService { styleFrequencyCounter.add(wordBlock.getFontStyle()); if (textBlock == null) { - textBlock = new TextBlock(wordBlock.getX1(), wordBlock.getX2(), wordBlock.getY1(), wordBlock.getY2(), wordBlockList, wordBlock.getRotation()); + textBlock = new TextBlock(wordBlock.getMinXDirAdj(), wordBlock.getMaxXDirAdj(), wordBlock.getMinYDirAdj(), wordBlock.getMaxYDirAdj(), wordBlockList, wordBlock.getRotation()); } else { TextBlock spatialEntity = textBlock.union(wordBlock); textBlock.resize(spatialEntity.getMinX(), spatialEntity.getMinY(), spatialEntity.getWidth(), spatialEntity.getHeight()); @@ -227,24 +198,57 @@ public class BlockificationService { textBlock.setHighestFontSize(fontSizeFrequencyCounter.getHighest()); } - if (textBlock != null && textBlock.getSequences() != null && textBlock.getSequences().stream().map(t -> round(t.getY1(), 3)).collect(toSet()).size() == 1) { - textBlock.getSequences().sort(Comparator.comparing(TextPositionSequence::getX1)); + if (textBlock != null && textBlock.getSequences() != null && textBlock.getSequences().stream().map(t -> round(t.getMinYDirAdj(), 3)).collect(toSet()).size() == 1) { + textBlock.getSequences().sort(Comparator.comparing(TextPositionSequence::getMinXDirAdj)); } return textBlock; } - private boolean isSplittedByRuling(float previousX2, - float previousY1, - float currentX1, - float currentY1, - List rulingLines, - float rotation, - float pageWidth, - float pageHeight) { + private boolean isSpitByRuling(float minX, + float minY, + float maxX, + float maxY, + TextPositionSequence word, + List horizontalRulingLines, + List verticalRulingLines) { + + return isSplitByRuling(maxX, + minY, + word.getMinXDirAdj(), + word.getMinYDirAdj(), + verticalRulingLines, + word.getDir().getDegrees(), + word.getPageWidth(), + word.getPageHeight()) || isSplitByRuling(minX, + minY, + word.getMinXDirAdj(), + word.getMaxYDirAdj(), + horizontalRulingLines, + word.getDir().getDegrees(), + word.getPageWidth(), + word.getPageHeight()) || isSplitByRuling(maxX, + minY, + word.getMinXDirAdj(), + word.getMinYDirAdj(), + horizontalRulingLines, + word.getDir().getDegrees(), + word.getPageWidth(), + word.getPageHeight()) || isSplitByRuling(minX, + minY, + word.getMinXDirAdj(), + word.getMaxYDirAdj(), + verticalRulingLines, + word.getDir().getDegrees(), + word.getPageWidth(), + word.getPageHeight()); + } + + + private boolean isSplitByRuling(float previousX2, float previousY1, float currentX1, float currentY1, List rulingLines, float dir, float pageWidth, float pageHeight) { for (Ruling ruling : rulingLines) { - var line = CoordSystemHelper.convertToDirAdj(ruling, rotation, pageWidth, pageHeight); + var line = RulingTextDirAdjustUtil.convertToDirAdj(ruling, dir, pageWidth, pageHeight); if (line.intersectsLine(previousX2, previousY1, currentX1, currentY1)) { return true; } @@ -253,114 +257,6 @@ public class BlockificationService { } - public Rectangle calculateBodyTextFrame(List pages, FloatFrequencyCounter documentFontSizeCounter, boolean landscape) { - - float minX = 10000; - float maxX = -100; - float minY = 10000; - float maxY = -100; - - for (Page page : pages) { - - if (page.getTextBlocks().isEmpty() || landscape != page.isLandscape()) { - continue; - } - - for (AbstractTextContainer container : page.getTextBlocks()) { - - if (container instanceof TextBlock) { - TextBlock textBlock = (TextBlock) container; - if (textBlock.getMostPopularWordFont() == null || textBlock.getMostPopularWordStyle() == null) { - continue; - } - - float approxLineCount = PositionUtils.getApproxLineCount(textBlock); - if (approxLineCount < 2.9f) { - continue; - } - - if (documentFontSizeCounter.getMostPopular() != null) { - if (textBlock.getMostPopularWordFontSize() >= documentFontSizeCounter.getMostPopular()) { - - if (page.getCropBox().getWidth() > page.getCropBox().getHeight() && page.getRotation() != 0) { - if (textBlock.getY1() < minX) { - minX = textBlock.getY1(); - } - if (textBlock.getY2() > maxX) { - maxX = textBlock.getY2(); - } - if (textBlock.getX1() < minY) { - minY = textBlock.getX1(); - } - if (textBlock.getX2() > maxY) { - maxY = textBlock.getX2(); - } - } else { - if (textBlock.getX1() < minX) { - minX = textBlock.getX1(); - } - if (textBlock.getX2() > maxX) { - maxX = textBlock.getX2(); - } - if (textBlock.getY1() < minY) { - minY = textBlock.getY1(); - } - if (textBlock.getY2() > maxY) { - maxY = textBlock.getY2(); - } - } - } - } - } - - if (container instanceof Table) { - Table table = (Table) container; - for (List row : table.getRows()) { - for (Cell cell : row) { - - if (cell == null || cell.getTextBlocks() == null) { - continue; - } - for (TextBlock textBlock : cell.getTextBlocks()) { - if (page.getCropBox().getWidth() > page.getCropBox().getHeight() && page.getRotation() != 0) { - if (textBlock.getY1() < minX) { - minX = textBlock.getMinY(); - } - if (textBlock.getY2() > maxX) { - maxX = textBlock.getY2(); - } - if (textBlock.getX1() < minY) { - minY = textBlock.getX1(); - } - if (textBlock.getX2() > maxY) { - maxY = textBlock.getX2(); - } - } else { - if (textBlock.getX1() < minX) { - minX = textBlock.getX1(); - } - if (textBlock.getX2() > maxX) { - maxX = textBlock.getX2(); - } - if (textBlock.getY1() < minY) { - minY = textBlock.getY1(); - } - if (textBlock.getY2() > maxY) { - maxY = textBlock.getY2(); - } - } - } - } - } - } - } - System.out.println("Page: " + page.getPageNumber() + " Landscape: " + page.isLandscape() + " MinX: " + minX + " MaxX: " + maxX + " MinY: " + minY + " MaxY: " + maxY); - - } - return new Rectangle(new Point(minX, minY), maxX - minX, maxY - minY, 0); - } - - private double round(float value, int decimalPoints) { var d = Math.pow(10, decimalPoints); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/BodyTextFrameService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/BodyTextFrameService.java new file mode 100644 index 00000000..05b8b825 --- /dev/null +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/BodyTextFrameService.java @@ -0,0 +1,171 @@ +package com.iqser.red.service.redaction.v1.server.classification.service; + +import java.util.List; + +import org.springframework.stereotype.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.FloatFrequencyCounter; +import com.iqser.red.service.redaction.v1.server.classification.model.Page; +import com.iqser.red.service.redaction.v1.server.classification.model.TextBlock; +import com.iqser.red.service.redaction.v1.server.classification.utils.PositionUtils; +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; + +@Service +public class BodyTextFrameService { + + /** + * Adjusts and sets the body text frame to a page. + * Note: This needs to use Pdf Coordinate System where {0,0} rotated with the page rotation. + * 0 -> LowerLeft + * 90 -> UpperLeft + * 180 -> UpperRight + * 270 -> LowerRight + * The aspect ratio of the page is also regarded. + * + * @param page The page + * @param bodyTextFrame frame that contains the main text on portrait pages + * @param landscapeBodyTextFrame frame that contains the main text on landscape pages + */ + public void setBodyTextFrameAdjustedToPage(Page page, Rectangle bodyTextFrame, Rectangle landscapeBodyTextFrame) { + + Rectangle textFrame = page.isLandscape() ? landscapeBodyTextFrame : bodyTextFrame; + + if (page.getPageWidth() > page.getPageHeight() && page.getRotation() == 270) { + textFrame = new Rectangle(new Point(textFrame.getTopLeft().getY(), page.getPageHeight() - textFrame.getTopLeft().getX() - textFrame.getWidth()), + textFrame.getHeight(), + textFrame.getWidth(), + 0); + } else if (page.getPageWidth() > page.getPageHeight() && page.getRotation() != 0) { + textFrame = new Rectangle(new Point(textFrame.getTopLeft().getY(), textFrame.getTopLeft().getX()), textFrame.getHeight(), textFrame.getWidth(), page.getPageNumber()); + } else if (page.getRotation() == 180) { + textFrame = new Rectangle(new Point(textFrame.getTopLeft().getX(), page.getPageHeight() - textFrame.getTopLeft().getY() - textFrame.getHeight()), + textFrame.getWidth(), + textFrame.getHeight(), + 0); + } + page.setBodyTextFrame(textFrame); + } + + + /** + * Calculates the frame that contains the main text, text outside the frame will be e.g. headers or footers. + * Note: This needs to use Pdf Coordinate System where {0,0} rotated with the page rotation. + * 0 -> LowerLeft + * 90 -> UpperLeft + * 180 -> UpperRight + * 270 -> LowerRight + * The aspect ratio of the page is also regarded. + * + * @param pages List of all pages + * @param documentFontSizeCounter Statistics of the document + * @param landscape Calculate for landscape or portrait + * @return Rectangle of the text frame + */ + public Rectangle calculateBodyTextFrame(List pages, FloatFrequencyCounter documentFontSizeCounter, boolean landscape) { + + float minX = 10000; + float maxX = -100; + float minY = 10000; + float maxY = -100; + + for (Page page : pages) { + + if (page.getTextBlocks().isEmpty() || landscape != page.isLandscape()) { + continue; + } + + for (AbstractTextContainer container : page.getTextBlocks()) { + + if (container instanceof TextBlock) { + TextBlock textBlock = (TextBlock) container; + if (textBlock.getMostPopularWordFont() == null || textBlock.getMostPopularWordStyle() == null) { + continue; + } + + float approxLineCount = PositionUtils.getApproxLineCount(textBlock); + if (approxLineCount < 2.9f) { + continue; + } + + if (documentFontSizeCounter.getMostPopular() != null && textBlock.getMostPopularWordFontSize() >= documentFontSizeCounter.getMostPopular()) { + + if (page.getPageWidth() > page.getPageHeight() && page.getRotation() != 0) { + if (textBlock.getPdfMinY() < minX) { + minX = textBlock.getPdfMinY(); + } + if (textBlock.getPdfMaxY() > maxX) { + maxX = textBlock.getPdfMaxY(); + } + if (textBlock.getPdfMinX() < minY) { + minY = textBlock.getPdfMinX(); + } + if (textBlock.getPdfMaxX() > maxY) { + maxY = textBlock.getPdfMaxX(); + } + } else { + if (textBlock.getPdfMinX() < minX) { + minX = textBlock.getPdfMinX(); + } + if (textBlock.getPdfMaxX() > maxX) { + maxX = textBlock.getPdfMaxX(); + } + if (textBlock.getPdfMinY() < minY) { + minY = textBlock.getPdfMinY(); + } + if (textBlock.getPdfMaxY() > maxY) { + maxY = textBlock.getPdfMaxY(); + } + } + } + } + + if (container instanceof Table) { + Table table = (Table) container; + for (List row : table.getRows()) { + for (Cell cell : row) { + + if (cell == null || cell.getTextBlocks() == null) { + continue; + } + for (TextBlock textBlock : cell.getTextBlocks()) { + if (page.getPageWidth() > page.getPageHeight() && page.getRotation() != 0) { + if (textBlock.getPdfMinY() < minX) { + minX = textBlock.getMinY(); + } + if (textBlock.getPdfMaxY() > maxX) { + maxX = textBlock.getPdfMaxY(); + } + if (textBlock.getPdfMinX() < minY) { + minY = textBlock.getPdfMinX(); + } + if (textBlock.getPdfMaxX() > maxY) { + maxY = textBlock.getPdfMaxX(); + } + } else { + if (textBlock.getPdfMinX() < minX) { + minX = textBlock.getPdfMinX(); + } + if (textBlock.getPdfMaxX() > maxX) { + maxX = textBlock.getPdfMaxX(); + } + if (textBlock.getPdfMinY() < minY) { + minY = textBlock.getPdfMinY(); + } + if (textBlock.getPdfMaxY() > maxY) { + maxY = textBlock.getPdfMaxY(); + } + } + } + } + } + } + } + } + return new Rectangle(new Point(minX, minY), maxX - minX, maxY - minY, 0); + } + +} 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 bace55ae..35381230 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 @@ -5,7 +5,6 @@ import java.util.regex.Pattern; import org.springframework.stereotype.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; @@ -21,53 +20,37 @@ import lombok.extern.slf4j.Slf4j; @RequiredArgsConstructor public class ClassificationService { - private final BlockificationService blockificationService; + private final BodyTextFrameService bodyTextFrameService; public void classifyDocument(Document document) { - Rectangle bodyTextFrame = blockificationService.calculateBodyTextFrame(document.getPages(), document.getFontSizeCounter(), false); - Rectangle landscapeBodyTextFrame = blockificationService.calculateBodyTextFrame(document.getPages(), document.getFontSizeCounter(), true); - + Rectangle bodyTextFrame = bodyTextFrameService.calculateBodyTextFrame(document.getPages(), document.getFontSizeCounter(), false); + Rectangle landscapeBodyTextFrame = bodyTextFrameService.calculateBodyTextFrame(document.getPages(), document.getFontSizeCounter(), true); List headlineFontSizes = document.getFontSizeCounter().getHighterThanMostPopular(); log.debug("Document FontSize counters are: {}", document.getFontSizeCounter().getCountPerValue()); for (Page page : document.getPages()) { - Rectangle btf = page.isLandscape() ? landscapeBodyTextFrame : bodyTextFrame; - - if (page.getCropBox().getWidth() > page.getCropBox().getHeight() && page.getRotation() == 270) { - btf = new Rectangle(new Point(btf.getTopLeft().getY(), page.getCropBox().getHeight() - btf.getTopLeft().getX() - btf.getWidth()), - btf.getHeight(), - btf.getWidth(), - 0); - } else if (page.getCropBox().getWidth() > page.getCropBox().getHeight() && page.getRotation() != 0) { - btf = new Rectangle(new Point(btf.getTopLeft().getY(), btf.getTopLeft().getX()), btf.getHeight(), btf.getWidth(), 0); - } else if (page.getRotation() == 180) { - btf = new Rectangle(new Point(btf.getTopLeft().getX(), page.getCropBox().getHeight() - btf.getTopLeft().getY() - btf.getHeight()), - btf.getWidth(), - btf.getHeight(), - 0); - } - - page.setBodyTextFrame(btf); - - classifyPage(btf, page, document, headlineFontSizes); + bodyTextFrameService.setBodyTextFrameAdjustedToPage(page, bodyTextFrame, landscapeBodyTextFrame); + classifyPage(page, document, headlineFontSizes); } } - public void classifyPage(Rectangle bodyTextFrame, Page page, Document document, List headlineFontSizes) { + public void classifyPage(Page page, Document document, List headlineFontSizes) { for (AbstractTextContainer textBlock : page.getTextBlocks()) { if (textBlock instanceof TextBlock) { - classifyBlock((TextBlock) textBlock, bodyTextFrame, page, document, headlineFontSizes); + classifyBlock((TextBlock) textBlock, page, document, headlineFontSizes); } } } - public void classifyBlock(TextBlock textBlock, Rectangle bodyTextFrame, Page page, Document document, List headlineFontSizes) { + public void classifyBlock(TextBlock textBlock, Page page, Document document, List headlineFontSizes) { + + var bodyTextFrame = page.getBodyTextFrame(); if (document.getFontSizeCounter().getMostPopular() == null) { textBlock.setClassification("Other"); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/CoordSystemHelper.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/CoordSystemHelper.java deleted file mode 100644 index 4a2b7c14..00000000 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/CoordSystemHelper.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.iqser.red.service.redaction.v1.server.classification.utils; - -import java.awt.geom.Line2D; -import java.awt.geom.Point2D; - -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.tableextraction.model.Ruling; - -import lombok.experimental.UtilityClass; - -@UtilityClass -public class CoordSystemHelper { - - public Rectangle convertToDirAdj(Rectangle rectangle, float rotation, float pageWidth, float pageHeight) { - - var topLeft = convertPoint(rectangle.getTopLeft().getX(), rectangle.getTopLeft().getY() + rectangle.getHeight(), rotation, pageWidth, pageHeight); - var bottomRight = convertPoint(rectangle.getTopLeft().getX() + rectangle.getWidth(), rectangle.getTopLeft().getY(), rotation, pageWidth, pageHeight); - - return new Rectangle(new Point((float) topLeft.getX(), (float) topLeft.getY()), - (float) (bottomRight.getX() - topLeft.getX()), - (float) (bottomRight.getY() - topLeft.getY()), - 0); - } - - - public Line2D.Float convertToDirAdj(Ruling ruling, float rotation, float pageWidth, float pageHeight) { - - return new Line2D.Float(convertPoint(ruling.x1, ruling.y1, rotation, pageWidth, pageHeight), convertPoint(ruling.x2, ruling.y2, rotation, pageWidth, pageHeight)); - } - - - private Point2D convertPoint(float x, float y, float rotation, float pageWidth, float pageHeight) { - - var xAdj = getXRot(x, y, rotation, pageWidth, pageHeight); - var yAdj = 0f; - if (rotation == 0 || rotation == 180) { - yAdj = pageHeight - getYLowerLeftRot(x, y, rotation, pageWidth, pageHeight); - } else { - yAdj = pageWidth - getYLowerLeftRot(x, y, rotation, pageWidth, pageHeight); - } - return new Point2D.Float(xAdj, yAdj); - } - - - private float getXRot(float x, float y, float rotation, float pageWidth, float pageHeight) { - - if (rotation == 0) { - return x; - } else if (rotation == 90) { - return y; - } else if (rotation == 180) { - return pageWidth - x; - } else if (rotation == 270) { - return pageHeight - y; - } - return 0; - } - - - private float getYLowerLeftRot(float x, float y, float rotation, float pageWidth, float pageHeight) { - - if (rotation == 0) { - return y; - } else if (rotation == 90) { - return pageWidth - x; - } else if (rotation == 180) { - return pageHeight - y; - } else if (rotation == 270) { - return x; - } - return 0; - } - -} 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 f3bb9331..37316f2a 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 @@ -9,18 +9,18 @@ import lombok.experimental.UtilityClass; @SuppressWarnings("all") public class PositionUtils { + // TODO This currently uses pdf coord system. In the futher this should use java coord system. + // Note: DirAdj (TextDirection Adjusted) can not be user for this. public boolean isWithinBodyTextFrame(Rectangle btf, TextBlock textBlock) { - //TODO Currently this is not working for rotated pages. - if (btf == null || textBlock == null) { return false; } double threshold = textBlock.getMostPopularWordHeight() * 3; - if (textBlock.getX1() + threshold > btf.getTopLeft().getX() && textBlock.getX2() - threshold < btf.getTopLeft() - .getX() + btf.getWidth() && textBlock.getY1() + threshold > btf.getTopLeft().getY() && textBlock.getY2() - threshold < btf.getTopLeft() + if (textBlock.getPdfMinX() + threshold > btf.getTopLeft().getX() && textBlock.getPdfMaxX() - threshold < btf.getTopLeft() + .getX() + btf.getWidth() && textBlock.getPdfMinY() + threshold > btf.getTopLeft().getY() && textBlock.getPdfMaxY() - threshold < btf.getTopLeft() .getY() + btf.getHeight()) { return true; } else { @@ -30,25 +30,27 @@ public class PositionUtils { } + // TODO This currently uses pdf coord system. In the futher this should use java coord system. + // Note: DirAdj (TextDirection Adjusted) can not be user for this. public boolean isOverBodyTextFrame(Rectangle btf, TextBlock textBlock, int rotation) { if (btf == null || textBlock == null) { return false; } - if (rotation == 90 && textBlock.getX2() < btf.getTopLeft().getX()) { + if (rotation == 90 && textBlock.getPdfMaxX() < btf.getTopLeft().getX()) { return true; } - if (rotation == 180 && textBlock.getY2() < btf.getTopLeft().getY()) { + if (rotation == 180 && textBlock.getPdfMaxY() < btf.getTopLeft().getY()) { return true; } - if (rotation == 270 && textBlock.getX1() > btf.getTopLeft().getX() + btf.getWidth()) { + if (rotation == 270 && textBlock.getPdfMinX() > btf.getTopLeft().getX() + btf.getWidth()) { return true; } - if (rotation == 0 && textBlock.getY1() > btf.getTopLeft().getY() + btf.getHeight()) { + if (rotation == 0 && textBlock.getPdfMinY() > btf.getTopLeft().getY() + btf.getHeight()) { return true; } else { return false; @@ -56,26 +58,27 @@ public class PositionUtils { } - + // TODO This currently uses pdf coord system. In the futher this should use java coord system. + // Note: DirAdj (TextDirection Adjusted) can not be user for this. public boolean isUnderBodyTextFrame(Rectangle btf, TextBlock textBlock, int rotation) { if (btf == null || textBlock == null) { return false; } - if (rotation == 90 && textBlock.getX1() > btf.getTopLeft().getX() + btf.getWidth()) { + if (rotation == 90 && textBlock.getPdfMinX() > btf.getTopLeft().getX() + btf.getWidth()) { return true; } - if (rotation == 180 && textBlock.getY1() > btf.getTopLeft().getY() + btf.getHeight()) { + if (rotation == 180 && textBlock.getPdfMinY() > btf.getTopLeft().getY() + btf.getHeight()) { return true; } - if (rotation == 270 && textBlock.getX2() < btf.getTopLeft().getX()) { + if (rotation == 270 && textBlock.getPdfMaxX() < btf.getTopLeft().getX()) { return true; } - if (rotation == 0 && textBlock.getY2() < btf.getTopLeft().getY()) { + if (rotation == 0 && textBlock.getPdfMaxY() < btf.getTopLeft().getY()) { return true; } else { return false; @@ -83,7 +86,8 @@ public class PositionUtils { } - + // TODO This currently uses pdf coord system. In the futher this should use java coord system. + // Note: DirAdj (TextDirection Adjusted) can not be user for this. public boolean isTouchingUnderBodyTextFrame(Rectangle btf, TextBlock textBlock) { //TODO Currently this is not working for rotated pages. diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/RulingTextDirAdjustUtil.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/RulingTextDirAdjustUtil.java new file mode 100644 index 00000000..3fe5a7f6 --- /dev/null +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/RulingTextDirAdjustUtil.java @@ -0,0 +1,67 @@ +package com.iqser.red.service.redaction.v1.server.classification.utils; + +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; + +import com.iqser.red.service.redaction.v1.server.tableextraction.model.Ruling; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class RulingTextDirAdjustUtil { + + /** + * Converts a ruling (line of a table) the same way TextPositions are converted in PDFBox. + * This will get the y position of the text, adjusted so that 0,0 is upper left and it is adjusted based on the text direction. + * + * See org.apache.pdfbox.text.TextPosition + */ + public Line2D.Float convertToDirAdj(Ruling ruling, float dir, float pageWidth, float pageHeight) { + + return new Line2D.Float(convertPoint(ruling.x1, ruling.y1, dir, pageWidth, pageHeight), convertPoint(ruling.x2, ruling.y2, dir, pageWidth, pageHeight)); + } + + + private Point2D convertPoint(float x, float y, float dir, float pageWidth, float pageHeight) { + + var xAdj = getXRot(x, y, dir, pageWidth, pageHeight); + var yAdj = 0f; + if (dir == 0 || dir == 180) { + yAdj = pageHeight - getYLowerLeftRot(x, y, dir, pageWidth, pageHeight); + } else { + yAdj = pageWidth - getYLowerLeftRot(x, y, dir, pageWidth, pageHeight); + } + return new Point2D.Float(xAdj, yAdj); + } + + + private float getXRot(float x, float y, float dir, float pageWidth, float pageHeight) { + + if (dir == 0) { + return x; + } else if (dir == 90) { + return y; + } else if (dir == 180) { + return pageWidth - x; + } else if (dir == 270) { + return pageHeight - y; + } + return 0; + } + + + private float getYLowerLeftRot(float x, float y, float dir, float pageWidth, float pageHeight) { + + if (dir == 0) { + return y; + } else if (dir == 90) { + return pageWidth - x; + } else if (dir == 180) { + return pageHeight - y; + } else if (dir == 270) { + return x; + } + return 0; + } + +} diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java index 446257d2..0ea72b66 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java @@ -47,16 +47,6 @@ public class TextPositionSequence implements CharSequence { } - public TextPositionSequence fromData(List textPositions, int page) { - - var textPositionSequence = new TextPositionSequence(); - textPositionSequence.textPositions = textPositions; - textPositionSequence.page = page; - - return textPositionSequence; - } - - public TextPositionSequence(List textPositions, int page) { this.textPositions = textPositions.stream().map(RedTextPosition::fromTextPosition).collect(Collectors.toList()); @@ -147,44 +137,60 @@ public class TextPositionSequence implements CharSequence { } + /** + * This value is adjusted so that 0,0 is upper left and it is adjusted based on the text direction. + * This method ignores the page rotation but takes the text rotation and adjusts the coordinates to awt. + * + * @return the text direction adjusted minX value + */ @JsonIgnore @JsonAttribute(ignore = true) - public float getRotationAdjustedY() { - - return textPositions.get(0).getYDirAdj(); - } - - - @JsonIgnore - @JsonAttribute(ignore = true) - public float getX1() { + public float getMinXDirAdj() { return textPositions.get(0).getXDirAdj(); } + /** + * This value is adjusted so that 0,0 is upper left and it is adjusted based on the text direction. + * This method ignores the page rotation but takes the text rotation and adjusts the coordinates to awt. + * + * @return the text direction adjusted maxX value + */ @JsonIgnore @JsonAttribute(ignore = true) - public float getX2() { + public float getMaxXDirAdj() { return textPositions.get(textPositions.size() - 1).getXDirAdj() + textPositions.get(textPositions.size() - 1).getWidthDirAdj() + HEIGHT_PADDING; } + /** + * This value is adjusted so that 0,0 is upper left and it is adjusted based on the text direction. + * This method ignores the page rotation but takes the text rotation and adjusts the coordinates to awt. + * + * @return the text direction adjusted minY value. The upper border of the bounding box of the word. + */ @JsonIgnore @JsonAttribute(ignore = true) - public float getY1() { + public float getMinYDirAdj() { return textPositions.get(0).getYDirAdj() - getTextHeight(); } + /** + * This value is adjusted so that 0,0 is upper left and it is adjusted based on the text direction. + * This method ignores the page rotation but takes the text rotation and adjusts the coordinates to awt. + * + * @return the text direction adjusted maxY value. The lower border of the bounding box of the word. + */ @JsonIgnore @JsonAttribute(ignore = true) - public float getY2() { + public float getMaxYDirAdj() { return textPositions.get(0).getYDirAdj(); @@ -203,7 +209,7 @@ public class TextPositionSequence implements CharSequence { @JsonAttribute(ignore = true) public float getHeight() { - return getY2() - getY1(); + return getMaxYDirAdj() - getMinYDirAdj(); } @@ -211,7 +217,7 @@ public class TextPositionSequence implements CharSequence { @JsonAttribute(ignore = true) public float getWidth() { - return getX2() - getX1(); + return getMaxXDirAdj() - getMinXDirAdj(); } @@ -258,6 +264,15 @@ public class TextPositionSequence implements CharSequence { } + /** + * This returns the bounding box of the word in Pdf Coordinate System where {0,0} rotated with the page rotation. + * 0 -> LowerLeft + * 90 -> UpperLeft + * 180 -> UpperRight + * 270 -> LowerRight + * + * @return bounding box of the word in Pdf Coordinate System + */ @JsonIgnore @JsonAttribute(ignore = true) @SneakyThrows diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/model/CellValue.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/model/CellValue.java index bdc6cbe9..e98f5f52 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/model/CellValue.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/model/CellValue.java @@ -33,7 +33,7 @@ public class CellValue { TextPositionSequence previous = null; for (TextPositionSequence word : textBlock.getSequences()) { if (previous != null) { - if (Math.abs(previous.getRotationAdjustedY() - word.getRotationAdjustedY()) > word.getTextHeight()) { + if (Math.abs(previous.getMaxYDirAdj() - word.getMaxYDirAdj()) > word.getTextHeight()) { sb.append('\n'); } else { sb.append(' '); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/model/SearchableText.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/model/SearchableText.java index e031854d..8ed10a20 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/model/SearchableText.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/model/SearchableText.java @@ -194,7 +194,7 @@ public class SearchableText { for (TextPositionSequence word : sequences) { if (previous != null) { - if (Math.abs(previous.getRotationAdjustedY() - word.getRotationAdjustedY()) > word.getTextHeight()) { + if (Math.abs(previous.getMaxYDirAdj() - word.getMaxYDirAdj()) > word.getTextHeight()) { sb.append('\n'); } else { sb.append(' '); @@ -228,7 +228,7 @@ public class SearchableText { for (TextPositionSequence word : sorted) { if (previous != null) { - if (Math.abs(previous.getRotationAdjustedY() - word.getRotationAdjustedY()) > word.getTextHeight()) { + if (Math.abs(previous.getMaxYDirAdj() - word.getMaxYDirAdj()) > word.getTextHeight()) { sb.append('\n'); } else { sb.append(' '); @@ -249,7 +249,7 @@ public class SearchableText { for (TextPositionSequence word : sequences) { if (previous != null) { - if (Math.abs(previous.getRotationAdjustedY() - word.getRotationAdjustedY()) > word.getTextHeight()) { + if (Math.abs(previous.getMaxYDirAdj() - word.getMaxYDirAdj()) > word.getTextHeight()) { sb.append('\n'); } else { sb.append(' '); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/SectionGridCreatorService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/SectionGridCreatorService.java index 5d03059e..233e6d7d 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/SectionGridCreatorService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/service/SectionGridCreatorService.java @@ -47,9 +47,9 @@ public class SectionGridCreatorService { classifiedDoc.getSectionGrid() .getRectanglesPerPage() .computeIfAbsent(page, (x) -> new ArrayList<>()) - .add(new SectionRectangle(new Point(tb.getX1(), tb.getY1()), - tb.getX2() - tb.getX1(), - tb.getY2() - tb.getY1(), + .add(new SectionRectangle(new Point(tb.getPdfMinX(), tb.getPdfMinY()), + tb.getPdfMaxX() - tb.getPdfMinX(), + tb.getPdfMaxY() - tb.getPdfMinY(), i + 1, paragraph.getPageBlocks().size(), null)); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/utils/EntitySearchUtils.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/utils/EntitySearchUtils.java index 842e1471..1446b19f 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/utils/EntitySearchUtils.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/redaction/utils/EntitySearchUtils.java @@ -292,9 +292,9 @@ public class EntitySearchUtils { .get(0) .getSequences() .get(0) - .getX1() && image.getPosition().getX() + image.getPosition().getWidth() > entity.getPositionSequences().get(0).getSequences().get(0).getX2() && image.getPosition() - .getY() < entity.getPositionSequences().get(0).getSequences().get(0).getY1() && image.getPosition().getY() + image.getPosition() - .getHeight() > entity.getPositionSequences().get(0).getSequences().get(0).getY2(); + .getMinXDirAdj() && image.getPosition().getX() + image.getPosition().getWidth() > entity.getPositionSequences().get(0).getSequences().get(0).getMaxXDirAdj() && image.getPosition() + .getY() < entity.getPositionSequences().get(0).getSequences().get(0).getMinYDirAdj() && image.getPosition().getY() + image.getPosition() + .getHeight() > entity.getPositionSequences().get(0).getSequences().get(0).getMaxYDirAdj(); } 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 2cd85d50..35672ddc 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 @@ -108,18 +108,13 @@ public class PdfSegmentationService { stripper.getRulings(), stripper.getMinCharWidth(), stripper.getMaxCharHeight()); - Page page = blockificationService.blockify(stripper.getTextPositionSequences(), cleanRulings.getHorizontal(), cleanRulings.getVertical(), rotation, cropbox); - - float cropboxArea = cropbox.getHeight() * cropbox.getWidth(); - page.setCropBoxArea(cropboxArea); - - System.out.println("CropBox: w:" + cropbox.getWidth() + " h:" + cropbox.getHeight() + "MediaBox: w:" + pdPage.getMediaBox() - .getWidth() + " h:" + pdPage.getMediaBox().getHeight()); + Page page = blockificationService.blockify(stripper.getTextPositionSequences(), cleanRulings.getHorizontal(), cleanRulings.getVertical()); page.setRotation(rotation); page.setLandscape(isLandscape); page.setPageNumber(pageNumber); - page.setCropBox(cropbox); + page.setPageWidth(cropbox.getWidth()); + page.setPageHeight(cropbox.getHeight()); tableExtractionService.extractTables(cleanRulings, page); buildPageStatistics(page); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/AbstractTextContainer.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/AbstractTextContainer.java index ae05eaba..f6a76b3a 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/AbstractTextContainer.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/AbstractTextContainer.java @@ -37,7 +37,7 @@ public abstract class AbstractTextContainer { public boolean containsBlock(TextBlock other) { - return this.minX <= other.getX1() && this.maxX >= other.getX2() && this.minY >= other.getY1() && this.maxY <= other.getY2(); + return this.minX <= other.getPdfMinX() && this.maxX >= other.getPdfMaxX() && this.minY >= other.getPdfMinY() && this.maxY <= other.getPdfMaxY(); } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/Cell.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/Cell.java index 39545144..5dcb1138 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/Cell.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/Cell.java @@ -51,7 +51,7 @@ public class Cell extends Rectangle { for (TextPositionSequence word : textBlock.getSequences()) { if (previous != null) { - if (Math.abs(previous.getRotationAdjustedY() - word.getRotationAdjustedY()) > word.getTextHeight()) { + if (Math.abs(previous.getMaxYDirAdj() - word.getMaxYDirAdj()) > word.getTextHeight()) { sb.append('\n'); } else { sb.append(' '); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/service/TableExtractionService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/service/TableExtractionService.java index ad4a82b4..71b2e76c 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/service/TableExtractionService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/service/TableExtractionService.java @@ -75,7 +75,7 @@ public class TableExtractionService { for (AbstractTextContainer abstractTextContainer : page.getTextBlocks()) { TextBlock textBlock = (TextBlock) abstractTextContainer; for (Cell cell : cells) { - if (cell.intersects(textBlock.getX1(), textBlock.getY1(), textBlock.getX2() - textBlock.getX1(), textBlock.getY2() - textBlock.getY1())) { + if (cell.intersects(textBlock.getPdfMinX(), textBlock.getPdfMinY(), textBlock.getPdfMaxX() - textBlock.getPdfMinX(), textBlock.getPdfMaxY() - textBlock.getPdfMinY())) { cell.addTextBlock(textBlock); toBeRemoved.add(textBlock); break; 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 dd6464b5..ccdb255e 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 @@ -100,7 +100,7 @@ public class PdfVisualisationService { contentStream.setStrokingColor(Color.RED); - contentStream.addRect(textBlock.getX1(), textBlock.getY1(), textBlock.getX2() - textBlock.getX1(), textBlock.getY2() - textBlock.getY1()); + contentStream.addRect(textBlock.getPdfMinX(), textBlock.getPdfMinY(), textBlock.getPdfMaxX() - textBlock.getPdfMinX(), textBlock.getPdfMaxY() - textBlock.getPdfMinY()); contentStream.stroke(); if (textBlock.getClassification() != null) { @@ -109,7 +109,7 @@ public class PdfVisualisationService { contentStream.setNonStrokingColor(Color.BLUE); contentStream.setFont(PDType1Font.TIMES_ROMAN, 9f); - contentStream.newLineAtOffset(textBlock.getX1(), textBlock.getY2() + 2); + contentStream.newLineAtOffset(textBlock.getPdfMinX(), textBlock.getPdfMaxY() + 2); contentStream.showText(textBlock.getClassification() + textBlock.getOrientation() + "-->" + textBlock.getSequences().get(0).getDir()); contentStream.endText(); @@ -153,7 +153,7 @@ public class PdfVisualisationService { contentStream.setStrokingColor(Color.GREEN); for (TextBlock textBlock : cell.getTextBlocks()) { - contentStream.addRect(textBlock.getX1(), textBlock.getY1(), textBlock.getX2() - textBlock.getX1(), textBlock.getY2() - textBlock.getY1()); + contentStream.addRect(textBlock.getPdfMinX(), textBlock.getPdfMinY(), textBlock.getPdfMaxX() - textBlock.getPdfMinX(), textBlock.getPdfMaxY() - textBlock.getPdfMinY()); contentStream.stroke(); } }