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:58:00 UTC
[jira] [Updated] (PDFBOX-4820) Multiplying two matrices produces
illegal values
[ https://issues.apache.org/jira/browse/PDFBOX-4820?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
jiangpeiheng updated PDFBOX-4820:
---------------------------------
Description:
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:
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
was:
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
> 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
> Priority: Major
> 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:
> 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