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>&lt;scale(Red|Green|Blue)&gt;</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>&lt;offset(Red|Green|Blue)&gt;</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>&lt;grayscale&gt;</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>
  
  
  

Reply via email to