package org.rr.jeborker.converter;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.rr.commons.mufs.IResourceHandler;
import org.rr.commons.mufs.MimeUtils;
import org.rr.commons.mufs.ResourceHandlerFactory;
import org.rr.commons.mufs.ResourceHandlerUtils;
import org.rr.commons.utils.compression.truezip.TrueZipUtils;
import org.rr.jeborker.app.JeboorkerConstants;
import org.rr.jeborker.app.JeboorkerConstants.SUPPORTED_MIMES;
import org.rr.jeborker.app.preferences.APreferenceStore;
import org.rr.jeborker.app.preferences.PreferenceStoreFactory;
import org.rr.jeborker.gui.ConverterPreferenceController;
import org.rr.jeborker.gui.MainController;
import org.rr.pm.image.ImageUtils;
import com.jmupdf.interfaces.Page;
import com.jmupdf.interfaces.PagePixels;
import com.jmupdf.page.PageRect;
public class PdfToCBZConverter implements IEBookConverter {
private static String IMAGE_QUALITY_LABEL = Bundle.getString("MultipleConverter.imageQuality.label");
private static String IMAGE_QUALITY_KEY = PdfToCBZConverter.class.getName() + "." + IMAGE_QUALITY_LABEL;
private APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE);
private IResourceHandler pdfResource;
private ConverterPreferenceController converterPreferenceController;
public PdfToCBZConverter(IResourceHandler pdfResource) {
this.pdfResource = pdfResource;
}
/**
* Renders a page of the given pdf data.
* @param pdfdata The pdf bytes.
* @param pageNumber The page number to be rendered starting with 1.
* @return The rendered pdf data or <code>null</code> if the pdf could not be rendered.
* @throws IOException
*/
private List<byte[]> renderPage(ConverterPreferenceController converterPreferenceDialog, com.jmupdf.pdf.PdfDocument doc, int pageNumber) throws Exception {
PagePixels pp = null;
Page page = null;
PageRect bb = null;
try {
page = doc.getPage(pageNumber);
pp = page.getPagePixels();
bb = page.getBoundBox();
pp.getOptions().setRotate(Page.PAGE_ROTATE_NONE);
pp.getOptions().setZoom(1.5f);
pp.drawPage(null, bb.getX0(), bb.getY0(), bb.getX1(), bb.getY1());
BufferedImage image = pp.getImage();
List<BufferedImage> processImageModifications = ConverterUtils.processImageModifications(image, getImageQuality(), converterPreferenceDialog);
List<byte[]> result = new ArrayList<byte[]>(processImageModifications.size());
for(BufferedImage processedImage : processImageModifications) {
byte[] imageBytes = ImageUtils.getImageBytes(processedImage, MimeUtils.MIME_JPEG);
result.add(imageBytes);
}
return result;
} finally {
if (pp != null) {
pp.dispose();
}
}
}
@Override
public IResourceHandler convert() throws IOException {
ConverterPreferenceController converterPreferenceDialog = getConverterPreferenceController();
if(converterPreferenceDialog.isConfirmed()) {
IResourceHandler targetCbzResource = ResourceHandlerFactory.getUniqueResourceHandler(pdfResource, "cbz");
com.jmupdf.pdf.PdfDocument doc = null;
try {
doc = new com.jmupdf.pdf.PdfDocument(pdfResource.getContent());
int pageCount = doc.getPageCount();
for(int pageNumber = 0, additional = 0; pageNumber < pageCount; pageNumber++) {
List<byte[]> renderedPages = renderPage(converterPreferenceDialog, doc, pageNumber + 1);
for(int i = 0; i < renderedPages.size(); i++) {
if(i > 0) {
additional++;
}
byte[] renderedPage = renderedPages.get(i);
TrueZipUtils.add(targetCbzResource, getFileName(pageNumber + additional, pageCount), new ByteArrayInputStream(renderedPage));
}
}
} catch(IOException e) {
throw e;
} catch(Exception e) {
throw new IOException("Failed to convert PDF " + pdfResource.getName(), e);
} finally {
if (doc != null) {
doc.dispose();
doc = null;
}
}
ConverterUtils.transferMetadata(pdfResource, targetCbzResource);
preferenceStore.addGenericEntryAsNumber(IMAGE_QUALITY_KEY, getImageQuality());
return targetCbzResource;
}
return null;
}
@Override
public SUPPORTED_MIMES getConversionSourceType() {
return JeboorkerConstants.SUPPORTED_MIMES.MIME_PDF;
}
@Override
public SUPPORTED_MIMES getConversionTargetType() {
return JeboorkerConstants.SUPPORTED_MIMES.MIME_CBZ;
}
private String getFileName(int pageNumber, int pageCount) {
String name = ResourceHandlerUtils.getFileNameWithoutFileExtension(pdfResource);
String pattern = StringUtils.repeat("0", String.valueOf(pageCount).length());
DecimalFormat format = new DecimalFormat(pattern);
String formattedPageNumber = format.format(pageNumber);
return formattedPageNumber + "_" + name + ".jpg";
}
/**
* Gets the {@link ConverterPreferenceController} for this instance. Creates a new
* {@link ConverterPreferenceController} if no one is created previously.
* @see #createConverterPreferenceController()
*/
private ConverterPreferenceController getConverterPreferenceController() {
if(this.converterPreferenceController == null) {
this.converterPreferenceController = this.createConverterPreferenceController();
}
if(!this.converterPreferenceController.hasShown()) {
this.converterPreferenceController.showPreferenceDialog();
}
return this.converterPreferenceController;
}
/**
* Create a new {@link ConverterPreferenceController} instance.
*/
public ConverterPreferenceController createConverterPreferenceController() {
ConverterPreferenceController preferenceController = MainController.getController().getConverterPreferenceController();
preferenceController.addCommonSlider(IMAGE_QUALITY_LABEL, preferenceStore.getGenericEntryAsNumber(IMAGE_QUALITY_KEY, 100).intValue());
preferenceController.setShowLandscapePageEntries(true);
return preferenceController;
}
private int getImageQuality() {
return getConverterPreferenceController().getCommonValueAsInt(IMAGE_QUALITY_LABEL);
}
public void setConverterPreferenceController(ConverterPreferenceController controller) {
this.converterPreferenceController = controller;
}
public static void main(String[] args) {
System.out.println(StringUtils.repeat("0", String.valueOf(101).length()));
}
}