/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.syncope.client.console.wicket.markup.html.form.preview;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.syncope.client.console.annotations.BinaryPreview;
import org.apache.wicket.Component;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.image.NonCachingImage;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.request.resource.DynamicImageResource;
import org.apache.wicket.request.resource.IResource;
import org.apache.wicket.util.io.IOUtils;
import org.apache.wicket.util.time.Time;
@BinaryPreview(mimeTypes = { "application/pdf" })
public class BinaryPDFPreviewer extends AbstractBinaryPreviewer {
private static final long serialVersionUID = -6606409541566687016L;
private static final int IMG_SIZE = 300;
private static final float RESOLUTION = 96;
private static final ImageType IMAGE_TYPE = ImageType.RGB;
private transient BufferedImage firstPage;
public BinaryPDFPreviewer(final String id, final String mimeType) {
super(id, mimeType);
}
@Override
public Component preview(final byte[] uploadedBytes) {
firstPage = null;
PDDocument document = null;
try {
document = PDDocument.load(new ByteArrayInputStream(uploadedBytes));
if (document.isEncrypted()) {
LOG.info("Document is encrypted, no preview is possible");
} else {
firstPage = new PDFRenderer(document).renderImage(0, RESOLUTION, IMAGE_TYPE);
}
} catch (IOException e) {
LOG.error("While generating thumbnail from first page", e);
} finally {
IOUtils.closeQuietly(document);
}
Fragment fragment;
if (firstPage == null) {
fragment = new Fragment("preview", "noPreviewFragment", this);
} else {
fragment = new Fragment("preview", "previewFragment", this);
fragment.add(new NonCachingImage("previewImage", new ThumbnailImageResource(firstPage)));
}
WebMarkupContainer previewContainer = new WebMarkupContainer("previewContainer");
previewContainer.setOutputMarkupId(true);
previewContainer.add(fragment);
return this.addOrReplace(previewContainer);
}
private static class ThumbnailImageResource extends DynamicImageResource implements Serializable {
private static final long serialVersionUID = 923201517955737928L;
private final transient BufferedImage image;
private transient byte[] thumbnail;
ThumbnailImageResource(final BufferedImage image) {
this.image = image;
}
@Override
protected byte[] getImageData(final IResource.Attributes attributes) {
if (thumbnail == null) {
thumbnail = toImageData(getScaledImageInstance());
setLastModifiedTime(Time.now());
}
return thumbnail;
}
private BufferedImage getScaledImageInstance() {
int originalWidth = image.getWidth();
int originalHeight = image.getHeight();
if ((originalWidth > IMG_SIZE) || (originalHeight > IMG_SIZE)) {
final int newWidth;
final int newHeight;
if (originalWidth > originalHeight) {
newWidth = IMG_SIZE;
newHeight = (IMG_SIZE * originalHeight) / originalWidth;
} else {
newWidth = (IMG_SIZE * originalWidth) / originalHeight;
newHeight = IMG_SIZE;
}
// http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
BufferedImage dimg = new BufferedImage(newWidth, newHeight, image.getType());
Graphics2D g = dimg.createGraphics();
try {
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(image, 0, 0, newWidth, newHeight, 0, 0, originalWidth,
originalHeight, null);
} finally {
g.dispose();
}
return dimg;
}
// no need for resizing
return image;
}
}
}