Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decorations and multicolor background fix #42

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/main/java/net/sf/mcf2pdf/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import net.sf.mcf2pdf.mcfelements.util.ImageUtil;
import net.sf.mcf2pdf.mcfelements.util.PdfUtil;


Expand Down
11 changes: 9 additions & 2 deletions src/main/java/net/sf/mcf2pdf/Mcf2FoConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,6 @@ public void convert(File mcfFile, OutputStream xslFoOut, int dpi, boolean bindin
if (albumType == null)
throw new IOException("No album type definition found for used print product '" + book.getProductName() + "'");

// prepare page render context
context = new PageRenderContext(dpi, resources, albumType);

// create XSL-FO document
XslFoDocumentBuilder docBuilder = new XslFoDocumentBuilder();
Expand Down Expand Up @@ -201,8 +199,17 @@ public void convert(File mcfFile, OutputStream xslFoOut, int dpi, boolean bindin
else
rightCover = p;
}
// look for the background templates that contain hue and fading parameters
for (McfBackground bg : p.getBackgrounds()) {
if (bg.getTemplateName().matches("([a-zA-Z0-9_]+),hue=([0-9]+),fading=([0-9]+),normal(,.*)?")) {
resources.addMulticolorBackground(bg.getTemplateName(), tempImageDir);
}
}
}

// prepare page render context
context = new PageRenderContext(dpi, resources, albumType);

