joerg 2004/03/08 15:32:50
Modified: src/java/org/apache/cocoon/reading ImageReader.java
. status.xml
src/webapp/samples/imagereader sitemap.xmap samples.xml
Log:
fixed bug 27020, thanks to Peter Horsfield: Added grayscaling and color
transformation to the ImageReader.
Revision Changes Path
1.7 +113 -34
cocoon-2.1/src/java/org/apache/cocoon/reading/ImageReader.java
Index: ImageReader.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/reading/ImageReader.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- ImageReader.java 5 Mar 2004 13:02:57 -0000 1.6
+++ ImageReader.java 8 Mar 2004 23:32:50 -0000 1.7
@@ -15,26 +15,28 @@
*/
package org.apache.cocoon.reading;
-import org.apache.avalon.framework.parameters.Parameters;
+import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorConvertOp;
+import java.awt.image.RescaleOp;
+import java.awt.image.WritableRaster;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Map;
+import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.environment.SourceResolver;
+import org.xml.sax.SAXException;
import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGDecodeParam;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
-import org.xml.sax.SAXException;
-
-import java.awt.geom.AffineTransform;
-import java.awt.image.AffineTransformOp;
-import java.awt.image.Raster;
-import java.awt.image.WritableRaster;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.Map;
/**
* The <code>ImageReader</code> component is used to serve binary image data
@@ -52,6 +54,20 @@
* <dd>This parameter is optional. When specified it determines the
height
* of the image that should be served.
* </dd>
+ * <dt><scale(Red|Green|Blue)></dt>
+ * <dd>This parameter is optional. When specified it will cause the
+ * specified color component in the image to be multiplied by the
+ * specified floating point value.
+ * </dd>
+ * <dt><offset(Red|Green|Blue)></dt>
+ * <dd>This parameter is optional. When specified it will cause the
+ * specified color component in the image to be incremented by the
+ * specified floating point value.
+ * </dd>
+ * <dt><grayscale></dt>
+ * <dd>This parameter is optional. When specified and set to true it
+ * will cause each image pixel to be normalized.
+ * </dd>
* </dl>
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a>
@@ -63,9 +79,17 @@
private int width;
private int height;
+
+ private float[] scaleColor = new float[3];
+ private float[] offsetColor = new float[3];
+ private RescaleOp colorFilter = null;
+
private boolean enlarge;
private final static String ENLARGE_DEFAULT = "true";
+ private ColorConvertOp grayscaleFilter = null;
+ private final static String GRAYSCALE_DEFAULT = "false";
+
public void setup(SourceResolver resolver, Map objectModel, String src,
Parameters par)
throws ProcessingException, SAXException, IOException {
@@ -74,6 +98,39 @@
width = par.getParameterAsInteger("width", 0);
height = par.getParameterAsInteger("height", 0);
+ scaleColor[0] = par.getParameterAsFloat("scaleRed", -1.0f);
+ scaleColor[1] = par.getParameterAsFloat("scaleGreen", -1.0f);
+ scaleColor[2] = par.getParameterAsFloat("scaleBlue", -1.0f);
+ offsetColor[0] = par.getParameterAsFloat("offsetRed", 0.0f);
+ offsetColor[1] = par.getParameterAsFloat("offsetGreen", 0.0f);
+ offsetColor[2] = par.getParameterAsFloat("offsetBlue", 0.0f);
+
+ boolean filterColor = false;
+
+ for (int i = 0; i < 3; ++i) {
+ if (scaleColor[i] != -1.0f) {
+ filterColor = true;
+ } else {
+ scaleColor[i] = 1.0f;
+ }
+ if (offsetColor[i] != 0.0f) {
+ filterColor = true;
+ }
+ }
+
+ if (filterColor) {
+ colorFilter = new RescaleOp(scaleColor, offsetColor, null);
+ } else {
+ colorFilter = null;
+ }
+
+ String grayscalePar = par.getParameter("grayscale",
GRAYSCALE_DEFAULT);
+ if ("true".equalsIgnoreCase(grayscalePar) ||
"yes".equalsIgnoreCase(grayscalePar)){
+ grayscaleFilter = new
ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
+ } else {
+ grayscaleFilter = null;
+ }
+
String enlargePar = par.getParameter("allow-enlarging",
ENLARGE_DEFAULT);
if ("true".equalsIgnoreCase(enlargePar) ||
"yes".equalsIgnoreCase(enlargePar)){
enlarge = true;
@@ -125,17 +182,17 @@
}
protected void processStream() throws IOException, ProcessingException {
- if (width > 0 || height > 0) {
+ if (width > 0 || height > 0 || null != colorFilter || null !=
grayscaleFilter) {
if (getLogger().isDebugEnabled()) {
- getLogger().debug("image " +
((width==0)?"?":Integer.toString(width))
- + "x" +
((height==0)?"?":Integer.toString(height))
+ getLogger().debug("image " + ((width == 0) ? "?" :
Integer.toString(width))
+ + "x" + ((height == 0) ? "?" :
Integer.toString(height))
+ " expires: " + expires);
}
// since we create the image on the fly
response.setHeader("Accept-Ranges", "none");
- /**
+ /*
* NOTE (SM):
* Due to Bug Id 4502892 (which is found in *all* JVM
implementations from
* 1.2.x and 1.3.x on all OS!), we must buffer the JPEG
generation to avoid
@@ -159,27 +216,43 @@
try {
JPEGImageDecoder decoder =
JPEGCodec.createJPEGDecoder(inputStream);
- Raster original = decoder.decodeAsRaster();
- JPEGDecodeParam decodeParam = decoder.getJPEGDecodeParam();
- double ow = decodeParam.getWidth();
- double oh = decodeParam.getHeight();
- AffineTransformOp filter = new
AffineTransformOp(getTransform(ow, oh, width, height),
AffineTransformOp.TYPE_BILINEAR);
- WritableRaster scaled =
filter.createCompatibleDestRaster(original);
- filter.filter(original, scaled);
+ BufferedImage original = decoder.decodeAsBufferedImage();
+ BufferedImage currentImage = original;
+
+ if (width > 0 || height > 0) {
+ JPEGDecodeParam decodeParam =
decoder.getJPEGDecodeParam();
+ double ow = decodeParam.getWidth();
+ double oh = decodeParam.getHeight();
+
+ AffineTransformOp filter = new
AffineTransformOp(getTransform(ow, oh, width, height),
AffineTransformOp.TYPE_BILINEAR);
+ WritableRaster scaledRaster =
filter.createCompatibleDestRaster(currentImage.getRaster());
+
+ filter.filter(currentImage.getRaster(), scaledRaster);
+
+ currentImage = new
BufferedImage(original.getColorModel(), scaledRaster, true, null);
+ }
+
+ if (null != grayscaleFilter) {
+ grayscaleFilter.filter(currentImage, currentImage);
+ }
+
+ if (null != colorFilter) {
+ colorFilter.filter(currentImage, currentImage);
+ }
if (!handleJVMBug()) {
if (getLogger().isDebugEnabled()) {
getLogger().debug( "No need to handle JVM bug" );
}
JPEGImageEncoder encoder =
JPEGCodec.createJPEGEncoder(out);
- encoder.encode(scaled);
+ encoder.encode(currentImage);
} else {
if (getLogger().isDebugEnabled()) {
getLogger().debug( "Need to handle JVM bug" );
}
ByteArrayOutputStream bstream = new
ByteArrayOutputStream();
JPEGImageEncoder encoder =
JPEGCodec.createJPEGEncoder(bstream);
- encoder.encode(scaled);
+ encoder.encode(currentImage);
out.write(bstream.toByteArray());
}
@@ -205,15 +278,21 @@
* Generate the unique key.
* This key must be unique inside the space of this component.
*
- * @return The generated key consists from src and width and height
+ * @return The generated key consists of the src and width and height,
and the color transform
* parameters
*/
public Serializable getKey() {
- if (width > 0 || height > 0) {
- return this.inputSource.getURI() + ':' + this.width + ':' +
this.height;
- } else {
- return super.getKey();
- }
+ return this.inputSource.getURI()
+ + ':' + this.width
+ + ':' + this.height
+ + ":" + this.scaleColor[0]
+ + ":" + this.scaleColor[1]
+ + ":" + this.scaleColor[2]
+ + ":" + this.offsetColor[0]
+ + ":" + this.offsetColor[1]
+ + ":" + this.offsetColor[2]
+ + ":" + ((null == this.grayscaleFilter) ? "color" :
"grayscale")
+ + ":" + super.getKey();
}
/**
@@ -228,10 +307,10 @@
// java.version=1.4.0
String java_version = System.getProperty( "java.version", "0.0.0" );
boolean handleJVMBug = true;
-
+
char major = java_version.charAt(0);
char minor = java_version.charAt(2);
-
+
// make 0.0, 1.1, 1.2, 1.3 handleJVMBug = true
if (major == '0' || major == '1') {
if (minor == '0' || minor == '1' || minor == '2' || minor ==
'3') {
@@ -246,7 +325,7 @@
getLogger().debug( "Running java.version " +
String.valueOf(java_version) +
" need to handle JVM bug " + String.valueOf(handleJVMBug) );
}
-
+
return handleJVMBug;
}
}
1.265 +4 -1 cocoon-2.1/status.xml
Index: status.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/status.xml,v
retrieving revision 1.264
retrieving revision 1.265
diff -u -r1.264 -r1.265
--- status.xml 8 Mar 2004 21:21:19 -0000 1.264
+++ status.xml 8 Mar 2004 23:32:50 -0000 1.265
@@ -211,6 +211,9 @@
<changes>
<release version="@version@" date="@date@">
+ <action dev="JH" type="add" fixes-bug="27020" due-to="Peter Horsfield"
due-to-email="[EMAIL PROTECTED]">
+ Added grayscaling and color transformation to the ImageReader.
+ </action>
<action dev="JH" type="fix" fixes-bug="26851" due-to="Marco Rolappe"
due-to-email="[EMAIL PROTECTED]">
LinkStatusGenerator now handles also links with a specified charset.
</action>
1.4 +28 -2 cocoon-2.1/src/webapp/samples/imagereader/sitemap.xmap
Index: sitemap.xmap
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/webapp/samples/imagereader/sitemap.xmap,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- sitemap.xmap 6 Mar 2004 02:26:15 -0000 1.3
+++ sitemap.xmap 8 Mar 2004 23:32:50 -0000 1.4
@@ -43,10 +43,36 @@
<map:serialize/>
</map:match>
- <map:match pattern="image-*">
+ <map:match pattern="image">
+ <map:read src="logo.jpg"/>
+ </map:match>
+
+ <map:match pattern="image-size-*">
<map:read type="image" src="logo.jpg">
<map:parameter name="width" value="{1}"/>
<map:parameter name="height" value="{1}"/>
+ </map:read>
+ </map:match>
+
+ <map:match pattern="image-grayscale">
+ <map:read type="image" src="logo.jpg">
+ <map:parameter name="grayscale" value="true"/>
+ </map:read>
+ </map:match>
+
+ <map:match pattern="image-color-scale-*-*-*">
+ <map:read type="image" src="logo.jpg">
+ <map:parameter name="scaleRed" value="{1}"/>
+ <map:parameter name="scaleGreen" value="{2}"/>
+ <map:parameter name="scaleBlue" value="{3}"/>
+ </map:read>
+ </map:match>
+
+ <map:match pattern="image-color-offset-*-*-*">
+ <map:read type="image" src="logo.jpg">
+ <map:parameter name="offsetRed" value="{1}"/>
+ <map:parameter name="offsetGreen" value="{2}"/>
+ <map:parameter name="offsetBlue" value="{3}"/>
</map:read>
</map:match>
</map:pipeline>
1.3 +45 -13 cocoon-2.1/src/webapp/samples/imagereader/samples.xml
Index: samples.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/webapp/samples/imagereader/samples.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- samples.xml 6 Mar 2004 06:16:54 -0000 1.2
+++ samples.xml 8 Mar 2004 23:32:50 -0000 1.3
@@ -15,21 +15,53 @@
limitations under the License.
-->
<samples xmlns:xlink="http://www.w3.org/1999/xlink">
-
- <group name="Main examples page.">
- <sample name="Back" href="..">to Cocoon examples main page</sample>
- </group>
-
- <group name="ImageReader">
- <sample href="image-0" name="Image">
- Image of original size
- </sample>
- <sample href="image-250" name="Image 250x250">
- Image scaled up to the size 250 x 250
+
+ <group name="Main examples page.">
+ <sample name="Back" href="..">to Cocoon examples main page</sample>
+ </group>
+
+ <group name="The Original">
+ <sample href="image" name="Image">
+ Image of original size and color.
</sample>
- <sample href="image-50" name="Image 50x50">
- Image scaled down to the size 50 x 50
+ </group>
+
+ <group name="ImageReader - Size Scaling">
+ <sample href="image-size-50" name="Image 50x50">
+ Image scaled down to the size 50 x 50.
</sample>
+ <sample href="image-size-250" name="Image 250x250">
+ Image scaled up to the size 250 x 250.
+ </sample>
+ </group>
+
+ <group name="ImageReader - Grayscaling">
+ <sample href="image-grayscale" name="Image grayscaled.">
+ The image in gray.
+ </sample>
</group>
+ <group name="ImageReader - Color Scaling">
+ <sample href="image-color-scale-2-1-1" name="Image tinted red.">
+ The values for the color red are duplicated.
+ </sample>
+ <sample href="image-color-scale-1-2-1" name="Image tinted green.">
+ The values for the color green are duplicated.
+ </sample>
+ <sample href="image-color-scale-1-1-2" name="Image tinted blue.">
+ The values for the color blue are duplicated.
+ </sample>
+ </group>
+
+ <group name="ImageReader - Color Offset">
+ <sample href="image-color-offset-50-0-0" name="Image tinted red.">
+ The values for the color red are incremented by 50.
+ </sample>
+ <sample href="image-color-offset-0-50-0" name="Image tinted green.">
+ The values for the color green are incremented by 50.
+ </sample>
+ <sample href="image-color-offset-0-0-50" name="Image tinted blue.">
+ The values for the color blue are incremented by 50.
+ </sample>
+ </group>
</samples>