KickJava   Java API By Example, From Geeks To Geeks.

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


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.image.DataBufferInt JavaDoc;
22 import java.awt.image.Raster JavaDoc;
23 import java.awt.image.RenderedImage JavaDoc;
24 import java.awt.image.SinglePixelPackedSampleModel JavaDoc;
25
26 /**
27  * Default BumpMap implementation.
28  *
29  * @author <a HREF="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
30  * @version $Id: BumpMap.java,v 1.7 2005/03/27 08:58:33 cam Exp $
31  */

32 public final class BumpMap {
33     /**
34      * Image whose alpha channel is used for the
35      * normal calculation
36      */

37     private RenderedImage JavaDoc texture;
38
39     /**
40      * Surface scale used in the normal computation
41      */

42     private double surfaceScale, surfaceScaleX, surfaceScaleY;
43
44     /**
45      * User space to device space scale factors
46      */

47     private double scaleX, scaleY;
48
49     /**
50      * Stores the normals for this bumpMap.
51      * scaleX and scaleY are the user space to device
52      * space scales.
53      */

54     public BumpMap(RenderedImage JavaDoc texture,
55                    double surfaceScale,
56                    double scaleX, double scaleY){
57         this.texture = texture;
58         this.surfaceScaleX = surfaceScale*scaleX;
59         this.surfaceScaleY = surfaceScale*scaleY;
60         this.surfaceScale = surfaceScale;
61         this.scaleX = scaleX;
62         this.scaleY = scaleY;
63     }
64
65     /**
66      * @return surface scale used by this bump map.
67      */

68     public final double getSurfaceScale(){
69         return surfaceScale;
70     }
71
72     /**
73      * @param x x-axis coordinate for which the normal is computed
74      * @param y y-axis coordinate for which the normal is computed
75      */

76     public final double[][][] getNormalArray
77         (final int x, final int y,
78          final int w, final int h)
79     {
80         final double[][][] N = new double[h][w][4];
81
82         Rectangle JavaDoc srcRect = new Rectangle JavaDoc(x-1, y-1, w+2, h+2);
83         Rectangle JavaDoc srcBound = new Rectangle JavaDoc
84             (texture.getMinX(), texture.getMinY(),
85              texture.getWidth(), texture.getHeight());
86
87         if (srcRect.intersects(srcBound) == false)
88             return N;
89         
90         srcRect = srcRect.intersection(srcBound);
91         final Raster JavaDoc r = texture.getData(srcRect);
92
93         srcRect = r.getBounds();
94
95         // System.out.println("SrcRect: " + srcRect);
96
// System.out.println("rect: [" +
97
// x + ", " + y + ", " +
98
// w + ", " + h + "]");
99

100         final DataBufferInt JavaDoc db = (DataBufferInt JavaDoc)r.getDataBuffer();
101
102
103         final int[] pixels = db.getBankData()[0];
104
105         final SinglePixelPackedSampleModel JavaDoc sppsm;
106         sppsm = (SinglePixelPackedSampleModel JavaDoc)r.getSampleModel();
107
108
109         final int scanStride = sppsm.getScanlineStride();
110         final int scanStridePP = scanStride + 1;
111         final int scanStrideMM = scanStride - 1;
112         double prpc=0, prcc=0, prnc=0;
113         double crpc=0, crcc=0, crnc=0;
114         double nrpc=0, nrcc=0, nrnc=0;
115         double invNorm;
116
117         final double quarterSurfaceScaleX = surfaceScaleX / 4f;
118         final double quarterSurfaceScaleY = surfaceScaleY / 4f;
119         final double halfSurfaceScaleX = surfaceScaleX / 2f;
120         final double halfSurfaceScaleY = surfaceScaleY /2;
121         final double thirdSurfaceScaleX = surfaceScaleX / 3f;
122         final double thirdSurfaceScaleY = surfaceScaleY / 3f;
123         final double twoThirdSurfaceScaleX = surfaceScaleX * 2 / 3f;
124         final double twoThirdSurfaceScaleY = surfaceScaleY * 2 / 3f;
125
126         final double pixelScale = 1.0/255;
127
128         if(w <= 0)
129             return N;
130         // Process pixels on the border
131
if(h <= 0)
132             return N;
133
134         final int xEnd = Math.min(srcRect.x+srcRect.width -1, x+w);
135         final int yEnd = Math.min(srcRect.y+srcRect.height-1, y+h);
136         final int offset =
137             (db.getOffset() +
138              sppsm.getOffset(srcRect.x -r.getSampleModelTranslateX(),
139                              srcRect.y -r.getSampleModelTranslateY()));
140
141         int yloc=y;
142         if (yloc < srcRect.y) {
143             yloc = srcRect.y;
144         }
145
146         // Top edge extend filters...
147
if (yloc == srcRect.y) {
148             if (yloc == yEnd) {
149                 // Only one row of pixels...
150
final double [][] NRow = N[yloc-y];
151                 int xloc=x;
152                 if (xloc < srcRect.x)
153                     xloc = srcRect.x;
154                 int p = (offset + (xloc-srcRect.x) +
155                           scanStride*(yloc-srcRect.y));
156
157                 crcc = (pixels[p] >>> 24)*pixelScale;
158
159                 if (xloc != srcRect.x) {
160                     crpc = (pixels[p - 1] >>> 24)*pixelScale;
161                 }
162                 else if (xloc < xEnd) {
163                     // Top left pixel, in src (0, 0);
164
crnc = (pixels[p+1] >>> 24)*pixelScale;
165
166                     final double [] n = NRow[xloc-x];
167         
168                     n[0] = 2*surfaceScaleX*(crcc - crnc);
169                     invNorm = 1.0/Math.sqrt(n[0]*n[0] + 1);
170                     n[0] *= invNorm;
171                     n[1] = 0;
172                     n[2] = invNorm;
173                     n[3] = crcc*surfaceScale;
174                     p++;
175                     xloc++;
176                     crpc = crcc;
177                     crcc = crnc;
178                 } else {
179                     // Single pix.
180
crpc = crcc;
181                 }
182
183                 for (; xloc<xEnd; xloc++) {
184                     // Middle Top row...
185
crnc = (pixels[p+1] >>> 24)*pixelScale;
186                     final double [] n = NRow[xloc-x];
187
188                     n[0] = surfaceScaleX * (crpc - crnc );
189                     invNorm = 1.0/Math.sqrt(n[0]*n[0] + 1);
190                     n[0] *= invNorm;
191                     n[1] = 0;
192                     n[2] = invNorm;
193                     n[3] = crcc*surfaceScale;
194                     p++;
195                     crpc = crcc;
196                     crcc = crnc;
197                 }
198
199                 if ((xloc < x+w) &&
200                     (xloc == srcRect.x+srcRect.width-1)) {
201                     // Last pixel of top row
202
final double [] n = NRow[xloc-x];
203
204                     n[0] = 2*surfaceScaleX*(crpc - crcc);
205                     invNorm = 1.0/Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
206                     n[0] *= invNorm;
207                     n[1] *= invNorm;
208                     n[2] = invNorm;
209                     n[3] = crcc*surfaceScale;
210                 }
211                 return N;
212             }
213
214             final double [][] NRow = N[yloc-y];
215             int p = offset + scanStride*(yloc-srcRect.y);
216             int xloc=x;
217             if (xloc < srcRect.x)
218                 xloc = srcRect.x;
219             p += xloc-srcRect.x;
220
221             crcc = (pixels[p] >>> 24)*pixelScale;
222             nrcc = (pixels[p + scanStride] >>> 24)*pixelScale;
223
224             if (xloc != srcRect.x) {
225                 crpc = (pixels[p - 1] >>> 24)*pixelScale;
226                 nrpc = (pixels[p + scanStrideMM] >>> 24)*pixelScale;
227             }
228             else if (xloc < xEnd) {
229                 // Top left pixel, in src (0, 0);
230
crnc = (pixels[p+1] >>> 24)*pixelScale;
231                 nrnc = (pixels[p + scanStridePP] >>> 24)*pixelScale;
232
233                 final double [] n = NRow[xloc-x];
234         
235                 n[0] = - twoThirdSurfaceScaleX *
236                     ((2*crnc + nrnc - 2*crcc - nrcc));
237                 n[1] = - twoThirdSurfaceScaleY *
238                     ((2*nrcc + nrnc - 2*crcc - crnc));
239                 invNorm = 1.0/Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
240                 n[0] *= invNorm;
241                 n[1] *= invNorm;
242                 n[2] = invNorm;
243                 n[3] = crcc*surfaceScale;
244                 p++;
245                 xloc++;
246                 crpc = crcc;
247                 nrpc = nrcc;
248                 crcc = crnc;
249                 nrcc = nrnc;
250             } else {
251                 // Single pix
252
crpc = crcc;
253                 nrpc = nrcc;
254             }
255
256             for (; xloc<xEnd; xloc++) {
257                 // Middle Top row...
258
crnc = (pixels[p+1] >>> 24)*pixelScale;
259                 nrnc = (pixels[p + scanStridePP] >>> 24)*pixelScale;
260
261                 final double [] n = NRow[xloc-x];
262
263                 n[0] = - thirdSurfaceScaleX * (( 2*crnc + nrnc)
264                                                - (2*crpc + nrpc));
265                 n[1] = - halfSurfaceScaleY *(( nrpc + 2*nrcc + nrnc)
266                                              - (crpc + 2*crcc + crnc));
267             
268                 invNorm = 1.0/Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
269                 n[0] *= invNorm;
270                 n[1] *= invNorm;
271                 n[2] = invNorm;
272                 n[3] = crcc*surfaceScale;
273                 p++;
274                 crpc = crcc;
275                 nrpc = nrcc;
276                 crcc = crnc;
277                 nrcc = nrnc;
278             }
279
280             if ((xloc < x+w) &&
281                 (xloc == srcRect.x+srcRect.width-1)) {
282                 // Last pixel of top row
283
final double [] n = NRow[xloc-x];
284
285                 n[0] = - twoThirdSurfaceScaleX *(( 2*crcc + nrcc)
286                                                  - (2*crpc + nrpc));
287                 n[1] = - twoThirdSurfaceScaleY *(( 2*nrcc + nrpc)
288                                                  - (2*crcc + crpc));
289             
290                 invNorm = 1.0/Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
291                 n[0] *= invNorm;
292                 n[1] *= invNorm;
293                 n[2] = invNorm;
294                 n[3] = crcc*surfaceScale;
295             }
296             yloc++;
297         }
298
299         for (; yloc<yEnd; yloc++) {
300             final double [][] NRow = N[yloc-y];
301             int p = offset + scanStride*(yloc-srcRect.y);
302
303             int xloc=x;
304             if (xloc < srcRect.x)
305                 xloc = srcRect.x;
306
307             p += xloc-srcRect.x;
308
309             prcc = (pixels[p - scanStride] >>> 24)*pixelScale;
310             crcc = (pixels[p] >>> 24)*pixelScale;
311             nrcc = (pixels[p + scanStride] >>> 24)*pixelScale;
312             
313             if (xloc != srcRect.x) {
314                 prpc = (pixels[p - scanStridePP] >>> 24)*pixelScale;
315                 crpc = (pixels[p - 1] >>> 24)*pixelScale;
316                 nrpc = (pixels[p + scanStrideMM] >>> 24)*pixelScale;
317             }
318             else if (xloc < xEnd) {
319                 // Now, process left column, from (0, 1) to (0, h-1)
320
crnc = (pixels[p+1] >>> 24)*pixelScale;
321                 prnc = (pixels[p - scanStrideMM] >>> 24)*pixelScale;
322                 nrnc = (pixels[p + scanStridePP] >>> 24)*pixelScale;
323
324                 final double [] n = NRow[xloc-x];
325
326                 n[0] = - halfSurfaceScaleX *(( prnc + 2*crnc + nrnc)
327                                              - (prcc + 2*crcc + nrcc));
328                 n[1] = - thirdSurfaceScaleY *(( 2*prcc + prnc)
329                                               - ( 2*crcc + crnc));
330             
331                 invNorm = 1.0/Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
332                 n[0] *= invNorm;
333                 n[1] *= invNorm;
334                 n[2] = invNorm;
335                 n[3] = crcc*surfaceScale;
336
337                 p++;
338                 xloc++;
339
340                 prpc = prcc;
341                 crpc = crcc;
342                 nrpc = nrcc;
343                 prcc = prnc;
344                 crcc = crnc;
345                 nrcc = nrnc;
346             } else {
347                 // Single pix
348
prpc = prcc;
349                 crpc = crcc;
350                 nrpc = nrcc;
351             }
352
353             for (; xloc<xEnd; xloc++) {
354                 // Middle Middle row...
355
prnc = (pixels[p - scanStrideMM] >>> 24)*pixelScale;
356                 crnc = (pixels[p+1] >>> 24)*pixelScale;
357                 nrnc = (pixels[p + scanStridePP] >>> 24)*pixelScale;
358
359                 final double [] n = NRow[xloc-x];
360
361                 n[0] = - quarterSurfaceScaleX *(( prnc + 2*crnc + nrnc)
362                                                 - (prpc + 2*crpc + nrpc));
363                 n[1] = - quarterSurfaceScaleY *(( nrpc + 2*nrcc + nrnc)
364                                                 - (prpc + 2*prcc + prnc));
365                     
366                 invNorm = 1.0/Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
367                 n[0] *= invNorm;
368                 n[1] *= invNorm;
369                 n[2] = invNorm;
370                 n[3] = crcc*surfaceScale;
371
372                 p++;
373                 prpc = prcc;
374                 crpc = crcc;
375                 nrpc = nrcc;
376                 prcc = prnc;
377                 crcc = crnc;
378                 nrcc = nrnc;
379             }
380
381             if ((xloc < x+w) &&
382                 (xloc == srcRect.x+srcRect.width-1)) {
383                 // Now, proces right column, from (w-1, 1) to (w-1, h-1)
384
final double [] n = NRow[xloc-x];
385
386                 n[0] = - halfSurfaceScaleX *( (prcc + 2*crcc + nrcc)
387                                              -(prpc + 2*crpc + nrpc));
388                 n[1] = - thirdSurfaceScaleY *(( nrpc + 2*nrcc)
389                                               - ( prpc + 2*prcc));
390             
391                 invNorm = 1.0/Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
392                 n[0] *= invNorm;
393                 n[1] *= invNorm;
394                 n[2] = invNorm;
395                 n[3] = crcc*surfaceScale;
396             }
397         }
398
399         if ((yloc < y+h) &&
400             (yloc == srcRect.y+srcRect.height-1)) {
401             final double [][] NRow = N[yloc-y];
402             int p = offset + scanStride*(yloc-srcRect.y);
403             int xloc=x;
404             if (xloc < srcRect.x)
405                 xloc = srcRect.x;
406
407             p += xloc-srcRect.x;
408
409             crcc = (pixels[p] >>> 24)*pixelScale;
410             prcc = (pixels[p - scanStride] >>> 24)*pixelScale;
411
412             if (xloc != srcRect.x) {
413                 prpc = (pixels[p - scanStridePP] >>> 24)*pixelScale;
414                 crpc = (pixels[p - 1] >>> 24)*pixelScale;
415             }
416             else if (xloc < xEnd) {
417                 // Process first pixel of last row
418
crnc = (pixels[p + 1] >>> 24)*pixelScale;
419                 prnc = (pixels[p - scanStrideMM] >>> 24)*pixelScale;
420
421                 final double [] n = NRow[xloc-x];
422
423                 n[0] = - twoThirdSurfaceScaleX * ((2*crnc + prnc - 2*crcc - prcc));
424                 n[1] = - twoThirdSurfaceScaleY * ((2*crcc + crnc - 2*prcc - prnc));
425                 invNorm = 1.0/Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
426                 n[0] *= invNorm;
427                 n[1] *= invNorm;
428                 n[2] = invNorm;
429                 n[3] = crcc*surfaceScale;
430
431                 p++;
432                 xloc++;
433                 crpc = crcc;
434                 prpc = prcc;
435                 crcc = crnc;
436                 prcc = prnc;
437             } else {
438                 // Single pix
439
crpc = crcc;
440                 prpc = prcc;
441             }
442             
443             for (; xloc<xEnd; xloc++) {
444                 // Middle of Bottom row...
445
crnc = (pixels[p + 1] >>> 24)*pixelScale;
446                 prnc = (pixels[p - scanStrideMM] >>> 24)*pixelScale;
447
448                 // System.out.println("Vals: " +
449
// prpc + "," + prcc + "," + prnc + " " +
450
// crpc + "," + crcc + "," + crnc );
451

452                 final double [] n = NRow[xloc-x];
453
454                 n[0] = - thirdSurfaceScaleX *(( 2*crnc + prnc)
455                                               - (2*crpc + prpc));
456                 n[1] = - halfSurfaceScaleY *(( crpc + 2*crcc + crnc)
457                                              - (prpc + 2*prcc + prnc));
458             
459                 invNorm = 1.0/Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
460                 n[0] *= invNorm;
461                 n[1] *= invNorm;
462                 n[2] = invNorm;
463                 n[3] = crcc*surfaceScale;
464
465                 p++;
466                 crpc = crcc;
467                 prpc = prcc;
468                 crcc = crnc;
469                 prcc = prnc;
470             }
471
472             if ((xloc < x+w) &&
473                 (xloc == srcRect.x+srcRect.width-1)) {
474                 // Bottom right corner
475
final double [] n = NRow[xloc-x];
476
477                 n[0] = - twoThirdSurfaceScaleX *(( 2*crcc + prcc)
478                                                  - (2*crpc + prpc));
479                 n[1] = - twoThirdSurfaceScaleY *(( 2*crcc + crpc)
480                                                  - (2*prcc + prpc));
481             
482                 invNorm = 1.0/Math.sqrt(n[0]*n[0] + n[1]*n[1] + 1);
483                 n[0] *= invNorm;
484                 n[1] *= invNorm;
485                 n[2] = invNorm;
486                 n[3] = crcc*surfaceScale;
487             }
488         }
489         return N;
490     }
491 }
492
493
Popular Tags