You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2010/06/19 17:39:44 UTC
svn commit: r956239 - in
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject:
CompositeImage.java PDJpeg.java PDPixelMap.java PDXObjectImage.java
Author: lehmi
Date: Sat Jun 19 15:39:42 2010
New Revision: 956239
URL: http://svn.apache.org/viewvc?rev=956239&view=rev
Log:
PDFBOX-323: added transparency/opacity for images. Patch by Neil McErlean (neil dot mcerlean at gmail dot com)
Added:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/CompositeImage.java
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDPixelMap.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDXObjectImage.java
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/CompositeImage.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/CompositeImage.java?rev=956239&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/CompositeImage.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/CompositeImage.java Sat Jun 19 15:39:42 2010
@@ -0,0 +1,104 @@
+/*
+ * 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.pdfbox.pdmodel.graphics.xobject;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSArray;
+
+
+/**
+ * This class is responsible for combining a base image with an SMask-based transparency
+ * image to form a composite image.
+ * See section 11.5 of the pdf specification for details on Soft Masks.
+ * <p/>
+ * Briefly however, an Smask is a supplementary greyscale image whose RGB-values define
+ * a transparency mask which, when combined appropriately with the base image,
+ * allows per-pixel transparency to be applied.
+ * <p/>
+ * Note that Smasks are not required for any image and if the smask is not present
+ * in the pdf file, the image will have no transparent pixels.
+ *
+ * @author Neil McErlean
+ */
+public class CompositeImage
+{
+ private BufferedImage baseImage;
+ private BufferedImage smaskImage;
+
+ /**
+ * Standard constructor.
+ * @param baseImage the base Image.
+ * @param smaskImage the transparency image.
+ *
+ */
+ public CompositeImage(BufferedImage baseImage, BufferedImage smaskImage)
+ {
+ this.baseImage = baseImage;
+ this.smaskImage = smaskImage;
+ }
+
+ /**
+ * This method applies the specified transparency mask to a given image and returns a new BufferedImage
+ * whose alpha values are computed from the transparency mask (smask) image.
+ */
+ public BufferedImage createMaskedImage(COSArray decodeArray) throws IOException
+ {
+ // The decode array should only be [0 1] or [1 0]. See PDF spec.
+ // [0 1] means the smask's RGB values give transparency. Default: see PDF spec section 8.9.5.1
+ // [1 0] means the smask's RGB values give opacity.
+
+ boolean isOpaque = false;
+ if (decodeArray != null)
+ {
+ isOpaque = decodeArray.getInt(0) > decodeArray.getInt(1);
+ }
+
+ final int baseImageWidth = baseImage.getWidth();
+ final int baseImageHeight = baseImage.getHeight();
+
+ BufferedImage result = new BufferedImage(baseImageWidth, baseImageHeight, BufferedImage.TYPE_INT_ARGB);
+ for (int x = 0; x < baseImageWidth; x++)
+ {
+ for (int y = 0; y < baseImageHeight; y++)
+ {
+ int rgb = baseImage.getRGB(x, y);
+ int alpha = smaskImage.getRGB(x, y);
+
+ // The smask image defines a transparency mask but it has no alpha values itself, instead
+ // using the greyscale values to indicate transparency.
+ // 0xAARRGGBB
+
+ // We need to remove any alpha value in the main image.
+ int rgbOnly = 0x00FFFFFF & rgb;
+
+ // We need to use one of the rgb values as the new alpha value for the main image.
+ // It seems the mask is greyscale, so it shouldn't matter whether we use R, G or B
+ // as the indicator of transparency.
+ if (isOpaque)
+ {
+ alpha = ~alpha;
+ }
+ int alphaOnly = alpha << 24;
+
+ result.setRGB(x, y, rgbOnly | alphaOnly);
+ }
+ }
+ return result;
+ }
+}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java?rev=956239&r1=956238&r2=956239&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDJpeg.java Sat Jun 19 15:39:42 2010
@@ -33,6 +33,7 @@ import java.util.List;
import javax.imageio.ImageIO;
import javax.imageio.IIOException;
+import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
@@ -50,7 +51,7 @@ import org.apache.pdfbox.pdmodel.graphic
public class PDJpeg extends PDXObjectImage
{
- private static final List<String> DCT_FILTERS = new ArrayList();
+ private static final List<String> DCT_FILTERS = new ArrayList<String>();
static
{
@@ -198,7 +199,8 @@ public class PDJpeg extends PDXObjectIma
readError = true;
}
catch (Exception ignore)
- {}
+ {
+ }
// 2. try to read jpeg again. some jpegs have some strange header containing
// "Adobe " at some place. so just replace the header with a valid jpeg header.
@@ -232,9 +234,26 @@ public class PDJpeg extends PDXObjectIma
imgFile.delete();
}
}
- return bi;
- }
+
+ // If there is a 'soft mask' image then we use that as a transparency mask.
+ PDXObjectImage smask = getSMaskImage();
+ if (smask != null)
+ {
+ BufferedImage smaskBI = smask.getRGBImage();
+
+ COSArray decodeArray = smask.getDecode();
+ CompositeImage compositeImage = new CompositeImage(bi, smaskBI);
+ BufferedImage rgbImage = compositeImage.createMaskedImage(decodeArray);
+ return rgbImage;
+ }
+ else
+ {
+ // But if there is no soft mask, use the unaltered image.
+ return bi;
+ }
+ }
+
/**
* This writes the JPeg to out.
* {@inheritDoc}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDPixelMap.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDPixelMap.java?rev=956239&r1=956238&r2=956239&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDPixelMap.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDPixelMap.java Sat Jun 19 15:39:42 2010
@@ -227,7 +227,24 @@ public class PDPixelMap extends PDXObjec
(array.length<bufferData.length?array.length: bufferData.length) );
image = new BufferedImage(cm, raster, false, null);
- return image;
+ // If there is a 'soft mask' image then we use that as a transparency mask.
+ PDXObjectImage smask = getSMaskImage();
+ if (smask != null)
+ {
+ BufferedImage smaskBI = smask.getRGBImage();
+
+ COSArray decodeArray = smask.getDecode();
+
+ CompositeImage compositeImage = new CompositeImage(image, smaskBI);
+ BufferedImage rgbImage = compositeImage.createMaskedImage(decodeArray);
+
+ return rgbImage;
+ }
+ else
+ {
+ // But if there is no soft mask, use the unaltered image.
+ return image;
+ }
}
catch (Exception exception)
{
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDXObjectImage.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDXObjectImage.java?rev=956239&r1=956238&r2=956239&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDXObjectImage.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/xobject/PDXObjectImage.java Sat Jun 19 15:39:42 2010
@@ -27,6 +27,7 @@ import org.apache.commons.logging.LogFac
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSStream;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
@@ -96,6 +97,27 @@ public abstract class PDXObjectImage ext
public abstract BufferedImage getRGBImage() throws IOException;
/**
+ * Returns a PDXObjectImage of the SMask image, if there is one.
+ * See section 11.5 of the pdf specification for details on Soft Masks.
+ *
+ * @return the PDXObjectImage of the SMask if there is one, else <code>null</code>.
+ */
+ public PDXObjectImage getSMaskImage() throws IOException
+ {
+ COSStream cosStream = getPDStream().getStream();
+ COSBase smask = cosStream.getDictionaryObject(COSName.SMASK);
+
+ if (smask == null)
+ {
+ return null;
+ }
+ else
+ {
+ return (PDXObjectImage)PDXObject.createXObject(smask);
+ }
+ }
+
+ /**
* Writes the Image to out.
* @param out the OutputStream that the Image is written to.
* @throws IOException when somethings wrong with out