1 /*
2  * $RCSfile: MlibScaleNearestOpImage.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.1 $
9  * $Date: 2005/02/11 04:56:04 $
10  * $State: Exp $
11  */
12 package com.lightcrafts.media.jai.mlib;
13 import java.awt.Rectangle;
14 import java.awt.image.DataBuffer;
15 import java.awt.image.Raster;
16 import java.awt.image.RenderedImage;
17 import java.awt.image.WritableRaster;
18 import com.lightcrafts.mediax.jai.ImageLayout;
19 import com.lightcrafts.mediax.jai.Interpolation;
20 import java.util.Map;
21 import com.lightcrafts.mediax.jai.BorderExtender;
22 import com.sun.medialib.mlib.*;
23 
24 // import com.lightcrafts.media.jai.test.OpImageTester;
25 
26 /**
27  * An OpImage class that scales an image using nearest-neighbor
28  * interpolation.
29  *
30  */
31 final class MlibScaleNearestOpImage extends MlibScaleOpImage {
32 
33     /**
34      * Constructs an MlibScaleNearestOpImage. The image dimensions are copied
35      * from the source image.  The tile grid layout, SampleModel, and
36      * ColorModel may optionally be specified by an ImageLayout object.
37      *
38      * @param source    a RenderedImage.
39      * @param layout    an ImageLayout optionally containing the tile
40      *                  grid layout, SampleModel, and ColorModel, or null.
41      * @param xScale    the x scaling factor.
42      * @param yScale    the y scaling factor.
43      * @param xTrans    the x translation factor.
44      * @param yTrans    the y translation factor.
45      * @param interp    the Nearest interpolation object.
46      */
MlibScaleNearestOpImage(RenderedImage source, BorderExtender extender, Map config, ImageLayout layout, float xScale, float yScale, float xTrans, float yTrans, Interpolation interp)47     public MlibScaleNearestOpImage(RenderedImage source,
48 				   BorderExtender extender,
49                                    Map config,
50 				   ImageLayout layout,
51 				   float xScale, float yScale,
52 				   float xTrans, float yTrans,
53 				   Interpolation interp) {
54         super(source, extender, config,
55               layout, xScale, yScale, xTrans, yTrans, interp, true);
56     }
57 
58     /**
59      * Scale the given rectangle by the specified scale and translation
60      * factors. The sources are cobbled.
61      *
62      * @param sources   an array of sources, guarantee to provide all
63      *                  necessary source data for computing the rectangle.
64      * @param dest      a tile that contains the rectangle to be computed.
65      * @param destRect  the rectangle within this OpImage to be processed.
66      */
computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect)67     protected void computeRect(Raster[] sources,
68                                WritableRaster dest,
69                                Rectangle destRect) {
70 
71 	Raster source = sources[0];
72 	Rectangle srcRect = source.getBounds();
73 
74         int formatTag = MediaLibAccessor.findCompatibleTag(sources, dest);
75 
76         MediaLibAccessor srcAccessor = new MediaLibAccessor(source, srcRect,
77 							    formatTag);
78         MediaLibAccessor dstAccessor = new MediaLibAccessor(dest, destRect,
79 							    formatTag);
80 
81 	// Get the floating point scale factors
82 	float mlibScaleX = scaleX;
83 	float mlibScaleY = scaleY;
84 
85         // Translation to be specified to Medialib. Note that we have to
86 	// specify an additional translation since all images are 0 based
87 	// in Medialib.  Note that scale and translation scalars have
88 	// rational representations.
89 
90 	// Calculate intermediate values using rational arithmetic.
91 	long tempDenomX = scaleXRationalDenom * transXRationalDenom;
92         long tempDenomY = scaleYRationalDenom * transYRationalDenom;
93 	long tempNumerX = (srcRect.x * scaleXRationalNum * transXRationalDenom) +
94 	                  (transXRationalNum * scaleXRationalDenom) -
95 			  (destRect.x * tempDenomX);
96 	long tempNumerY = (srcRect.y * scaleYRationalNum * transYRationalDenom) +
97 	                  (transYRationalNum * scaleYRationalDenom) -
98 			  (destRect.y * tempDenomY);
99         float tx = (float)tempNumerX/(float)tempDenomX;
100 	float ty = (float)tempNumerY/(float)tempDenomY;
101 
102 	mediaLibImage srcML[], dstML[];
103 
104         switch (dstAccessor.getDataType()) {
105         case DataBuffer.TYPE_BYTE:
106         case DataBuffer.TYPE_USHORT:
107         case DataBuffer.TYPE_SHORT:
108         case DataBuffer.TYPE_INT:
109             srcML = srcAccessor.getMediaLibImages();
110             dstML = dstAccessor.getMediaLibImages();
111             for (int i = 0 ; i < dstML.length; i++) {
112                 Image.ZoomTranslate(dstML[i], srcML[i],
113 						    (double)mlibScaleX,
114 						    (double)mlibScaleY,
115 						    (double)tx, (double)ty,
116 						    Constants.MLIB_NEAREST,
117                                                     Constants.MLIB_EDGE_DST_NO_WRITE);
118             }
119             break;
120 
121 	case DataBuffer.TYPE_FLOAT:
122 	case DataBuffer.TYPE_DOUBLE:
123             srcML = srcAccessor.getMediaLibImages();
124             dstML = dstAccessor.getMediaLibImages();
125             for (int i = 0 ; i < dstML.length; i++) {
126                 Image.ZoomTranslate_Fp(dstML[i], srcML[i],
127 						       (double)mlibScaleX,
128 						       (double)mlibScaleY,
129 						       (double)tx, (double)ty,
130 						       Constants.MLIB_NEAREST,
131 						       Constants.MLIB_EDGE_DST_NO_WRITE);
132             }
133             break;
134 
135         default:
136             String className = this.getClass().getName();
137             throw new RuntimeException(JaiI18N.getString("Generic2"));
138         }
139 
140         if (dstAccessor.isDataCopy()) {
141             dstAccessor.clampDataArrays();
142             dstAccessor.copyDataToRaster();
143         }
144     }
145 
146 //     public static OpImage createTestImage(OpImageTester oit) {
147 // 	Interpolation interp = new InterpolationNearest();
148 //         return new MlibScaleNearestOpImage(oit.getSource(), null,
149 // 					   new ImageLayout(oit.getSource()),
150 // 					   2, 2, 0, 0, interp);
151 //     }
152 
153 //     // Calls a method on OpImage that uses introspection, to make this
154 //     // class, discover it's createTestImage() call, call it and then
155 //     // benchmark the performance of the created OpImage chain.
156 //     public static void main (String args[]) {
157 //         String classname = "com.lightcrafts.media.jai.mlib.MlibScaleNearestOpImage";
158 //         OpImageTester.performDiagnostics(classname, args);
159 //     }
160 }
161