Wrong scaling for Images in Reports
This commit is contained in:
aoezyetimoglu 2021-11-08 14:12:36 +01:00
parent f258d62a1f
commit 599a099d35
7 changed files with 98 additions and 161 deletions

View File

@ -1,5 +1,48 @@
package com.iqser.red.service.redaction.report.v1.server.service;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.DOSSIER_NAME_PLACEHOLDER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.EXCERPT_PLACEHOLDER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FILE_NAME_PLACEHOLDER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ENG;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ENG_PLACEHOLDER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_GER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_GER_PLACEHOLDER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ISO;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ISO_PLACEHOLDER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_TIME_ISO;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_TIME_ISO_PLACEHOLDER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_PARAGRAPH_PLACEHOLDER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_PLACEHOLDER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_REASON_PLACEHOLDER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.PAGE_PLACEHOLDER;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.PARAGRAPH_PLACEHOLDER;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.DossierAttributeConfig;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.Dossier;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierAttribute;
@ -10,29 +53,10 @@ import com.iqser.red.service.redaction.report.v1.server.client.DossierAttributes
import com.iqser.red.service.redaction.report.v1.server.client.FileAttributesConfigClient;
import com.iqser.red.service.redaction.report.v1.server.model.ImagePlaceholder;
import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEntry;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.Dimension2DDouble;
import org.apache.poi.util.Units;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.*;
import javax.imageio.ImageIO;
@Slf4j
@Service
@ -240,30 +264,29 @@ public class ExcelTemplateReportGenerationService {
if (cell.getStringCellValue().contains(imagePlaceholder.getPlaceholder())) {
try (ByteArrayInputStream is = new ByteArrayInputStream(imagePlaceholder.getImage())) {
ByteArrayInputStream scaledImage = getScaledImage(is, sheet.getColumnWidthInPixels(cell.getColumnIndex()), convertPointsToPixel(cell.getRow().getHeightInPoints()));
// ByteArrayInputStream scaledImage = getScaledImage(is, PixelUtil.widthUnits2Pixel((short) sheet.getColumnWidth(cell.getColumnIndex())), PixelUtil.heightUnits2Pixel(cell.getRow().getHeight()));
// is.reset();
double factor = calculateScale(is, PixelUtil.widthUnits2Pixel((short) sheet.getColumnWidth(cell.getColumnIndex())), PixelUtil.heightUnits2Pixel(cell.getRow().getHeight()));
is.reset();
int pictureIdx = workbook.addPicture(scaledImage, XSSFWorkbook.PICTURE_TYPE_JPEG);
// scaledImage.reset();
int pictureIdx = workbook.addPicture(is, XSSFWorkbook.PICTURE_TYPE_JPEG);
is.reset();
//Returns an object that handles instantiating concrete classes
CreationHelper helper = workbook.getCreationHelper();
//Creates the top-level drawing patriarch.
//Create an anchor that is attached to the worksheet
ClientAnchor anchor = helper.createClientAnchor();
// anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
anchor.setCol1(cell.getColumnIndex());
anchor.setRow1(cell.getRowIndex());
anchor.setCol2(cell.getColumnIndex() + 1);
anchor.setRow2(cell.getRowIndex() + 1);
//Creates the top-level drawing patriarch.
Drawing drawing = sheet.createDrawingPatriarch();
drawing.createPicture(anchor, pictureIdx);
//sheet.setColumnWidth(cell.getColumnIndex(), (int) dim.getWidth());
// cell.getRow().setHeight((short) dim.getHeight());
Picture picture = drawing.createPicture(anchor, pictureIdx);
picture.resize(factor);
cell.setCellValue("");
}
@ -273,138 +296,26 @@ public class ExcelTemplateReportGenerationService {
}
private float convertPointsToPixel(float points) {
return points/0.75f;
}
private double calculateScale(ByteArrayInputStream imageByteArrayInputStream, float cellWidth, float cellHeight) throws IOException {
BufferedImage img = ImageIO.read(imageByteArrayInputStream);
double imageWidth = img.getWidth();
double imageHeight = img.getHeight();
private ByteArrayInputStream getScaledImage(ByteArrayInputStream imageByteArrayInputStream, float cellWidth, float cellHeight) throws IOException {
BufferedImage image = ImageIO.read(imageByteArrayInputStream);
double imageWidth = image.getWidth();
double imageHeight = image.getHeight();
double imageWidthScaleFactor;
double imageHeightScaleFactor;
double imageRatio = imageWidth/imageHeight;
// if(cellRatio <= 1 && imageRatio <=1) {
// // cell and image are landscape
//
//
// } else if(cellRatio <= 1 && imageRatio <=1) {
// // cell and image are portrait
//
// } else if(cellRatio <= 1 && imageRatio <=1) {
// // cell is landscape and image is portrait
//
// } else if(cellRatio <= 1 && imageRatio <=1) {
// // cell is portrait and image is landscape
//
// }
AffineTransform at = new AffineTransform();
imageWidthScaleFactor = cellWidth / imageWidth;
imageHeightScaleFactor = cellHeight / imageHeight;
if(imageWidthScaleFactor <= 1 && imageHeightScaleFactor > 1) {
imageWidth = imageWidth * imageWidthScaleFactor;
imageHeight = imageHeight * imageWidthScaleFactor;
at.scale(imageWidthScaleFactor, imageRatio);
} else if(imageWidthScaleFactor > 1 && imageHeightScaleFactor <= 1) {
imageHeight = imageHeight * imageHeightScaleFactor;
imageWidth = imageWidth * imageHeightScaleFactor;
at.scale(imageHeightScaleFactor, imageHeightScaleFactor/imageWidthScaleFactor);
} else if(imageWidthScaleFactor <= 1 && imageHeightScaleFactor <= 1) {
if(imageWidthScaleFactor <= imageHeightScaleFactor) {
imageWidth = imageWidth * imageWidthScaleFactor;
imageHeight = imageHeight * imageWidthScaleFactor;
at.scale(imageWidthScaleFactor, imageWidthScaleFactor/imageHeightScaleFactor);
} else {
imageHeight = imageHeight * imageHeightScaleFactor;
imageWidth = imageWidth * imageHeightScaleFactor;
at.scale(imageHeightScaleFactor, imageHeightScaleFactor/imageWidthScaleFactor);
}
double widthFactor = (double) cellWidth/ imageWidth;
double heightFactor = (double) cellHeight/ imageHeight;
if (imageWidth < cellWidth && imageHeight < cellHeight) {
return 1;
} else if (cellWidth > cellHeight) {
return heightFactor;
} else {
at.scale(1/imageHeightScaleFactor, 1/imageWidthScaleFactor);
return widthFactor;
}
// AffineTransform at = new AffineTransform();
// at.scale(1/imageWidthScaleFactor, 1/imageHeightScaleFactor);
AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
BufferedImage scaledImage = new BufferedImage((int) imageWidth, (int) imageHeight, image.getType());
scaledImage = scaleOp.filter(image, scaledImage);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(scaledImage, "jpeg", os);
//os.reset();
return new ByteArrayInputStream(os.toByteArray());
}
// private ByteArrayInputStream getScaledImage(ByteArrayInputStream imageByteArrayInputStream, float cellWidth, float cellHeight) throws IOException {
// BufferedImage image = ImageIO.read(imageByteArrayInputStream);
//
// double imageWidth = image.getWidth();
//
// double imageHeight = image.getHeight();
//
// double cellRatio = cellWidth/cellHeight;
// double imageRatio = imageWidth/imageHeight;
//
// boolean scaleWidth = imageWidth > cellWidth;
// boolean scaleHeight = imageHeight > cellHeight;
//
// double imageWidthScaleFactor;
// double imageHeightScaleFactor;
//
// if (scaleWidth && scaleHeight) {
// // image width and height is greater than cell
// if (imageRatio < cellRatio) {
// // scale width
// imageWidthScaleFactor = cellWidth / imageWidth;
// imageHeightScaleFactor = imageWidthScaleFactor / imageRatio;
// } else {
// // scale height
// imageHeightScaleFactor = cellHeight / imageHeight;
// imageWidthScaleFactor = imageHeightScaleFactor * imageRatio;
// }
// } else if (scaleWidth) {
// // only image width is greater than cell
// imageWidthScaleFactor = cellWidth / imageWidth;
// imageHeightScaleFactor = imageWidthScaleFactor / imageRatio;
// } else if (scaleHeight) {
// // only image height is greater than cell
// imageHeightScaleFactor = cellHeight / imageHeight;
// imageWidthScaleFactor = imageHeightScaleFactor * imageRatio;
// } else {
// // nothing to do, image fits in cell
// imageWidthScaleFactor = 1;
// imageHeightScaleFactor = 1;
// }
//
// AffineTransform at = new AffineTransform();
// at.scale(imageWidthScaleFactor, imageHeightScaleFactor);
// AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
// BufferedImage scaledImage = new BufferedImage((int) (imageWidth * imageWidthScaleFactor), (int) (imageHeight * imageHeightScaleFactor), image.getType());
// scaledImage = scaleOp.filter(image, scaledImage);
//
// ByteArrayOutputStream os = new ByteArrayOutputStream();
// ImageIO.write(scaledImage, "jpeg", os);
// //os.reset();
// return new ByteArrayInputStream(os.toByteArray());
// }
//
private String getPlaceholderValue(String placeholder, Dossier project, FileModel fileStatus,
Map<String, String> fileAttributePlaceholders,
Map<String, String> dossierAttributesPlaceholders) {

View File

@ -0,0 +1,29 @@
package com.iqser.red.service.redaction.report.v1.server.service;
public class PixelUtil {
public static final short EXCEL_COLUMN_WIDTH_FACTOR = 256;
public static final short EXCEL_ROW_HEIGHT_FACTOR = 20;
public static final int UNIT_OFFSET_LENGTH = 7;
public static final int[] UNIT_OFFSET_MAP = new int[] { 0, 36, 73, 109, 146, 182, 219 };
public static short pixel2WidthUnits(int pxs) {
short widthUnits = (short) (EXCEL_COLUMN_WIDTH_FACTOR * (pxs / UNIT_OFFSET_LENGTH));
widthUnits += UNIT_OFFSET_MAP[pxs % UNIT_OFFSET_LENGTH];
return widthUnits;
}
public static int widthUnits2Pixel(short widthUnits) {
int pixels = (widthUnits / EXCEL_COLUMN_WIDTH_FACTOR) * UNIT_OFFSET_LENGTH;
int offsetWidthUnits = widthUnits % EXCEL_COLUMN_WIDTH_FACTOR;
pixels += Math.floor((float) offsetWidthUnits / ((float) EXCEL_COLUMN_WIDTH_FACTOR / UNIT_OFFSET_LENGTH));
return pixels;
}
public static int heightUnits2Pixel(short heightUnits) {
int pixels = heightUnits / EXCEL_ROW_HEIGHT_FACTOR;
int offsetWidthUnits = heightUnits % EXCEL_ROW_HEIGHT_FACTOR;
pixels += Math.floor((float) offsetWidthUnits / ((float) EXCEL_ROW_HEIGHT_FACTOR / UNIT_OFFSET_LENGTH));
return pixels;
}
}

View File

@ -12,7 +12,6 @@ import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.apache.commons.io.IOUtils;
@ -34,12 +33,10 @@ import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.Re
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.Dossier;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierAttribute;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.DossierAttributeType;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileAttribute;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileAttributeConfig;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileAttributeType;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileModel;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.legalbasis.LegalBasis;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.legalbasis.LegalBasisMapping;
import com.iqser.red.service.redaction.report.v1.api.model.ReportType;
import com.iqser.red.service.redaction.report.v1.server.client.DossierAttributesClient;
import com.iqser.red.service.redaction.report.v1.server.client.DossierAttributesConfigClient;
@ -412,11 +409,11 @@ public class RedactionReportIntegrationTest {
public void testIuclidReport() {
String dossierTemplateId = "dossierTemplateId";
ClassPathResource redactionLogResource = new ClassPathResource("files/redactionLog.json");
ClassPathResource redactionLogResource = new ClassPathResource("files/S11RedactionLog.json");
RedactionLog redactionLog = objectMapper.readValue(redactionLogResource.getInputStream(), RedactionLog.class);
ClassPathResource legalBasisMappingResource = new ClassPathResource("files/legalBasisMapping.json");
ClassPathResource legalBasisMappingResource = new ClassPathResource("files/S1116LegalBasis.json");
List<LegalBasis> legalBasisMapping = objectMapper.readValue(legalBasisMappingResource.getInputStream(), new TypeReference<>() {
});
@ -433,7 +430,7 @@ public class RedactionReportIntegrationTest {
when(fileAttributesConfigClient.getFileAttributeConfigs(dossierTemplateId)).thenReturn(new ArrayList<>());
FileModel fileStatus = FileModel.builder().filename("filename").build();
FileModel fileStatus = FileModel.builder().filename("VV123456").build();
Dossier project = Dossier.builder().id("dossierId").dossierName("projectName").build();
@ -455,7 +452,7 @@ public class RedactionReportIntegrationTest {
.build();
byte[] report = wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, dossierTemplateId, reportTemplate, fileStatus, project);
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/iuclid_report.docx")) {
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/iuclid_report_2.docx")) {
fileOutputStream.write(report);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB