org.sejda.impl.sambox.component.PageImageWriter Maven / Gradle / Ivy
/*
* Copyright 2016 by Eduard Weissmann ([email protected]).
*
* This file is part of the Sejda source code
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package org.sejda.impl.sambox.component;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageOutputStream;
import org.apache.commons.io.FilenameUtils;
import org.sejda.core.support.io.IOUtils;
import org.sejda.model.exception.TaskIOException;
import org.sejda.model.input.FileSource;
import org.sejda.model.input.Source;
import org.sejda.model.input.SourceDispatcher;
import org.sejda.model.input.StreamSource;
import org.sejda.sambox.pdmodel.PDDocument;
import org.sejda.sambox.pdmodel.PDPage;
import org.sejda.sambox.pdmodel.PDPageContentStream;
import org.sejda.sambox.pdmodel.graphics.PDXObject;
import org.sejda.sambox.pdmodel.graphics.form.PDFormXObject;
import org.sejda.sambox.pdmodel.graphics.image.PDImageXObject;
import org.sejda.sambox.pdmodel.graphics.image.UnsupportedTiffImageException;
import org.sejda.sambox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.sejda.sambox.util.Matrix;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PageImageWriter {
private static final Logger LOG = LoggerFactory.getLogger(PageImageWriter.class);
private PDDocument document;
public PageImageWriter(PDDocument document) {
this.document = document;
}
public void append(PDPage page, PDImageXObject image, Point2D position, float width, float height,
PDExtendedGraphicsState gs, int rotation) throws TaskIOException {
write(page, image, position, width, height, PDPageContentStream.AppendMode.APPEND, gs, true, rotation);
}
public void append(PDPage page, PDFormXObject image, Point2D position, float width, float height,
PDExtendedGraphicsState gs, int rotation) throws TaskIOException {
write(page, image, position, width, height, PDPageContentStream.AppendMode.APPEND, gs, true, rotation);
}
public void prepend(PDPage page, PDImageXObject image, Point2D position, float width, float height,
PDExtendedGraphicsState gs, int rotation) throws TaskIOException {
write(page, image, position, width, height, PDPageContentStream.AppendMode.PREPEND, gs, false, rotation);
}
public void prepend(PDPage page, PDFormXObject image, Point2D position, float width, float height,
PDExtendedGraphicsState gs, int rotation) throws TaskIOException {
write(page, image, position, width, height, PDPageContentStream.AppendMode.PREPEND, gs, false, rotation);
}
private void write(PDPage page, PDXObject image, Point2D position, float width, float height,
PDPageContentStream.AppendMode mode, PDExtendedGraphicsState gs, boolean resetContext, int rotation)
throws TaskIOException {
try (PDPageContentStream contentStream = new PDPageContentStream(document, page, mode, true, resetContext)) {
AffineTransform at = new AffineTransform(width, 0, 0, height, (float) position.getX(), (float) position.getY());
if(rotation != 0) {
at.rotate(Math.toRadians(rotation));
}
if (image instanceof PDFormXObject) {
contentStream.drawImage((PDFormXObject) image, new Matrix(at), gs);
} else {
contentStream.drawImage((PDImageXObject) image, new Matrix(at), gs);
}
} catch (IOException e) {
throw new TaskIOException("An error occurred writing image to the page.", e);
}
}
public static PDImageXObject toPDXImageObject(Source> imageSource) throws TaskIOException {
return imageSource.dispatch(new SourceDispatcher() {
@Override
public PDImageXObject dispatch(FileSource source) throws TaskIOException {
try {
return createFromFile(source.getSource().getPath());
} catch (IOException e) {
throw new TaskIOException("An error occurred creating PDImageXObject from file source: " + imageSource.getName(), e);
}
}
@Override
public PDImageXObject dispatch(StreamSource source) throws TaskIOException {
try {
String extension = FilenameUtils.getExtension(source.getName());
File tmp = IOUtils.createTemporaryBuffer("." + extension);
try (FileOutputStream fos = new FileOutputStream(tmp)) {
org.apache.commons.io.IOUtils.copyLarge(source.getSource(), fos);
}
return createFromFile(tmp.getPath());
} catch (IOException e) {
throw new TaskIOException("An error occurred creating PDImageXObject from file source: " + imageSource.getName(), e);
}
}
});
}
public static PDImageXObject createFromFile(String filePath) throws TaskIOException, IOException {
try {
return PDImageXObject.createFromFile(filePath);
} catch (UnsupportedTiffImageException e) {
LOG.warn("Found unsupported TIFF compression, converting TIFF to JPEG: " + e.getMessage());
try {
return PDImageXObject.createFromFile(convertTiffToJpg(filePath));
} catch (UnsupportedOperationException ex) {
if (ex.getMessage().contains("alpha channel")) {
LOG.warn("Found alpha channel image, JPEG compression failed, converting TIFF to PNG");
return PDImageXObject.createFromFile(convertTiffToPng(filePath));
}
throw ex;
}
}
}
public static String convertTiffToJpg(String filePath) throws IOException, TaskIOException {
return convertImageTo(filePath, "jpeg");
}
public static String convertTiffToPng(String filePath) throws IOException, TaskIOException {
return convertImageTo(filePath, "png");
}
public static String convertImageTo(String filePath, String format) throws IOException, TaskIOException {
BufferedImage image = ImageIO.read(new File(filePath));
File tmpFile = IOUtils.createTemporaryBuffer("." + format);
ImageOutputStream outputStream = new FileImageOutputStream(tmpFile);
try {
ImageWriter writer = ImageIO.getImageWritersByFormatName(format).next();
writer.setOutput(outputStream);
ImageWriteParam param = writer.getDefaultWriteParam();
if (format.equals("jpeg")) {
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(1.0F);
}
writer.write(null, new IIOImage(image, null, null), param);
} finally {
org.apache.commons.io.IOUtils.closeQuietly(outputStream);
}
return tmpFile.getPath();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy