Fixed a NPE when a mask is null in BitmapImage.java Add support for properly encoding binary data as a hexadecimal string object (including encryption). Adjust palette generation for indexed bitmaps to work correctly with encryption. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ImagePackageRedesign@611133 13f79535-47bb-0310-9956-ffa450edef68Temp_ImagePackageRedesign
@@ -56,7 +56,9 @@ public class BitmapImage implements PDFImage { | |||
this.bitsPerComponent = 8; | |||
this.colorSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB); | |||
this.bitmaps = data; | |||
maskRef = new PDFReference(mask); | |||
if (mask != null) { | |||
maskRef = new PDFReference(mask); | |||
} | |||
} | |||
/** |
@@ -276,14 +276,23 @@ public abstract class PDFObject implements PDFWritable { | |||
*/ | |||
protected byte[] encodeString(String string) { | |||
return encodeText(string); | |||
/* | |||
final byte[] buf = encode(PDFText.escapeString(string)); | |||
} | |||
/** | |||
* Encodes binary data as hexadecimal string object. | |||
* @param data the binary data | |||
* @param out the OutputStream to write the encoded object to | |||
* @throws IOException if an I/O error occurs | |||
*/ | |||
protected void encodeBinaryToHexString(byte[] data, OutputStream out) throws IOException { | |||
out.write('<'); | |||
if (getDocumentSafely().isEncryptionActive()) { | |||
return PDFText.escapeByteArray( | |||
getDocument().getEncryption().encrypt(buf, this)); | |||
} else { | |||
return buf; | |||
}*/ | |||
data = getDocument().getEncryption().encrypt(data, this); | |||
} | |||
String hex = PDFText.toHex(data, false); | |||
byte[] encoded = hex.getBytes("US-ASCII"); | |||
out.write(encoded); | |||
out.write('>'); | |||
} | |||
/** | |||
@@ -307,6 +316,9 @@ public abstract class PDFObject implements PDFWritable { | |||
} | |||
} else if (obj instanceof Boolean) { | |||
writer.write(obj.toString()); | |||
} else if (obj instanceof byte[]) { | |||
writer.flush(); | |||
encodeBinaryToHexString((byte[])obj, out); | |||
} else { | |||
writer.flush(); | |||
out.write(encodeText(obj.toString())); |
@@ -51,6 +51,9 @@ public class PDFReference implements PDFWritable { | |||
* @param ref an object reference | |||
*/ | |||
public PDFReference(String ref) { | |||
if (ref == null) { | |||
throw new NullPointerException("ref must not be null"); | |||
} | |||
this.indirectReference = ref; | |||
} | |||
@@ -25,12 +25,12 @@ import org.apache.avalon.framework.CascadingRuntimeException; | |||
/** | |||
* This class represents a simple number object. It also contains contains some | |||
* utility methods for outputing numbers to PDF. | |||
* utility methods for outputting numbers to PDF. | |||
*/ | |||
public class PDFText extends PDFObject { | |||
private static final char[] DIGITS = | |||
{'0', '1', '2', '3', '4', '5', '6', '7', | |||
private static final char[] DIGITS | |||
= {'0', '1', '2', '3', '4', '5', '6', '7', | |||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | |||
private String text; | |||
@@ -145,19 +145,33 @@ public class PDFText extends PDFObject { | |||
/** | |||
* Converts a byte array to a Hexadecimal String (3.2.3 in PDF 1.4 specs) | |||
* @param data the data to encode | |||
* @param brackets true if enclosing brackets should be included | |||
* @return String the resulting string | |||
*/ | |||
public static final String toHex(byte[] data) { | |||
public static final String toHex(byte[] data, boolean brackets) { | |||
final StringBuffer sb = new StringBuffer(data.length * 2); | |||
sb.append("<"); | |||
if (brackets) { | |||
sb.append("<"); | |||
} | |||
for (int i = 0; i < data.length; i++) { | |||
sb.append(DIGITS[(data[i] >>> 4) & 0x0F]); | |||
sb.append(DIGITS[data[i] & 0x0F]); | |||
} | |||
sb.append(">"); | |||
if (brackets) { | |||
sb.append(">"); | |||
} | |||
return sb.toString(); | |||
} | |||
/** | |||
* Converts a byte array to a Hexadecimal String (3.2.3 in PDF 1.4 specs) | |||
* @param data the data to encode | |||
* @return String the resulting string | |||
*/ | |||
public static final String toHex(byte[] data) { | |||
return toHex(data, true); | |||
} | |||
/** | |||
* Converts a String to UTF-16 (big endian). | |||
* @param text text to convert |
@@ -25,6 +25,7 @@ import java.awt.image.RenderedImage; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import org.apache.commons.io.output.ByteArrayOutputStream; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
@@ -41,7 +42,6 @@ import org.apache.fop.pdf.PDFFilter; | |||
import org.apache.fop.pdf.PDFFilterList; | |||
import org.apache.fop.pdf.PDFName; | |||
import org.apache.fop.pdf.PDFReference; | |||
import org.apache.fop.pdf.PDFWritable; | |||
/** | |||
* PDFImage implementation for the PDF renderer which handles RenderedImages. | |||
@@ -176,11 +176,6 @@ public class ImageRenderedAdapter extends AbstractImageAdapter { | |||
return maskRef; | |||
} | |||
/** {@inheritDoc} */ | |||
public String getSoftMask() { | |||
return softMask.toInlinePDFString(); | |||
} | |||
/** {@inheritDoc} */ | |||
public PDFReference getSoftMaskReference() { | |||
return softMask; | |||
@@ -203,7 +198,7 @@ public class ImageRenderedAdapter extends AbstractImageAdapter { | |||
ColorModel cm = getEffectiveColorModel(); | |||
if (cm instanceof IndexColorModel) { | |||
IndexColorModel icm = (IndexColorModel)cm; | |||
PDFArray indexed = new PDFArray(); | |||
PDFArray indexed = new PDFArray(dict); | |||
indexed.add(new PDFName("Indexed")); | |||
if (icm.getColorSpace().getType() != ColorSpace.TYPE_RGB) { | |||
@@ -219,30 +214,25 @@ public class ImageRenderedAdapter extends AbstractImageAdapter { | |||
throw new UnsupportedOperationException("hival must not go beyond " + MAX_HIVAL); | |||
} | |||
indexed.add(new Integer(hival)); | |||
final StringBuffer sb = new StringBuffer("<"); | |||
int[] palette = new int[c]; | |||
icm.getRGBs(palette); | |||
ByteArrayOutputStream baout = new ByteArrayOutputStream(); | |||
for (int i = 0; i < c; i++) { | |||
if (i > 0) { | |||
sb.append(" "); | |||
} | |||
//TODO Probably doesn't work for non RGB based color spaces | |||
rgb2Hex(palette[i], sb); | |||
//See log warning above | |||
int entry = palette[i]; | |||
baout.write((entry & 0xFF0000) >> 16); | |||
baout.write((entry & 0xFF00) >> 8); | |||
baout.write(entry & 0xFF); | |||
} | |||
sb.append(">"); | |||
indexed.add(new PDFWritable() { | |||
public String toInlinePDFString() { | |||
//Work-around String escaping. Maybe a little hacky. | |||
return sb.toString(); | |||
} | |||
}); | |||
indexed.add(baout.toByteArray()); | |||
dict.put("ColorSpace", indexed); | |||
dict.put("BitsPerComponent", icm.getPixelSize()); | |||
Integer index = getIndexOfFirstTransparentColorInPalette(getImage().getRenderedImage()); | |||
if (index != null) { | |||
PDFArray mask = new PDFArray(); | |||
PDFArray mask = new PDFArray(dict); | |||
mask.add(index); | |||
mask.add(index); | |||
dict.put("Mask", mask); | |||
@@ -250,19 +240,6 @@ public class ImageRenderedAdapter extends AbstractImageAdapter { | |||
} | |||
} | |||
private static final char[] HEX = { | |||
'0', '1', '2', '3', '4', '5', '6', '7', | |||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | |||
}; | |||
private static void rgb2Hex(int rgb, StringBuffer sb) { | |||
for (int i = 5; i >= 0; i--) { | |||
int shift = i * 4; | |||
int n = (rgb & (15 << shift)) >> shift; | |||
sb.append(HEX[n % 16]); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public String getFilterHint() { | |||
return PDFFilterList.IMAGE_FILTER; |
@@ -39,11 +39,9 @@ import java.util.Map; | |||
import javax.xml.transform.Source; | |||
import javax.xml.transform.stream.StreamSource; | |||
import org.w3c.dom.Document; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.io.output.CountingOutputStream; | |||
import org.apache.xmlgraphics.image.loader.ImageException; | |||
import org.apache.xmlgraphics.image.loader.ImageInfo; | |||
import org.apache.xmlgraphics.image.loader.ImageManager; | |||
import org.apache.xmlgraphics.image.loader.ImageSessionContext; |
@@ -36,8 +36,6 @@ import java.util.Map; | |||
import javax.xml.transform.Source; | |||
import org.w3c.dom.Document; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
@@ -65,6 +63,8 @@ import org.apache.xmlgraphics.ps.PSResource; | |||
import org.apache.xmlgraphics.ps.PSState; | |||
import org.apache.xmlgraphics.ps.dsc.DSCException; | |||
import org.apache.xmlgraphics.ps.dsc.ResourceTracker; | |||
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox; | |||
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentHiResBoundingBox; | |||
import org.apache.fop.apps.FOPException; | |||
import org.apache.fop.apps.FOUserAgent; |