cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Joerg Heinicke <joerg.heini...@gmx.de>
Subject Re: [Patch Submission] Color transform feature added to ImageReader.java
Date Wed, 18 Feb 2004 01:14:26 GMT
Hello Pete,

found another issue: you made your changes on the version 1.3 of the 
ImageReader. In the meantime 1.4 was committed (on 12th of December). 
With your patch those changes would be lost.

Can you please also fix this issue and add your patch to bugzilla 
afterwards?

Thanks in advance,

Joerg

On 17.02.2004 05:16, Pete wrote:

> Hello everyone, as I was building an image gallery app I was requested 
> to add
> the ability to tint an image to coordinate color schemes with the 
> website in
> general. To do this I patched the ImageReader to perform a transform on the
> RGB color channels. This is configured in exactly the same manner as 
> scaling is
> now done.
> 
> See http://www.grumpykitty.biz/index.html for the results.
> 
> This required modification of the
> 
>    org.apache.cocoon.reading.ImageReader
> 
> class only.
> 
> The changes include
> 
>       *   Support for creating a grayscale jpeg
>       *   Support for tinting ( scale red, green or blue color channel )
> 
>       *   Cache key now *always* contains scaling and color coefficients
> 
> This does mean that instead of scaling a decoded Raster, a decoded
> BufferedImage is used. A BufferedImage consists of a Raster + color
> information and is required for the color transform. I consider this the
> most pivotal change.
> 
> The actual color transform is not applied unless specifically requested
> in the sitemap, so I believe the change is benign.
> 
> A cvs diff -u style patch to
> 
>    /src/java/org/apache/cocoon/reading/ImageReader.java
> 
> is attached. Please review and consider it for inclusion in Cocoon.
> 
> 
> 
> All the best, and thank you
> 
> Peter
> 
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> Index: ImageReader.java
> ===================================================================
> RCS file: /home/cvspublic/cocoon-2.1/src/java/org/apache/cocoon/reading/ImageReader.java,v
> retrieving revision 1.4
> diff -u -r1.4 ImageReader.java
> --- ImageReader.java	12 Dec 2003 09:41:33 -0000	1.4
> +++ ImageReader.java	10 Jan 2004 04:32:33 -0000
> @@ -62,9 +62,13 @@
>  import com.sun.image.codec.jpeg.JPEGImageEncoder;
>  import org.xml.sax.SAXException;
>  
> +import java.awt.color.ColorSpace;
>  import java.awt.geom.AffineTransform;
>  import java.awt.image.AffineTransformOp;
> -import java.awt.image.Raster;
> +import java.awt.image.BufferedImage;
> +import java.awt.image.ColorConvertOp;
> +import java.awt.image.DataBuffer;
> +import java.awt.image.RescaleOp;
>  import java.awt.image.WritableRaster;
>  import java.io.ByteArrayOutputStream;
>  import java.io.IOException;
> @@ -87,19 +91,41 @@
>   *     <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. It cannot be used
> + *	alongside the scale and offset parameters.
> + *     </dd>
>   *   </dl>
>   *
>   * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
>   * @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
>   * @author <a href="mailto:tcurdt@apache.org">Torsten Curdt</a>
> - * @version CVS $Id: ImageReader.java,v 1.4 2003/12/12 09:41:33 huber Exp $
> + * @version CVS $Id: ImageReader.java,v 1.3 2003/09/24 21:41:11 cziegeler Exp $
>   */
>  final public class ImageReader extends ResourceReader {
>  
>      private int width;
>      private int height;
> +    private float[] scaleColor = new float[3];
> +    private float[] offsetColor = new float[3];
> +    private ColorConvertOp grayscaleFilter = null;
> +    private RescaleOp colorFilter = null;
> +    
>      private boolean enlarge;
>      private final static String ENLARGE_DEFAULT = "true";
> +    
> +    private final static String GRAYSCALE_DEFAULT = "false";
>  
>      public void setup(SourceResolver resolver, Map objectModel, String src, Parameters
par)
>              throws ProcessingException, SAXException, IOException {
> @@ -108,7 +134,38 @@
>  
>          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("offsetBlue",0.0f);
> +	offsetColor[1] = par.getParameterAsFloat("offsetBlue",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(true == 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;
> @@ -121,7 +178,7 @@
>       * Returns the affine transform that implements the scaling.
>       * The behavior is the following: if both the new width and height values
>       * are positive, the image is rescaled according to these new values and
> -     * the original aspect ration is lost.
> +     * the original aspect ratio is lost.
>       * Otherwise, if one of the two parameters is zero or negative, the
>       * aspect ratio is maintained and the positive parameter indicates the
>       * scaling.
> @@ -160,7 +217,7 @@
>      }
>  
>      protected void processStream() throws IOException, ProcessingException {
> -        if (width > 0 || height > 0) {
> +        if (width > 0 || height > 0 || null != colorFilter) {
>              if (getLogger().isDebugEnabled()) {
>                  getLogger().debug("image " + ((width==0)?"?":Integer.toString(width))
>                                    + "x" + ((height==0)?"?":Integer.toString(height))
> @@ -193,40 +250,48 @@
>               */
>  
>              try {
> +            	
>                  JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(inputStream);
> -                Raster original = decoder.decodeAsRaster();
> +                BufferedImage original = decoder.decodeAsBufferedImage();
>                  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);
> -
> -                if (!handleJVMBug()) {
> -                    if (getLogger().isDebugEnabled()) {
> -                        getLogger().debug( "No need to handle JVM bug" );
> -                    }
> -                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
> -                    encoder.encode(scaled);
> -                } else {
> -                    if (getLogger().isDebugEnabled()) {
> -                        getLogger().debug( "Need to handle JVM bug" );
> -                    }
> -                    ByteArrayOutputStream bstream = new ByteArrayOutputStream();
> -                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bstream);
> -                    encoder.encode(scaled);
> -                    out.write(bstream.toByteArray());
> -                }
> +                
> +            	BufferedImage currentImage = original;
> +                
> +                if(width > 0 || height > 0)
> +                {
> +			double ow = decodeParam.getWidth();
> +                	double oh = decodeParam.getHeight();
> +
> +	                AffineTransformOp filter = new AffineTransformOp(getTransform(ow, oh,
width, height), AffineTransformOp.TYPE_BILINEAR);
> +	                WritableRaster intermediateRaster = filter.createCompatibleDestRaster(currentImage.getRaster());
> +	                
> +	                filter.filter(currentImage.getRaster(), intermediateRaster);
> +	                
> +	                currentImage = new BufferedImage(original.getColorModel(), intermediateRaster,
true, null);
> +	        }
> +	        
> +	        if(null != grayscaleFilter)
> +	        {
> +	                grayscaleFilter.filter(currentImage, currentImage);
> +	        }
> +                if(null != colorFilter)
> +                {
> +	                colorFilter.filter(currentImage, currentImage);
> +		}
> +		
> +                // JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
> +
> +                ByteArrayOutputStream bstream = new ByteArrayOutputStream();
> +                JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bstream);
> +                encoder.encode(currentImage);
> +                out.write(bstream.toByteArray());
>  
>                  out.flush();
>              } catch (ImageFormatException e) {
>                  throw new ProcessingException("Error reading the image. Note that only
JPEG images are currently supported.");
> -            } finally {
> -              // Bugzilla Bug 25069, close inputStream in finally block
> -              // this will close inputStream even if processStream throws
> -              // an exception
> -              inputStream.close();
>              }
> +
> +            inputStream.close();
>          } else {
>              // only read the resource - no modifications requested
>              if (getLogger().isDebugEnabled()) {
> @@ -240,48 +305,20 @@
>       * 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();
> -        }
> -    }
> -
> -    /**
> -     * Determine if workaround for Bug Id 4502892 is neccessary.
> -     * This method assumes that Bug is present if 
> -     * java.version is undeterminable, and for java.version
> -     * 1.1, 1.2, 1.3, all other java.version do not need the Bug handling
> -     *
> -     * @return true if we should handle the JVM bug, else false
> -     */
> -    protected boolean handleJVMBug() {
> -        // 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') {
> -                handleJVMBug = true;
> -            } else {
> -                handleJVMBug = false;
> -            }
> -        } else {
> -            handleJVMBug = true;
> -        }
> -        if (getLogger().isDebugEnabled()) {
> -            getLogger().debug( "Running java.version " + String.valueOf(java_version)
+ 
> -              " need to handle JVM bug " + String.valueOf(handleJVMBug) );
> -        }
> -        
> -        return handleJVMBug;
> +    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)?"grayscale":"color")
> +    		+ ":" + super.getKey();
>      }
>  }
> 

Mime
View raw message