KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > ext > awt > image > rendered > DisplacementMapRed


1 /*
2
3    Copyright 2001,2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.ext.awt.image.rendered;
19
20 import java.awt.Rectangle JavaDoc;
21 import java.awt.RenderingHints JavaDoc;
22 import java.awt.image.ColorModel JavaDoc;
23 import java.awt.image.DataBufferInt JavaDoc;
24 import java.awt.image.Raster JavaDoc;
25 import java.awt.image.SinglePixelPackedSampleModel JavaDoc;
26 import java.awt.image.WritableRaster JavaDoc;
27
28 import org.apache.batik.ext.awt.image.ARGBChannel;
29 import org.apache.batik.ext.awt.image.GraphicsUtil;
30 import org.apache.batik.ext.awt.image.PadMode;
31
32
33 /**
34  * This implementation of RenderableImage will render its input
35  * GraphicsNode on demand for tiles.
36  *
37  * @author <a HREF="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
38  * @version $Id: DisplacementMapRed.java,v 1.8 2005/03/27 08:58:33 cam Exp $
39  */

40 public class DisplacementMapRed extends AbstractRed {
41     // Use these to control timing and Nearest Neighbot vs. Bilinear Interp.
42
static private final boolean TIME = false;
43     static private final boolean USE_NN = false;
44
45     /**
46      * The displacement scale factor along the x axis
47      */

48     private float scaleX;
49
50     /**
51      * The displacement scale factor along the y axis
52      */

53     private float scaleY;
54
55     /**
56      * The channel type of the operation on X axis
57      */

58     private ARGBChannel xChannel;
59
60     /**
61      * The channel type of the operation on Y axis
62      */

63     private ARGBChannel yChannel;
64
65     /**
66      * The image to distort.
67      */

68     CachableRed image;
69
70     /**
71      * The offset image (displacement map).
72      */

73     CachableRed offsets;
74
75     /**
76      * The maximum possible offsets in x and y
77      */

78     int maxOffX, maxOffY;
79
80     /**
81      * The set of rendering hints
82      */

83     RenderingHints JavaDoc hints;
84
85     /**
86      * Computed tile Offsets Soft referencces to TileOffsets instances...
87      */

88     TileOffsets [] xOffsets;
89     TileOffsets [] yOffsets;
90
91     static class TileOffsets {
92         int [] tile;
93         int [] off;
94         TileOffsets(int len, int base, int stride,
95                     int loc, int endLoc, int slop, int tile, int endTile) {
96             this.tile = new int[len+1];
97             this.off = new int[len+1];
98             
99             if (tile == endTile) endLoc -= slop;
100
101             for (int i=0; i<len; i++) {
102                 this.tile[i] = tile;
103                 this.off [i] = base+(loc*stride);
104                 loc++;
105                 if (loc == endLoc) {
106                     loc = 0;
107                     tile++;
108                     if (tile == endTile) endLoc -=slop;
109                 }
110             }
111             this.tile[len] = this.tile[len-1];
112             this.off [len] = this.off [len-1];
113         }
114     }
115
116     /**
117      * @param image the image to distort
118      * @param offsets the displacement map
119      * @param xChannel defines the channel of off whose values will be
120      * on X-axis operation
121      * @param yChannel defines the channel of off whose values will be
122      * @param scaleX defines the scale factor of the filter operation
123      * on the X axis.
124      * @param scaleY defines the scale factor of the filter operation
125      * on the Y axis
126      * @param rh the rendering hints
127      */

128     public DisplacementMapRed(CachableRed image,
129                               CachableRed offsets,
130                               ARGBChannel xChannel,
131                               ARGBChannel yChannel,
132                               float scaleX, float scaleY,
133                               RenderingHints JavaDoc rh) {
134         
135         if(xChannel == null){
136             throw new IllegalArgumentException JavaDoc("Must provide xChannel");
137         }
138
139         if(yChannel == null){
140             throw new IllegalArgumentException JavaDoc("Must provide yChannel");
141         }
142
143         this.offsets = offsets;
144         this.scaleX = scaleX;
145         this.scaleY = scaleY;
146         this.xChannel = xChannel;
147         this.yChannel = yChannel;
148         this.hints = rh;
149
150         maxOffX = (int)Math.ceil(scaleX/2);
151         maxOffY = (int)Math.ceil(scaleY/2);
152
153         Rectangle JavaDoc rect = image.getBounds();
154
155         Rectangle JavaDoc r = image.getBounds();
156         r.x -= maxOffX; r.width += 2*maxOffX;
157         r.y -= maxOffY; r.height += 2*maxOffY;
158         image = new PadRed(image, r, PadMode.ZERO_PAD, null);
159         image = new TileCacheRed(image);
160         this.image = image;
161         ColorModel JavaDoc cm = image.getColorModel();
162         if (!USE_NN)
163             // For Bilinear we need alpha premult.
164
cm = GraphicsUtil.coerceColorModel(cm, true);
165
166         init(image, rect, cm, image.getSampleModel(),
167              rect.x, rect.y, null);
168
169         xOffsets = new TileOffsets[getNumXTiles()];
170         yOffsets = new TileOffsets[getNumYTiles()];
171     }
172
173     public WritableRaster JavaDoc copyData(WritableRaster JavaDoc wr) {
174         copyToRaster(wr);
175         return wr;
176     }
177
178     public Raster JavaDoc getTile(int tileX, int tileY) {
179         WritableRaster JavaDoc dest = makeTile(tileX, tileY);
180         Rectangle JavaDoc srcR = dest.getBounds();
181
182         // Get Raster from offsetes
183
Raster JavaDoc mapRas = offsets.getData(srcR);
184         ColorModel JavaDoc mapCM = offsets.getColorModel();
185         // ensure map isn't pre-multiplied.
186
GraphicsUtil.coerceData((WritableRaster JavaDoc)mapRas, mapCM, false);
187
188         TileOffsets xinfo = getXOffsets(tileX);
189         TileOffsets yinfo = getYOffsets(tileY);
190
191         if (USE_NN)
192             filterNN(mapRas, dest,
193                      xinfo.tile, xinfo.off,
194                      yinfo.tile, yinfo.off);
195         else if (image.getColorModel().isAlphaPremultiplied())
196             filterBL(mapRas, dest,
197                      xinfo.tile, xinfo.off,
198                      yinfo.tile, yinfo.off);
199         else
200             filterBLPre(mapRas, dest,
201                         xinfo.tile, xinfo.off,
202                         yinfo.tile, yinfo.off);
203
204         return dest;
205     }
206
207     public TileOffsets getXOffsets(int xTile) {
208         TileOffsets ret = xOffsets[xTile-getMinTileX()];
209         if (ret != null)
210             return ret;
211
212         SinglePixelPackedSampleModel JavaDoc sppsm;
213         sppsm = (SinglePixelPackedSampleModel JavaDoc)getSampleModel();
214         int base = sppsm.getOffset(0, 0);
215         int tw = sppsm.getWidth();
216
217         // The span we need to cover in the input image.
218
int width = tw+2*maxOffX;
219
220         // The start and end X in image's tile coordinate system...
221
int x0 = (getTileGridXOffset() + (xTile*tw) - maxOffX
222                      -image.getTileGridXOffset());
223         int x1 = x0+width-1;
224         
225         int tile = (int)Math.floor(x0/(double)tw);
226         int endTile = (int)Math.floor(x1/(double)tw);
227         int loc = x0-(tile*tw);
228         int endLoc = tw;
229
230         // Amount not used from right edge tile
231
int slop = ((endTile+1)*tw-1) - x1;
232         
233         ret = new TileOffsets(width, base, 1,
234                               loc, endLoc, slop, tile, endTile);
235
236         xOffsets[xTile-getMinTileX()] = ret;
237         return ret;
238     }
239
240     public TileOffsets getYOffsets(int yTile) {
241         TileOffsets ret = yOffsets[yTile-getMinTileY()];
242         if (ret != null)
243             return ret;
244
245         SinglePixelPackedSampleModel JavaDoc sppsm;
246         sppsm = (SinglePixelPackedSampleModel JavaDoc)getSampleModel();
247         int stride = sppsm.getScanlineStride();
248         int th = sppsm.getHeight();
249
250         // The span we need to cover in the input image.
251
int height = th+2*maxOffY;
252
253         // The start and end Y in image's tile coordinate system...
254
int y0 = (getTileGridYOffset() + (yTile*th) - maxOffY
255                        -image.getTileGridYOffset());
256         int y1 = y0+height-1;
257
258         int tile = (int)Math.floor(y0/(double)th);
259         int endTile = (int)Math.floor(y1/(double)th);
260         int loc = y0-(tile*th);
261         int endLoc = th;
262
263         // Amount not used from bottom edge tile
264
int slop = ((endTile+1)*th-1) - y1;
265         
266         ret = new TileOffsets(height, 0, stride,
267                               loc, endLoc, slop, tile, endTile);
268
269         yOffsets[yTile-getMinTileY()] = ret;
270         return ret;
271     }
272
273     public void filterBL(Raster JavaDoc off, WritableRaster JavaDoc dst,
274                          int [] xTile, int [] xOff,
275                          int [] yTile, int [] yOff) {
276         final int w = dst.getWidth();
277         final int h = dst.getHeight();
278         final int xStart = maxOffX;
279         final int yStart = maxOffY;
280         final int xEnd = xStart+w;
281         final int yEnd = yStart+h;
282
283         // Access the integer buffer for each image.
284
DataBufferInt JavaDoc dstDB = (DataBufferInt JavaDoc)dst.getDataBuffer();
285         DataBufferInt JavaDoc offDB = (DataBufferInt JavaDoc)off.getDataBuffer();
286
287         // Offset defines where in the stack the real data begin
288
SinglePixelPackedSampleModel JavaDoc dstSPPSM, offSPPSM;
289
290         dstSPPSM = (SinglePixelPackedSampleModel JavaDoc)dst.getSampleModel();
291         final int dstOff = dstDB.getOffset() +
292             dstSPPSM.getOffset(dst.getMinX() - dst.getSampleModelTranslateX(),
293                                dst.getMinY() - dst.getSampleModelTranslateY());
294
295         offSPPSM = (SinglePixelPackedSampleModel JavaDoc)off.getSampleModel();
296         final int offOff = offDB.getOffset() +
297             offSPPSM.getOffset(dst.getMinX() - off.getSampleModelTranslateX(),
298                                dst.getMinY() - off.getSampleModelTranslateY());
299
300         // Stride is the distance between two consecutive column elements,
301
// in the one-dimention dataBuffer
302
final int dstScanStride = dstSPPSM.getScanlineStride();
303         final int offScanStride = offSPPSM.getScanlineStride();
304
305         final int dstAdjust = dstScanStride - w;
306         final int offAdjust = offScanStride - w;
307
308         // Access the pixel value array
309
final int dstPixels[] = dstDB.getBankData()[0];
310         final int offPixels[] = offDB.getBankData()[0];
311
312         // Below is the number of shifts for each axis
313
// e.g when xChannel is ALPHA, the pixel needs
314
// to be shifted 24, RED 16, GREEN 8 and BLUE 0
315
final int xShift = xChannel.toInt()*8;
316         final int yShift = yChannel.toInt()*8;
317
318         // The pointer of img and dst indicating where the pixel values are
319
int dp = dstOff, ip = offOff;
320
321         // Fixed point representation of scale factor.
322
final int fpScaleX = (int)((scaleX/255.0)*(1<<15)+0.5);
323         final int fpAdjX = (int)(-127.5*fpScaleX-0.5);
324         final int fpScaleY = (int)((scaleY/255.0)*(1<<15)+0.5);
325         final int fpAdjY = (int)(-127.5*fpScaleY-0.5);
326
327         long start = System.currentTimeMillis();
328
329         int pel00, pel01, pel10, pel11, xFrac, yFrac, newPel;
330         int sp0, sp1, pel0, pel1;
331
332         int x, y, x0, y0, xDisplace, yDisplace, dPel;
333
334         int xt=xTile[0]-1, yt=yTile[0]-1, xt1, yt1;
335         int [] imgPix = null;
336
337         for (y=yStart; y<yEnd; y++) {
338             for (x=xStart; x<xEnd; x++, dp++, ip++) {
339                 dPel = offPixels[ip];
340                 
341                 xDisplace = (fpScaleX*((dPel>>xShift)&0xff))+fpAdjX;
342                 yDisplace = (fpScaleY*((dPel>>yShift)&0xff))+fpAdjY;
343                 
344                 x0 = x+(xDisplace>>15);
345                 y0 = y+(yDisplace>>15);
346
347                 if ((xt != xTile[x0]) ||
348                     (yt != yTile[y0])) {
349                     xt = xTile[x0]; yt = yTile[y0];
350                     imgPix = ((DataBufferInt JavaDoc)image.getTile(xt, yt)
351                               .getDataBuffer()).getBankData()[0];
352                 }
353                 pel00 = imgPix[xOff[x0]+yOff[y0]];
354
355                 xt1 = xTile[x0+1];
356                 yt1 = yTile[y0+1];
357                 if ((yt == yt1)) {
358                     // Same tile vertically, check across...
359
if ((xt == xt1)) {
360                         // All from same tile..
361
pel10 = imgPix[xOff[x0+1]+yOff[y0]];
362                         pel01 = imgPix[xOff[x0] +yOff[y0+1]];
363                         pel11 = imgPix[xOff[x0+1]+yOff[y0+1]];
364                     } else {
365                         // Different tile horizontally...
366
pel01 = imgPix[xOff[x0]+yOff[y0+1]];
367
368                         imgPix = ((DataBufferInt JavaDoc)image.getTile(xt1, yt)
369                                   .getDataBuffer()).getBankData()[0];
370                         pel10 = imgPix[xOff[x0+1]+yOff[y0]];
371                         pel11 = imgPix[xOff[x0+1]+yOff[y0+1]];
372                         xt = xt1;
373                     }
374                 } else {
375                     // Steped into next tile down, check across...
376
if ((xt == xt1)) {
377                         // Different tile horizontally.
378
pel10 = imgPix[xOff[x0+1]+yOff[y0]];
379
380                         imgPix = ((DataBufferInt JavaDoc)image.getTile(xt, yt1)
381                                   .getDataBuffer()).getBankData()[0];
382                         pel01 = imgPix[xOff[x0] +yOff[y0+1]];
383                         pel11 = imgPix[xOff[x0+1]+yOff[y0+1]];
384                         yt = yt1;
385                     } else {
386                         // Ugg we are at the 4way intersection of tiles...
387
imgPix = ((DataBufferInt JavaDoc)image.getTile(xt, yt1)
388                                   .getDataBuffer()).getBankData()[0];
389                         pel01 = imgPix[xOff[x0]+yOff[y0+1]];
390
391                         imgPix = ((DataBufferInt JavaDoc)image.getTile(xt1, yt1)
392                                   .getDataBuffer()).getBankData()[0];
393                         pel11 = imgPix[xOff[x0+1]+yOff[y0+1]];
394                         
395                         imgPix = ((DataBufferInt JavaDoc)image.getTile(xt1, yt)
396                                   .getDataBuffer()).getBankData()[0];
397                         pel10 = imgPix[xOff[x0+1]+yOff[y0]];
398                         xt = xt1;
399                     }
400                 }
401
402                 xFrac = xDisplace&0x7FFF;
403                 yFrac = yDisplace&0x7FFF;
404
405                 // Combine the alpha channels.
406
sp0 = (pel00>>>16) & 0xFF00;
407                 sp1 = (pel10>>>16) & 0xFF00;
408                 pel0 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
409                 sp0 = (pel01>>>16) & 0xFF00;
410                 sp1 = (pel11>>>16) & 0xFF00;
411                 pel1 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
412                 newPel = (((pel0<<15) + (pel1-pel0)*yFrac + 0x00400000)
413                           &0x7F800000)<< 1;
414
415                 // Combine the red channels.
416
sp0 = (pel00>> 8) & 0xFF00;
417                 sp1 = (pel10>> 8) & 0xFF00;
418                 pel0 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
419                 sp0 = (pel01>> 8) & 0xFF00;
420                 sp1 = (pel11>> 8) & 0xFF00;
421                 pel1 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
422                 newPel |= (((pel0<<15) + (pel1-pel0)*yFrac + 0x00400000)
423                            &0x7F800000)>>> 7;
424
425                 // Combine the green channels.
426
sp0 = (pel00 ) & 0xFF00;
427                 sp1 = (pel10 ) & 0xFF00;
428                 pel0 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
429                 sp0 = (pel01 ) & 0xFF00;
430                 sp1 = (pel11 ) & 0xFF00;
431                 pel1 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
432                 newPel |= (((pel0<<15) + (pel1-pel0)*yFrac + 0x00400000)
433                            &0x7F800000)>>>15;
434
435                 // Combine the blue channels.
436
sp0 = (pel00<< 8) & 0xFF00;
437                 sp1 = (pel10<< 8) & 0xFF00;
438                 pel0 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
439                 sp0 = (pel01<< 8) & 0xFF00;
440                 sp1 = (pel11<< 8) & 0xFF00;
441                 pel1 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
442                 newPel |= (((pel0<<15) + (pel1-pel0)*yFrac + 0x00400000)
443                            &0x7F800000)>>>23;
444
445                 dstPixels[dp] = newPel;
446             }
447
448             dp += dstAdjust;
449             ip += offAdjust;
450         }
451
452         if (TIME) {
453             long end = System.currentTimeMillis();
454             System.out.println("Time: " + (end-start));
455         }
456     }// end of the filter() method for Raster
457

458     public void filterBLPre(Raster JavaDoc off, WritableRaster JavaDoc dst,
459                             int [] xTile, int [] xOff,
460                             int [] yTile, int [] yOff) {
461         final int w = dst.getWidth();
462         final int h = dst.getHeight();
463         final int xStart = maxOffX;
464         final int yStart = maxOffY;
465         final int xEnd = xStart+w;
466         final int yEnd = yStart+h;
467
468         // Access the integer buffer for each image.
469
DataBufferInt JavaDoc dstDB = (DataBufferInt JavaDoc)dst.getDataBuffer();
470         DataBufferInt JavaDoc offDB = (DataBufferInt JavaDoc)off.getDataBuffer();
471
472         // Offset defines where in the stack the real data begin
473
SinglePixelPackedSampleModel JavaDoc dstSPPSM, offSPPSM;
474
475         dstSPPSM = (SinglePixelPackedSampleModel JavaDoc)dst.getSampleModel();
476         final int dstOff = dstDB.getOffset() +
477             dstSPPSM.getOffset(dst.getMinX() - dst.getSampleModelTranslateX(),
478                                dst.getMinY() - dst.getSampleModelTranslateY());
479
480         offSPPSM = (SinglePixelPackedSampleModel JavaDoc)off.getSampleModel();
481         final int offOff = offDB.getOffset() +
482             offSPPSM.getOffset(dst.getMinX() - off.getSampleModelTranslateX(),
483                                dst.getMinY() - off.getSampleModelTranslateY());
484
485         // Stride is the distance between two consecutive column elements,
486
// in the one-dimention dataBuffer
487
final int dstScanStride = dstSPPSM.getScanlineStride();
488         final int offScanStride = offSPPSM.getScanlineStride();
489
490         final int dstAdjust = dstScanStride - w;
491         final int offAdjust = offScanStride - w;
492
493         // Access the pixel value array
494
final int dstPixels[] = dstDB.getBankData()[0];
495         final int offPixels[] = offDB.getBankData()[0];
496
497         // Below is the number of shifts for each axis
498
// e.g when xChannel is ALPHA, the pixel needs
499
// to be shifted 24, RED 16, GREEN 8 and BLUE 0
500
final int xShift = xChannel.toInt()*8;
501         final int yShift = yChannel.toInt()*8;
502
503         // The pointer of img and dst indicating where the pixel values are
504
int dp = dstOff, ip = offOff;
505
506         // Fixed point representation of scale factor.
507
// Fixed point representation of scale factor.
508
final int fpScaleX = (int)((scaleX/255.0)*(1<<15)+0.5);
509         final int fpAdjX = (int)(-127.5*fpScaleX-0.5);
510         final int fpScaleY = (int)((scaleY/255.0)*(1<<15)+0.5);
511         final int fpAdjY = (int)(-127.5*fpScaleY-0.5);
512
513         long start = System.currentTimeMillis();
514
515         int pel00, pel01, pel10, pel11, xFrac, yFrac, newPel;
516         int sp0, sp1, pel0, pel1, a00, a01, a10, a11;
517
518         int x, y, x0, y0, xDisplace, yDisplace, dPel;
519         final int norm = (1<<24)/255;
520
521         int xt=xTile[0]-1, yt=yTile[0]-1, xt1, yt1;
522         int [] imgPix = null;
523
524         for (y=yStart; y<yEnd; y++) {
525             for (x=xStart; x<xEnd; x++, dp++, ip++) {
526                 dPel = offPixels[ip];
527                 
528                 xDisplace = (fpScaleX*((dPel>>xShift)&0xff))+fpAdjX;
529                 yDisplace = (fpScaleY*((dPel>>yShift)&0xff))+fpAdjY;
530                 
531                 x0 = x+(xDisplace>>15);
532                 y0 = y+(yDisplace>>15);
533
534                 if ((xt != xTile[x0]) || (yt != yTile[y0])) {
535                     xt = xTile[x0];
536                     yt = yTile[y0];
537                     imgPix = ((DataBufferInt JavaDoc)image.getTile(xt, yt)
538                               .getDataBuffer()).getBankData()[0];
539                 }
540                 pel00 = imgPix[xOff[x0]+yOff[y0]];
541
542                 xt1 = xTile[x0+1];
543                 yt1 = yTile[y0+1];
544                 if ((yt == yt1)) {
545                     // Same tile vertically, check across...
546
if ((xt == xt1)) {
547                         // All from same tile..
548
pel10 = imgPix[xOff[x0+1]+yOff[y0]];
549                         pel01 = imgPix[xOff[x0] +yOff[y0+1]];
550                         pel11 = imgPix[xOff[x0+1]+yOff[y0+1]];
551                     } else {
552                         // Different tile horizontally...
553
pel01 = imgPix[xOff[x0]+yOff[y0+1]];
554
555                         imgPix = ((DataBufferInt JavaDoc)image.getTile(xt1, yt)
556                                   .getDataBuffer()).getBankData()[0];
557                         pel10 = imgPix[xOff[x0+1]+yOff[y0]];
558                         pel11 = imgPix[xOff[x0+1]+yOff[y0+1]];
559                         xt = xt1;
560                     }
561                 } else {
562                     // Steped into next tile down, check across...
563
if ((xt == xt1)) {
564                         // Different tile horizontally.
565
pel10 = imgPix[xOff[x0+1]+yOff[y0]];
566
567                         imgPix = ((DataBufferInt JavaDoc)image.getTile(xt, yt1)
568                                   .getDataBuffer()).getBankData()[0];
569                         pel01 = imgPix[xOff[x0] +yOff[y0+1]];
570                         pel11 = imgPix[xOff[x0+1]+yOff[y0+1]];
571                         yt = yt1;
572                     } else {
573                         // Ugg we are at the 4way intersection of tiles...
574
imgPix = ((DataBufferInt JavaDoc)image.getTile(xt, yt1)
575                                   .getDataBuffer()).getBankData()[0];
576                         pel01 = imgPix[xOff[x0]+yOff[y0+1]];
577
578                         imgPix = ((DataBufferInt JavaDoc)image.getTile(xt1, yt1)
579                                   .getDataBuffer()).getBankData()[0];
580                         pel11 = imgPix[xOff[x0+1]+yOff[y0+1]];
581                         
582                         imgPix = ((DataBufferInt JavaDoc)image.getTile(xt1, yt)
583                                   .getDataBuffer()).getBankData()[0];
584                         pel10 = imgPix[xOff[x0+1]+yOff[y0]];
585                         xt = xt1;
586                     }
587                 }
588
589                 xFrac = xDisplace&0x7FFF;
590                 yFrac = yDisplace&0x7FFF;
591
592                 // Combine the alpha channels.
593
sp0 = (pel00>>>16) & 0xFF00;
594                 sp1 = (pel10>>>16) & 0xFF00;
595                 pel0 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
596                 a00 = ((sp0>>8)*norm + 0x80)>>8;
597                 a10 = ((sp1>>8)*norm + 0x80)>>8;
598
599                 sp0 = (pel01>>>16) & 0xFF00;
600                 sp1 = (pel11>>>16) & 0xFF00;
601                 pel1 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
602                 a01 = ((sp0>>8)*norm + 0x80)>>8;
603                 a11 = ((sp1>>8)*norm + 0x80)>>8;
604                 newPel = (((pel0<<15) + (pel1-pel0)*yFrac + 0x00400000)
605                           &0x7F800000)<< 1;
606
607                 // Combine the red channels.
608
sp0 = ((((pel00>> 16) & 0xFF)*a00) + 0x80)>>8;
609                 sp1 = ((((pel10>> 16) & 0xFF)*a10) + 0x80)>>8;
610                 pel0 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
611                 sp0 = ((((pel01>> 16) & 0xFF)*a01) + 0x80)>>8;
612                 sp1 = ((((pel11>> 16) & 0xFF)*a11) + 0x80)>>8;
613                 pel1 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
614                 newPel |= (((pel0<<15) + (pel1-pel0)*yFrac + 0x00400000)
615                            &0x7F800000)>>> 7;
616
617                 // Combine the green channels.
618
sp0 = ((((pel00>> 8) & 0xFF)*a00) + 0x80)>>8;
619                 sp1 = ((((pel10>> 8) & 0xFF)*a10) + 0x80)>>8;
620                 pel0 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
621                 sp0 = ((((pel01>> 8) & 0xFF)*a01) + 0x80)>>8;
622                 sp1 = ((((pel11>> 8) & 0xFF)*a11) + 0x80)>>8;
623                 pel1 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
624                 newPel |= (((pel0<<15) + (pel1-pel0)*yFrac + 0x00400000)
625                            &0x7F800000)>>>15;
626
627                 // Combine the blue channels.
628
sp0 = (((pel00 & 0xFF)*a00) + 0x80)>>8;
629                 sp1 = (((pel10 & 0xFF)*a10) + 0x80)>>8;
630                 pel0 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
631                 sp0 = (((pel01 & 0xFF)*a01) + 0x80)>>8;
632                 sp1 = (((pel11 & 0xFF)*a11) + 0x80)>>8;
633                 pel1 = (sp0 + (((sp1-sp0)*xFrac+0x4000)>>15)) & 0xFFFF;
634                 newPel |= (((pel0<<15) + (pel1-pel0)*yFrac + 0x00400000)
635                            &0x7F800000)>>>23;
636
637                 dstPixels[dp] = newPel;
638             }
639
640             dp += dstAdjust;
641             ip += offAdjust;
642         }
643
644         if (TIME) {
645             long end = System.currentTimeMillis();
646             System.out.println("Time: " + (end-start));
647         }
648     }// end of the filter() method for Raster
649

650     /**
651      * Does displacement map using Nearest neighbor interpolation
652      *
653      * @param off the displacement map
654      * @param dst stores the filtered image. If null, a destination will
655      * be created. img and dst can refer to the same Raster, in
656      * which situation the img will be modified.
657      */

658     public void filterNN(Raster JavaDoc off, WritableRaster JavaDoc dst,
659                          int [] xTile, int [] xOff,
660                          int [] yTile, int [] yOff) {
661         final int w = dst.getWidth();
662         final int h = dst.getHeight();
663         final int xStart = maxOffX;
664         final int yStart = maxOffY;
665         final int xEnd = xStart+w;
666         final int yEnd = yStart+h;
667
668         // Access the integer buffer for each image.
669
DataBufferInt JavaDoc dstDB = (DataBufferInt JavaDoc)dst.getDataBuffer();
670         DataBufferInt JavaDoc offDB = (DataBufferInt JavaDoc)off.getDataBuffer();
671
672         // Offset defines where in the stack the real data begin
673
SinglePixelPackedSampleModel JavaDoc dstSPPSM, offSPPSM;
674
675         dstSPPSM = (SinglePixelPackedSampleModel JavaDoc)dst.getSampleModel();
676         final int dstOff = dstDB.getOffset() +
677             dstSPPSM.getOffset(dst.getMinX() - dst.getSampleModelTranslateX(),
678                                dst.getMinY() - dst.getSampleModelTranslateY());
679
680         offSPPSM = (SinglePixelPackedSampleModel JavaDoc)off.getSampleModel();
681         final int offOff = offDB.getOffset() +
682             offSPPSM.getOffset(off.getMinX() - off.getSampleModelTranslateX(),
683                                off.getMinY() - off.getSampleModelTranslateY());
684
685         // Stride is the distance between two consecutive column elements,
686
// in the one-dimention dataBuffer
687
final int dstScanStride = dstSPPSM.getScanlineStride();
688         final int offScanStride = offSPPSM.getScanlineStride();
689
690         final int dstAdjust = dstScanStride - w;
691         final int offAdjust = offScanStride - w;
692
693         // Access the pixel value array
694
final int dstPixels[] = dstDB.getBankData()[0];
695         final int offPixels[] = offDB.getBankData()[0];
696
697         // Below is the number of shifts for each axis
698
// e.g when xChannel is ALPHA, the pixel needs
699
// to be shifted 24, RED 16, GREEN 8 and BLUE 0
700
final int xShift = xChannel.toInt()*8;
701         final int yShift = yChannel.toInt()*8;
702
703         final int fpScaleX = (int)((scaleX/255.0)*(1<<15)+0.5);
704         final int fpScaleY = (int)((scaleY/255.0)*(1<<15)+0.5);
705
706         // Calculate the shift to make '.5' no movement.
707
// This also includes rounding factor (0x4000) for Fixed Point stuff.
708
final int fpAdjX = (int)(-127.5*fpScaleX-0.5) + 0x4000;
709         final int fpAdjY = (int)(-127.5*fpScaleY-0.5) + 0x4000;
710
711         // The pointer of img and dst indicating where the pixel values are
712
int dp = dstOff, ip = offOff;
713
714         long start = System.currentTimeMillis();
715         int y=yStart, xt=xTile[0]-1, yt=yTile[0]-1;
716         int [] imgPix = null;
717
718         int x0, y0, xDisplace, yDisplace, dPel;
719         while (y<yEnd) {
720             int x=xStart;
721             while (x<xEnd) {
722                 dPel = offPixels[ip];
723                 
724                 xDisplace = (fpScaleX*((dPel>>xShift)&0xff))+fpAdjX;
725                 yDisplace = (fpScaleY*((dPel>>yShift)&0xff))+fpAdjY;
726
727                 x0 = x+(xDisplace>>15);
728                 y0 = y+(yDisplace>>15);
729
730                 if ((xt != xTile[x0]) ||
731                     (yt != yTile[y0])) {
732                     xt = xTile[x0]; yt = yTile[y0];
733                     imgPix = ((DataBufferInt JavaDoc)image.getTile(xt, yt)
734                               .getDataBuffer()).getBankData()[0];
735                 }
736                 dstPixels[dp] = imgPix[xOff[x0]+yOff[y0]];
737
738                 dp++;
739                 ip++;
740                 x++;
741             }
742
743             dp += dstAdjust;
744             ip += offAdjust;
745             y++;
746         }
747         if (TIME) {
748             long end = System.currentTimeMillis();
749             System.out.println("Time: " + (end-start));
750         }
751     }// end of the filter() method for Raster
752
}
753
754
755
Popular Tags