if (leftCover != null) {
log.info("Rendering cover...");
currentPage = new BitmapPageBuilder(coverPageWidth, coverPageHeight, context, tempImageDir);
Expand Down
120 changes: 105 additions & 15 deletions src/main/java/net/sf/mcf2pdf/mcfglobals/McfResourceScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@
*******************************************************************************/
package net.sf.mcf2pdf.mcfglobals;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
Expand All @@ -14,6 +23,10 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;

import org.apache.commons.digester3.Digester;
import org.apache.commons.io.IOUtils;
Expand All @@ -24,12 +37,13 @@
import net.sf.mcf2pdf.mcfconfig.Fading;
import net.sf.mcf2pdf.mcfconfig.Template;
import net.sf.mcf2pdf.mcfelements.impl.DigesterConfiguratorImpl;
import net.sf.mcf2pdf.mcfelements.util.ImageUtil;

/**
* "Dirty little helper" which scans installation directory and temporary
* directory of fotobook software for background images, cliparts, fonts,
* and masks (fadings). As there is no (known) usable TOC for these, we just
* take what we find.
* directory of fotobook software for background images, cliparts, fonts, and
* masks (fadings). As there is no (known) usable TOC for these, we just take
* what we find.
*/
public class McfResourceScanner {

Expand All @@ -49,6 +63,9 @@ public class McfResourceScanner {

private File foundBinding;

private int hue;
private int fading;

public McfResourceScanner(List<File> scanDirs) {
this.scanDirs.addAll(scanDirs);
}
Expand All @@ -72,27 +89,23 @@ private void scanDirectory(File dir) throws IOException {
if (nm.matches(".+\\.(jp(e?)g|webp|bmp)")) {
String id = nm.substring(0, nm.indexOf("."));
foundImages.put(id, f);
}
else if (nm.matches(".+\\.(clp|svg)")) {
} else if (nm.matches(".+\\.(clp|svg)")) {
String id = f.getName().substring(0, nm.lastIndexOf("."));
foundClips.put(id, f);
}
else if (nm.equals("1_color_backgrounds.xml")) {
} else if (nm.equals("1_color_backgrounds.xml")) {
log.debug("Processing 1-color backgrounds " + f.getAbsolutePath());
List<Template> colors = loadColorsMapping(f);
for (Template color : colors) {
File colorFile = new File(f.getParent() + '/' + color.getFilename());
foundColors.put(color.getName(), colorFile);
}
}
else if(nm.matches(".+\\.ttf")) {
} else if (nm.matches(".+\\.ttf")) {
Font font = loadFont(f);
foundFonts.put(font.getFamily(), font);
}
else if(nm.matches("normalbinding.*\\.png")) {
} else if (nm.matches("normalbinding.*\\.png")) {
foundBinding = f;
}
else if (nm.matches(".+\\.xml") && path.contains("/decorations/")) {
} else if (nm.matches(".+\\.xml")
&& (path.contains("/decorations/") || (path.contains("\\decorations\\")))) {
String id = f.getName().substring(0, nm.lastIndexOf("."));
List<Decoration> spec = loadDecoration(f);
if (spec.size() == 1) {
Expand All @@ -111,8 +124,7 @@ private static Font loadFont(File f) throws IOException {
return Font.createFont(Font.TRUETYPE_FONT, is);
} catch (FontFormatException e) {
throw new IOException(e);
}
finally {
} finally {
IOUtils.closeQuietly(is);
}
}
Expand Down Expand Up @@ -165,4 +177,82 @@ public Fading getDecoration(String id) {
return foundDecorations.get(id);
}

public void addMulticolorBackground(String templateName, File tempDir) throws IOException {

// typical templateName looks like: 357,hue=60,fading=2,normal ...
// files with names 357.webm etc are already loaded in foundImages
Pattern pattern = Pattern.compile("([a-zA-Z0-9_]+),hue=([0-9]+),fading=([0-9]+),normal(,.*)?");
Matcher matcher = pattern.matcher(templateName);
String id = "";
if (!matcher.find())
log.error("Error during parsing multicolor background. Template name: " + templateName);

// extract the parameters
if (matcher.groupCount() == 4) {
id = matcher.group(1);
if (matcher.group(2) != null) {
hue = Integer.parseInt(matcher.group(2));
}
if (matcher.group(3) != null) {
fading = Integer.parseInt(matcher.group(3));
}
log.debug("Multicolor background found. Parameters are: hue=" + hue + ", fading=" + fading);
}

String newFileName = id + "_" + hue + "_" + fading + ".png";


if (foundImages.get(newFileName) == null) {

// get the base file
File f = foundImages.get(id);
if (f != null) {

// change the hue and add fading
BufferedImage img = ImageUtil.readImage(f);
ImageFilter filter = new RGBImageFilter() {
@Override
public int filterRGB(int x, int y, int rgb) {
int alpha = (rgb & 0xff000000);
int red = (rgb & 0xff0000) >> 16;
int green = (rgb & 0x00ff00) >> 8;
int blue = (rgb & 0x0000ff);
float[] hsbvals = new float[3];

// convert from RGB to HSB and apply the fading if necessary
if (fading > 0)
Color.RGBtoHSB(red + (255 - red) / 4 * (fading + 1),
green + (255 - green) / 4 * (fading + 1), blue + (255 - blue) / 4 * (fading + 1),
hsbvals);
else
Color.RGBtoHSB(red, green, blue, hsbvals);

// apply the hue
int rgbOut = Color.HSBtoRGB(((float) hue) / 360, hsbvals[1], hsbvals[2]);
return alpha | rgbOut;
}
};

// apply the filter
ImageProducer prod = new FilteredImageSource(img.getSource(), filter);
Image filteredImage = Toolkit.getDefaultToolkit().createImage(prod);

// render the image
BufferedImage outputImage = new BufferedImage(filteredImage.getWidth(null),
filteredImage.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D bGr = outputImage.createGraphics();
bGr.drawImage(filteredImage, 0, 0, null);
bGr.dispose();

// write the image to file in the temp directory (same as pages are rendered to)
File tempFile = new File(tempDir + "\\" + newFileName);
ImageIO.write(outputImage, "png", tempFile);

// add the image to the list of found images (with the hue and fading parameters
// being part of the id)
foundImages.put(newFileName, tempFile);
}
}

}
}
68 changes: 44 additions & 24 deletions src/main/java/net/sf/mcf2pdf/pagebuild/PageBackground.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.sf.mcf2pdf.mcfelements.McfBackground;
import net.sf.mcf2pdf.mcfelements.util.ImageUtil;
import net.sf.mcf2pdf.mcfglobals.McfAlbumType;


public class PageBackground implements PageDrawable {

private List<? extends McfBackground> leftBg;

private List<? extends McfBackground> rightBg;

public PageBackground(List<? extends McfBackground> leftBg,
List<? extends McfBackground> rightBg) {
public PageBackground(List<? extends McfBackground> leftBg, List<? extends McfBackground> rightBg) {
this.leftBg = leftBg;
this.rightBg = rightBg;
}
Expand All @@ -40,8 +40,7 @@ public void renderAsSvgElement(Writer writer, PageRenderContext context) throws
}

@Override
public BufferedImage renderAsBitmap(PageRenderContext context,
Point drawOffsetPixels) throws IOException {
public BufferedImage renderAsBitmap(PageRenderContext context, Point drawOffsetPixels) throws IOException {
File fLeft = extractBackground(leftBg, context);
File fRight = extractBackground(rightBg, context);

Expand All @@ -50,17 +49,16 @@ public BufferedImage renderAsBitmap(PageRenderContext context,
float widthMM = (albumType.getUsableWidth() + albumType.getBleedMargin()) / 10.0f * 2;
float heightMM = (albumType.getUsableHeight() + albumType.getBleedMargin() * 2) / 10.0f;

BufferedImage img = new BufferedImage(context.toPixel(widthMM),
context.toPixel(heightMM), BufferedImage.TYPE_INT_ARGB);
BufferedImage img = new BufferedImage(context.toPixel(widthMM), context.toPixel(heightMM),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);

if (fLeft != null && fLeft.equals(fRight)) {
// draw the background image on whole page
drawBackground(fLeft, g2d, 0, 0, img.getWidth(), img.getHeight());
}
else {
} else {
// process background parts separate
if (fLeft != null)
drawBackground(fLeft, g2d, 0, 0, img.getWidth() / 2, img.getHeight());
Expand All @@ -78,41 +76,63 @@ private void drawBackground(File f, Graphics2D g2d, int x, int y, int width, int
throw new IOException("Could not read image file: " + f.getAbsolutePath());
}

float tgtRatio = width / (float)height;
float tgtRatio = width / (float) height;

float imgRatio = img.getWidth() / (float)img.getHeight();
float imgRatio = img.getWidth() / (float) img.getHeight();
float scale;
boolean xVar;

if (imgRatio > tgtRatio) {
// scale image Y to target Y
scale = height / (float)img.getHeight();
scale = height / (float) img.getHeight();
xVar = true;
}
else {
} else {
// scale image X to target X
scale = width / (float)img.getWidth();
scale = width / (float) img.getWidth();
xVar = false;
}

int sx = (int)(xVar ? ((img.getWidth() - (width / scale)) / 2) : 0);
int sy = (int)(xVar ? 0 : ((img.getHeight() - (height / scale)) / 2));
int sx = (int) (xVar ? ((img.getWidth() - (width / scale)) / 2) : 0);
int sy = (int) (xVar ? 0 : ((img.getHeight() - (height / scale)) / 2));

int sw = (int)(width / scale);
int sh = (int)(height / scale);
int sw = (int) (width / scale);
int sh = (int) (height / scale);

g2d.drawImage(img, x, y, x + width, y + height, sx, sy, sx + sw, sy + sh, null);
}

private File extractBackground(List<? extends McfBackground> bgs,
PageRenderContext context) throws IOException {
private File extractBackground(List<? extends McfBackground> bgs, PageRenderContext context) throws IOException {
for (McfBackground bg : bgs) {
String tn = bg.getTemplateName();
if (tn == null || !tn.matches("[a-zA-Z0-9_]+,normal(,.*)?"))
continue;

tn = tn.substring(0, tn.indexOf(","));
// enhanced pattern to cover the examples with hue and fading set
Pattern pattern = Pattern.compile("([a-zA-Z0-9_]+)(,hue=([0-9]+))?(,fading=([0-9]+))?,normal(,.*)?");
Matcher matcher = pattern.matcher(tn);
if (tn == null || !matcher.find())
continue;
boolean multicolorBg = false;
int hue = 0;
int fading = 0;

// extract the parameters
if (matcher.groupCount() == 6) {
tn = matcher.group(1);
if (matcher.group(3) != null) {
hue = Integer.parseInt(matcher.group(3));
multicolorBg = true;
}
if (matcher.group(5) != null) {
fading = Integer.parseInt(matcher.group(5));
multicolorBg = true;
}
if (multicolorBg)
context.getLog().debug("Multicolor background for page no. " + bg.getPage().getPageNr()
+ " parameters are: hue=" + hue + ", fading=" + fading);
}

if (multicolorBg) {
tn = tn + "_" + hue + "_" + fading + ".png";
}
File f = context.getBackgroundImage(tn);
if (f == null) {
f = context.getBackgroundColor(tn);
Expand Down