You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@pdfbox.apache.org by "jiangpeiheng (Jira)" <ji...@apache.org> on 2020/04/27 19:56:00 UTC
[jira] [Created] (PDFBOX-4820) Multiplying two matrices produces
illegal values
jiangpeiheng created PDFBOX-4820:
------------------------------------
Summary: Multiplying two matrices produces illegal values
Key: PDFBOX-4820
URL: https://issues.apache.org/jira/browse/PDFBOX-4820
Project: PDFBox
Issue Type: Bug
Components: Rendering
Affects Versions: 2.0.19
Reporter: jiangpeiheng
Attachments: bit_coin.pdf
Hi, pdfbox developers
I meet an exception during rendering the PDF in the attachment. It seems that this exception occors while rendering the first and the last page of this PDF. The exception is:
{code:java}
20/04/28 03:45:01 ERROR RenderHandler: [PDF_RENDER_CORE_HANDLER]渲染单页异常, pageIndex:1, traceId:test-trace, e:20/04/28 03:45:01 ERROR RenderHandler: [PDF_RENDER_CORE_HANDLER]渲染单页异常, pageIndex:1, traceId:test-trace, e:java.lang.IllegalArgumentException: Multiplying two matrices produces illegal values at org.apache.pdfbox.util.Matrix.multiply(Matrix.java:408) at org.apache.pdfbox.util.Matrix.concatenate(Matrix.java:261) at org.apache.pdfbox.contentstream.PDFStreamEngine.processAnnotation(PDFStreamEngine.java:321) at org.apache.pdfbox.contentstream.PDFStreamEngine.showAnnotation(PDFStreamEngine.java:425) at org.apache.pdfbox.rendering.PageDrawer.showAnnotation(PageDrawer.java:1394) at org.apache.pdfbox.rendering.PageDrawer.drawPage(PageDrawer.java:274) at org.apache.pdfbox.rendering.PDFRenderer.renderImage(PDFRenderer.java:321) at org.apache.pdfbox.rendering.PDFRenderer.renderImage(PDFRenderer.java:243) at org.apache.pdfbox.rendering.PDFRenderer.renderImageWithDPI(PDFRenderer.java:215) at com.bytedance.esign.pdfrender.handler.RenderHandler.renderSinglePage(RenderHandler.java:175) at com.bytedance.esign.pdfrender.handler.RenderHandler.render(RenderHandler.java:119) at com.bytedance.esign.pdfrender.handler.RenderHandlerTest.renderTest(RenderHandlerTest.java:32) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
{code}
And here is my rendering code:
{code:java}
package com.bytedance.esign.pdfrender.handler;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 切图相关的Handler
*
* @author jiangpeiheng create on 2020/4/27
*/
@Slf4j
public class RenderHandler {
private static final String LOG_PERFIX = "PDF_RENDER_CORE_HANDLER";
// some settings for rendering
private static final int IMAGE_DPI = 200;
private static final String IMAGE_FORMAT = "jpg";
private RenderHandler() {
}
@Data
@Accessors(chain = true)
public static class RenderTask {
/**
* pdf源文件byte数组
*/
@ToString.Exclude
private byte[] pdfBytes;
/**
* 用于追踪文件渲染关联的id
*/
private String traceId;
/**
* 起始渲染页,从0开始
*/
private int start;
/**
* 终止渲染页,不包含该页
*/
private int end;
}
@Data
@Accessors(chain = true)
public static class RenderResult {
/**
* 渲染完成的页面
*/
@ToString.Exclude
private Map<Integer, byte[]> images = Maps.newHashMap();
/**
* 用于追踪文件渲染关联的id
*/
private String traceId;
/**
* 渲染失败的页面
*/
private List<Integer> failedPages = Lists.newArrayList();
/**
* 总页数
*/
private int totalPageCount;
/**
* 渲染成功页数
*/
private int successPageCount;
/**
* 渲染失败页数
*/
private int failedPageCount;
}
/**
* 针对pdf文件进行渲染
*
* @param task 渲染任务
* @return
*/
public static RenderResult render(RenderTask task) {
long startTime = System.currentTimeMillis();
RenderResult result = initResult(task);
try (
PDDocument doc = load(task.getPdfBytes())
) {
log.info("[{}]载入PDDocument耗时:{}",
LOG_PERFIX, System.currentTimeMillis() - startTime);
PDFRenderer renderer = new PDFRenderer(doc);
for (int i = task.start; i <= task.end; i++) {
recordTransferedImage(result, renderSinglePage(task, renderer, i), i);
}
} catch (Exception e) {
log.error("[{}]渲染PDF异常, task:{}, e:",
LOG_PERFIX, task, e);
result = buildFailedResult(task);
} finally {
log.info("[{}]渲染PDF完成, task:{}, result:{}, cost:{}",
LOG_PERFIX, task, result,
System.currentTimeMillis() - startTime);
}
return result;
}
/**
* 初始化RenderResult
*
* @param task
* @return
*/
private static RenderResult initResult(RenderTask task) {
return new RenderResult()
.setTraceId(task.traceId)
.setTotalPageCount(getPageCountByRange(task.start, task.end));
}
/**
* 记录单页渲染结果
*
* @param result
* @param image
* @param pageIndex
*/
private static void recordTransferedImage(RenderResult result, byte[] image, int pageIndex) {
if (image == null) {
// 渲染失败
result.failedPages.add(pageIndex);
result.failedPageCount++;
} else {
// 渲染成功
result.images.put(pageIndex, image);
result.successPageCount++;
}
}
/**
* 渲染单页
*
* @param task
* @param renderer
* @param pageIndex
* @return
*/
private static byte[] renderSinglePage(RenderTask task, PDFRenderer renderer, int pageIndex) {
try {
// 渲染第一页,则这里传入的pageIndex需要减1
return transformImage(renderer.renderImageWithDPI(pageIndex - 1, IMAGE_DPI));
} catch (Exception e) {
log.error("[{}]渲染单页异常, pageIndex:{}, traceId:{}, e:",
LOG_PERFIX, pageIndex, task.getTraceId(), e);
return null;
}
}
/**
* BufferedImage -> byte[]
*
* @param bim
* @return
* @throws IOException
*/
private static byte[] transformImage(BufferedImage bim) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bim, IMAGE_FORMAT, os);
return os.toByteArray();
}
/**
* byte[] -> PDDocument
*
* @param docBytes
* @return
* @throws IOException
*/
private static PDDocument load(byte[] docBytes) throws IOException {
return PDDocument.load(new ByteArrayInputStream(docBytes),
MemoryUsageSetting.setupTempFileOnly());
}
/**
* 渲染主流程失败时,直接构建失败的result
*
* @param task
* @return
*/
private static RenderResult buildFailedResult(RenderTask task) {
return new RenderResult()
.setImages(Collections.emptyMap())
.setFailedPages(IntStream.rangeClosed(task.start, task.end)
.boxed()
.collect(Collectors.toList()))
.setTotalPageCount(getPageCountByRange(task.start, task.end))
.setTraceId(task.traceId);
}
/**
* 根据页码范围获取页数
*
* @param start
* @param end
* @return
*/
private static int getPageCountByRange(int start, int end) {
return end - start + 1;
}
}
{code}
And here is my unit test code:
{code:java}
package com.bytedance.esign.pdfrender.handler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
/**
* @author jiangpeiheng create on 2020/4/27
*/
@Slf4j
public class RenderHandlerTest {
private static final String BASE_DIR_PATH = "/Users/jiangpeiheng/myhome/work_stuff/esign/optimize/pdfrender/";
private static final String OUTPUT_DIR_PATH = BASE_DIR_PATH + "output/";
private static final String INPUT_PDF_PATH = BASE_DIR_PATH + "bit_coin.pdf";
private static final String OUTPUT_PIC_PATH_PREFIX = OUTPUT_DIR_PATH + "output_pic_";
@Test
public void renderTest() throws Exception {
byte[] input = IOUtils.toByteArray(new FileInputStream(INPUT_PDF_PATH));
RenderHandler.RenderTask task = new RenderHandler.RenderTask()
.setPdfBytes(input)
.setTraceId("test-trace")
.setStart(1)
.setEnd(20);
RenderHandler.RenderResult result = RenderHandler.render(task);
result.getImages().forEach((pageIndex, image) -> {
try (
FileOutputStream fos = new FileOutputStream(OUTPUT_PIC_PATH_PREFIX + pageIndex + ".jpg");
) {
fos.write(image);
} catch (Exception e) {
log.error("output process error");
}
});
}
}
{code}
I'm looking forward to your kindly response.
Thank you
Jiang Peiheng
--
This message was sent by Atlassian Jira
(v8.3.4#803005)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@pdfbox.apache.org
For additional commands, e-mail: dev-help@pdfbox.apache.org