nl.siegmann.epublib.bookprocessor.CoverpageBookProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of epublib-tools Show documentation
Show all versions of epublib-tools Show documentation
A java library for reading/writing/manipulating epub files
The newest version!
package nl.siegmann.epublib.bookprocessor;
import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import nl.siegmann.epublib.domain.Book;
import nl.siegmann.epublib.domain.Metadata;
import nl.siegmann.epublib.domain.Resource;
import nl.siegmann.epublib.domain.Resources;
import nl.siegmann.epublib.epub.BookProcessor;
import nl.siegmann.epublib.service.MediatypeService;
import nl.siegmann.epublib.util.CollectionUtil;
import nl.siegmann.epublib.util.ResourceUtil;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* If the book contains a cover image then this will add a cover page to the book.
* If the book contains a cover html page it will set that page's first image as the book's cover image.
*
* FIXME:
* will overwrite any "cover.jpg" or "cover.html" that are already there.
*
* @author paul
*
*/
public class CoverpageBookProcessor implements BookProcessor {
public static int MAX_COVER_IMAGE_SIZE = 999;
private static final Logger log = LoggerFactory.getLogger(CoverpageBookProcessor.class);
public static final String DEFAULT_COVER_PAGE_ID = "cover";
public static final String DEFAULT_COVER_PAGE_HREF = "cover.html";
public static final String DEFAULT_COVER_IMAGE_ID = "cover-image";
public static final String DEFAULT_COVER_IMAGE_HREF = "images/cover.png";
@Override
public Book processBook(Book book) {
Metadata metadata = book.getMetadata();
if(book.getCoverPage() == null && book.getCoverImage() == null) {
return book;
}
Resource coverPage = book.getCoverPage();
if (coverPage == null) {
coverPage = findCoverPage(book);
book.setCoverPage(coverPage);
}
Resource coverImage = book.getCoverImage();
if(coverPage == null) {
if(coverImage == null) {
// give up
} else { // coverImage != null
if(StringUtils.isBlank(coverImage.getHref())) {
coverImage.setHref(getCoverImageHref(coverImage, book));
}
String coverPageHtml = createCoverpageHtml(CollectionUtil.first(metadata.getTitles()), coverImage.getHref());
coverPage = new Resource(null, coverPageHtml.getBytes(), getCoverPageHref(book), MediatypeService.XHTML);
fixCoverResourceId(book, coverPage, DEFAULT_COVER_PAGE_ID);
}
} else { // coverPage != null
if(book.getCoverImage() == null) {
coverImage = getFirstImageSource(coverPage, book.getResources());
book.setCoverImage(coverImage);
if (coverImage != null) {
book.getResources().remove(coverImage.getHref());
}
} else { // coverImage != null
}
}
book.setCoverImage(coverImage);
book.setCoverPage(coverPage);
setCoverResourceIds(book);
return book;
}
// private String getCoverImageHref(Resource coverImageResource) {
// return "cover" + coverImageResource.getMediaType().getDefaultExtension();
// }
private Resource findCoverPage(Book book) {
if (book.getCoverPage() != null) {
return book.getCoverPage();
}
if (! (book.getSpine().isEmpty())) {
return book.getSpine().getResource(0);
}
return null;
}
private void setCoverResourceIds(Book book) {
if(book.getCoverImage() != null) {
fixCoverResourceId(book, book.getCoverImage(), DEFAULT_COVER_IMAGE_ID);
}
if(book.getCoverPage() != null) {
fixCoverResourceId(book, book.getCoverPage(), DEFAULT_COVER_PAGE_ID);
}
}
private void fixCoverResourceId(Book book, Resource resource, String defaultId) {
if (StringUtils.isBlank(resource.getId())) {
resource.setId(defaultId);
}
book.getResources().fixResourceId(resource);
}
private String getCoverPageHref(Book book) {
return DEFAULT_COVER_PAGE_HREF;
}
private String getCoverImageHref(Resource imageResource, Book book) {
return DEFAULT_COVER_IMAGE_HREF;
}
private Resource getFirstImageSource(Resource titlePageResource, Resources resources) {
try {
Document titlePageDocument = ResourceUtil.getAsDocument(titlePageResource);
NodeList imageElements = titlePageDocument.getElementsByTagName("img");
for (int i = 0; i < imageElements.getLength(); i++) {
String relativeImageHref = ((Element) imageElements.item(i)).getAttribute("src");
String absoluteImageHref = calculateAbsoluteImageHref(relativeImageHref, titlePageResource.getHref());
Resource imageResource = resources.getByHref(absoluteImageHref);
if (imageResource != null) {
return imageResource;
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
// package
static String calculateAbsoluteImageHref(String relativeImageHref,
String baseHref) {
if (relativeImageHref.startsWith("/")) {
return relativeImageHref;
}
String result = FilenameUtils.normalize(baseHref.substring(0, baseHref.lastIndexOf('/') + 1) + relativeImageHref, true);
return result;
}
private String createCoverpageHtml(String title, String imageHref) {
return "" +
"\n" +
"\n" +
"\t\n" +
"\t\tCover \n" +
"\t\t\n" +
"\t\n" +
"\t\n" +
"\t\t\n" +
"\t\t\t\n" +
"\t\t\n" +
"\t\n" +
"\n";
}
private Dimension calculateResizeSize(BufferedImage image) {
Dimension result;
if (image.getWidth() > image.getHeight()) {
result = new Dimension(MAX_COVER_IMAGE_SIZE, (int) (((double) MAX_COVER_IMAGE_SIZE / (double) image.getWidth()) * (double) image.getHeight()));
} else {
result = new Dimension((int) (((double) MAX_COVER_IMAGE_SIZE / (double) image.getHeight()) * (double) image.getWidth()), MAX_COVER_IMAGE_SIZE);
}
return result;
}
@SuppressWarnings("unused")
private byte[] createThumbnail(byte[] imageData) throws IOException {
BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(imageData));
Dimension thumbDimension = calculateResizeSize(originalImage);
BufferedImage thumbnailImage = createResizedCopy(originalImage, (int) thumbDimension.getWidth(), (int) thumbDimension.getHeight(), false);
ByteArrayOutputStream result = new ByteArrayOutputStream();
ImageIO.write(thumbnailImage, "png", result);
return result.toByteArray();
}
private BufferedImage createResizedCopy(java.awt.Image originalImage, int scaledWidth, int scaledHeight, boolean preserveAlpha) {
int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
Graphics2D g = scaledBI.createGraphics();
if (preserveAlpha) {
g.setComposite(AlphaComposite.Src);
}
g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
g.dispose();
return scaledBI;
}
}