Support for PDF (1st page)
This commit is contained in:
parent
c46cd2e3fe
commit
6f674599da
3 changed files with 124 additions and 36 deletions
11
pom.xml
11
pom.xml
|
|
@ -237,6 +237,17 @@
|
|||
<version>3.9.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox-io</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
|
|
|
|||
|
|
@ -6,11 +6,7 @@ import java.io.IOException;
|
|||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.*;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
|
|
@ -19,6 +15,11 @@ import javax.imageio.stream.ImageInputStream;
|
|||
|
||||
import com.drew.imaging.ImageMetadataReader;
|
||||
import com.drew.imaging.ImageProcessingException;
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.forkalsrud.album.db.DirectoryProps;
|
||||
import org.forkalsrud.album.video.MovieMetadataGenerator;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -91,6 +92,9 @@ public class DirectoryMetadataGenerator {
|
|||
} else if (name.endsWith(".mov") || name.endsWith(".MOV") || name.endsWith(".mp4") || name.endsWith(".m4v") || name.endsWith(".avi")) {
|
||||
Map<String, String> p = movieMetadataGenerator.generateVideoProperties(f);
|
||||
addPropsForFile(props, f, p);
|
||||
} else if (name.endsWith(".pdf")) {
|
||||
Map<String, String> p = generatePdfProperties(f);
|
||||
addPropsForFile(props, f, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -229,4 +233,34 @@ public class DirectoryMetadataGenerator {
|
|||
iis.close();
|
||||
return new Dimension(img.getWidth(), img.getHeight());
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Map<String, String> generatePdfProperties(File file) throws IOException {
|
||||
|
||||
HashMap<String, String> props = new HashMap<>();
|
||||
|
||||
String name = file.getName();
|
||||
props.put("etag", Integer.toHexString(name.hashCode() + Long.valueOf(file.lastModified()).hashCode()));
|
||||
|
||||
try (PDDocument document = Loader.loadPDF(new RandomAccessReadBufferedFile(file))) {
|
||||
|
||||
PDPage page = document.getPage(0);
|
||||
PDRectangle rect = page.getMediaBox();
|
||||
|
||||
|
||||
int width = Math.round(rect.getWidth());
|
||||
int height = Math.round(rect.getHeight());
|
||||
props.put("dimensions", new Dimension(width, height).toString());
|
||||
props.put("orientation", "1");
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
|
||||
Calendar cal = document.getDocumentInformation().getCreationDate();
|
||||
Date date = cal != null ? cal.getTime() : new Date(file.lastModified());
|
||||
props.put("captureDate", sdf.format(date));
|
||||
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,15 @@ import javax.imageio.ImageWriteParam;
|
|||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.cos.COSDocument;
|
||||
import org.apache.pdfbox.io.RandomAccessRead;
|
||||
import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
|
||||
import org.apache.pdfbox.io.RandomAccessReadMemoryMappedFile;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
import org.forkalsrud.album.exif.Dimension;
|
||||
import org.forkalsrud.album.exif.Thumbnail;
|
||||
|
||||
|
|
@ -85,7 +94,10 @@ public class PictureScaler {
|
|||
|
||||
@Override
|
||||
public CachedImage call() throws Exception {
|
||||
try {
|
||||
try {
|
||||
if (file.getName().endsWith(".pdf")) {
|
||||
return renderPdf(file, thumbnail, size);
|
||||
}
|
||||
return scalePictureReally(file, thumbnail, size);
|
||||
} catch (Exception e) {
|
||||
log.error("sadness: " + file.getAbsolutePath(), e);
|
||||
|
|
@ -151,11 +163,11 @@ public class PictureScaler {
|
|||
* @param size
|
||||
* @throws IOException
|
||||
*/
|
||||
CachedImage scalePictureReally(File file, Thumbnail thumbnail, String size) throws IOException {
|
||||
CachedImage scalePictureReally(File file, Thumbnail thumbnail, String size) throws IOException {
|
||||
|
||||
Dimension orig = thumbnail.getSize();
|
||||
Dimension outd = orig.scale(size);
|
||||
|
||||
|
||||
/* In order to make the quality as good as possible we follow the advice from
|
||||
* http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
|
||||
* and scale the image by a factor of 2 in intermediate steps, thereby getting a smoother
|
||||
|
|
@ -174,7 +186,7 @@ public class PictureScaler {
|
|||
// on pictures with each orientation.
|
||||
//
|
||||
// 1 2 3 4 5 6 7 8
|
||||
//
|
||||
//
|
||||
// 888888 888888 88 88 8888888888 88 88 8888888888
|
||||
// 88 88 88 88 88 88 88 88 88 88 88 88
|
||||
// 8888 8888 8888 8888 88 8888888888 8888888888 88
|
||||
|
|
@ -185,46 +197,50 @@ public class PictureScaler {
|
|||
// The last four are obtained by rotating 90 degrees and then flipping X and/or Y.
|
||||
//
|
||||
|
||||
double[] flipX = new double[] { +1, -1, -1, +1, -1, +1, +1, -1 };
|
||||
double[] flipY = new double[] { +1, +1, -1, -1, +1, +1, -1, -1 };
|
||||
double[] flipX = new double[]{ +1, -1, -1, +1, -1, +1, +1, -1 };
|
||||
double[] flipY = new double[]{ +1, +1, -1, -1, +1, +1, -1, -1 };
|
||||
int idx = thumbnail.getOrientation() - 1;
|
||||
|
||||
// Recalculate scale after sub-sampling was applied
|
||||
double scale;
|
||||
AffineTransform xform = new AffineTransform();
|
||||
// Recalculate scale after sub-sampling was applied
|
||||
double scale;
|
||||
AffineTransform xform = new AffineTransform();
|
||||
boolean rotate = idx >= 4;
|
||||
|
||||
xform.translate(intermediate.getWidth() / 2d, intermediate.getHeight() / 2d);
|
||||
if (rotate) {
|
||||
xform.rotate(Math.PI / 2);
|
||||
scale = (double)intermediate.getHeight() / img.getWidth();
|
||||
xform.rotate(Math.PI / 2);
|
||||
scale = (double) intermediate.getHeight() / img.getWidth();
|
||||
} else {
|
||||
scale = (double)intermediate.getWidth() / img.getWidth();
|
||||
scale = (double) intermediate.getWidth() / img.getWidth();
|
||||
}
|
||||
xform.scale(scale, scale);
|
||||
xform.scale(flipX[idx], flipY[idx]);
|
||||
xform.translate(-img.getWidth() / 2d, -img.getHeight() / 2d);
|
||||
|
||||
int imgType = img.getType() > 0 ? img.getType() : BufferedImage.TYPE_INT_RGB;
|
||||
BufferedImage buf2 = new BufferedImage(intermediate.getWidth(), intermediate.getHeight(), imgType);
|
||||
Graphics2D g2 = buf2.createGraphics();
|
||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
|
||||
g2.transform(xform);
|
||||
g2.drawImage(img, 0, 0, null);
|
||||
img = null;
|
||||
int imgType = img.getType() > 0 ? img.getType() : BufferedImage.TYPE_INT_RGB;
|
||||
BufferedImage buf2 = new BufferedImage(intermediate.getWidth(), intermediate.getHeight(), imgType);
|
||||
Graphics2D g2 = buf2.createGraphics();
|
||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
|
||||
while (intermediate.getWidth() > outd.getWidth()) {
|
||||
|
||||
BufferedImage buf3 = buf2;
|
||||
intermediate = intermediate.halved();
|
||||
buf2 = new BufferedImage(intermediate.getWidth(), intermediate.getHeight(), imgType);
|
||||
g2 = buf2.createGraphics();
|
||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
g2.drawImage(buf3, 0, 0, intermediate.getWidth(), intermediate.getHeight(), null);
|
||||
}
|
||||
g2.transform(xform);
|
||||
g2.drawImage(img, 0, 0, null);
|
||||
img = null;
|
||||
|
||||
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
|
||||
while (intermediate.getWidth() > outd.getWidth()) {
|
||||
|
||||
BufferedImage buf3 = buf2;
|
||||
intermediate = intermediate.halved();
|
||||
buf2 = new BufferedImage(intermediate.getWidth(), intermediate.getHeight(), imgType);
|
||||
g2 = buf2.createGraphics();
|
||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
g2.drawImage(buf3, 0, 0, intermediate.getWidth(), intermediate.getHeight(), null);
|
||||
}
|
||||
return encoded(buf2, file.lastModified());
|
||||
}
|
||||
|
||||
|
||||
private CachedImage encoded(BufferedImage buf2, long lastModifiedTs) throws IOException {
|
||||
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
|
||||
ImageWriter writer = writers.next();
|
||||
ImageWriteParam writeParam = writer.getDefaultWriteParam();
|
||||
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||
|
|
@ -241,10 +257,37 @@ public class PictureScaler {
|
|||
ios.flush();
|
||||
|
||||
CachedImage cimg = new CachedImage();
|
||||
cimg.lastModified = file.lastModified();
|
||||
cimg.lastModified = lastModifiedTs;
|
||||
cimg.mimeType = "image/jpeg";
|
||||
cimg.bits = bits.toByteArray();
|
||||
return cimg;
|
||||
}
|
||||
|
||||
|
||||
CachedImage renderPdf(File file, Thumbnail thumbnail, String size) throws IOException {
|
||||
|
||||
|
||||
Dimension orig = thumbnail.getSize();
|
||||
Dimension dim = orig.scale(size);
|
||||
|
||||
|
||||
|
||||
try (PDDocument document = Loader.loadPDF(new RandomAccessReadBufferedFile(file))) {
|
||||
|
||||
PDPage page = document.getPage(0);
|
||||
PDRectangle rect = page.getMediaBox();
|
||||
|
||||
|
||||
float width = rect.getWidth() / 72; // inches
|
||||
float targetWidth = dim.getWidth(); // pixels
|
||||
|
||||
PDFRenderer renderer = new PDFRenderer(document);
|
||||
BufferedImage image = renderer.renderImageWithDPI(0, targetWidth / width);
|
||||
|
||||
|
||||
return encoded(image, file.lastModified());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue