1 /*
2  * $RCSfile: FormatCRIF.java,v $
3  *
4  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
5  *
6  * Use is subject to license terms.
7  *
8  * $Revision: 1.2 $
9  * $Date: 2005/05/12 18:24:32 $
10  * $State: Exp $
11  */
12 package com.lightcrafts.media.jai.opimage;
13 import java.awt.RenderingHints;
14 import java.awt.image.ColorModel;
15 import java.awt.image.RenderedImage;
16 import java.awt.image.SampleModel;
17 import java.awt.image.renderable.ParameterBlock;
18 import java.util.Map;
19 import com.lightcrafts.mediax.jai.CRIFImpl;
20 import com.lightcrafts.mediax.jai.ImageLayout;
21 import com.lightcrafts.mediax.jai.JAI;
22 import com.lightcrafts.mediax.jai.OpImage;
23 import com.lightcrafts.mediax.jai.NullOpImage;
24 import com.lightcrafts.mediax.jai.RasterFactory;
25 import com.lightcrafts.media.jai.util.JDKWorkarounds;
26 
27 /**
28  * A <code>CRIF</code> supporting the "Format" operation in the rendered
29  * and renderable image layers.
30  *
31  * @see com.lightcrafts.mediax.jai.operator.FormatDescriptor
32  * @see FormatOpImage
33  *
34  *
35  * @since EA4
36  */
37 public class FormatCRIF extends CRIFImpl {
38 
39     /** Constructor. */
FormatCRIF()40     public FormatCRIF() {
41         super("format");
42     }
43 
44     /**
45      * Creates a new instance of <code>FormatOpImage</code> in the
46      * rendered layer.
47      *
48      * @param args   The source image and data type
49      * @param hints  Contains destination image layout.
50      */
create(ParameterBlock args, RenderingHints renderHints)51     public RenderedImage create(ParameterBlock args,
52                                 RenderingHints renderHints) {
53 
54         // Get the source image and the data type parameter.
55         RenderedImage src = args.getRenderedSource(0);
56         Integer datatype = (Integer)args.getObjectParameter(0);
57         int type = datatype.intValue();
58 
59         // Get ImageLayout from renderHints if any.
60         ImageLayout layout = RIFUtil.getImageLayoutHint(renderHints);
61 
62         // If there is no change return the source image directly.
63         if(layout == null && type == src.getSampleModel().getDataType()) {
64             return src;
65         }
66 
67         // Create or clone the ImageLayout.
68         if(layout == null) {
69             layout = new ImageLayout(src);
70         } else {
71             layout = (ImageLayout)layout.clone();
72         }
73 
74 	boolean isDataTypeChange = false;
75 
76         // Get prospective destination SampleModel.
77         SampleModel sampleModel = layout.getSampleModel(src);
78 
79         // Create a new SampleModel if the type is not as desired.
80         if (sampleModel.getDataType() != type) {
81             int tileWidth = layout.getTileWidth(src);
82             int tileHeight = layout.getTileHeight(src);
83             int numBands = src.getSampleModel().getNumBands();
84 
85             SampleModel csm =
86                 RasterFactory.createComponentSampleModel(sampleModel,
87                                                          type,
88                                                          tileWidth,
89                                                          tileHeight,
90                                                          numBands);
91 
92             layout.setSampleModel(csm);
93 	    isDataTypeChange = true;
94         }
95 
96 
97         // Check ColorModel.
98         ColorModel colorModel = layout.getColorModel(null);
99         if(colorModel != null &&
100            !JDKWorkarounds.areCompatibleDataModels(layout.getSampleModel(src),
101                                                    colorModel)) {
102             // Clear the mask bit if incompatible.
103             layout.unsetValid(ImageLayout.COLOR_MODEL_MASK);
104         }
105 
106         // Check whether anything but the ColorModel is changing.
107         if (layout.getSampleModel(src) == src.getSampleModel() &&
108             layout.getMinX(src) == src.getMinX() &&
109             layout.getMinY(src) == src.getMinY() &&
110             layout.getWidth(src) == src.getWidth() &&
111             layout.getHeight(src) == src.getHeight() &&
112             layout.getTileWidth(src) == src.getTileWidth() &&
113             layout.getTileHeight(src) == src.getTileHeight() &&
114             layout.getTileGridXOffset(src) == src.getTileGridXOffset() &&
115             layout.getTileGridYOffset(src) == src.getTileGridYOffset()) {
116 
117             if(layout.getColorModel(src) == src.getColorModel()) {
118                 // Nothing changed: return the source directly.
119                 return src;
120             } else {
121                 // Remove TileCache hint from RenderingHints if present.
122                 RenderingHints hints = renderHints;
123                 if(hints != null && hints.containsKey(JAI.KEY_TILE_CACHE)) {
124                     hints = new RenderingHints((Map)renderHints);
125                     hints.remove(JAI.KEY_TILE_CACHE);
126                 }
127 
128                 // Only the ColorModel is changing.
129                 return new NullOpImage(src, layout, hints,
130                                        OpImage.OP_IO_BOUND);
131             }
132         }
133 
134 	if (isDataTypeChange == true) {
135 
136 	    // Add JAI.KEY_REPLACE_INDEX_COLOR_MODEL hint to renderHints
137 	    if (renderHints == null) {
138 		renderHints =
139 		    new RenderingHints(JAI.KEY_REPLACE_INDEX_COLOR_MODEL,
140 				       Boolean.TRUE);
141 
142 	    } else if (!renderHints.containsKey(
143 					JAI.KEY_REPLACE_INDEX_COLOR_MODEL)) {
144 		// If the user specified a value for this hint, we don't
145 		// want to change that
146 		renderHints.put(JAI.KEY_REPLACE_INDEX_COLOR_MODEL,
147 				Boolean.TRUE);
148 	    }
149 	}
150 
151         return new CopyOpImage(src, renderHints, layout);
152     }
153 }
154