KickJava   Java API By Example, From Geeks To Geeks.

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


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.Transparency JavaDoc;
22 import java.awt.color.ColorSpace JavaDoc;
23 import java.awt.image.ColorModel JavaDoc;
24 import java.awt.image.ComponentColorModel JavaDoc;
25 import java.awt.image.ComponentSampleModel JavaDoc;
26 import java.awt.image.DataBuffer JavaDoc;
27 import java.awt.image.DataBufferByte JavaDoc;
28 import java.awt.image.DataBufferInt JavaDoc;
29 import java.awt.image.PixelInterleavedSampleModel JavaDoc;
30 import java.awt.image.Raster JavaDoc;
31 import java.awt.image.SampleModel JavaDoc;
32 import java.awt.image.SinglePixelPackedSampleModel JavaDoc;
33 import java.awt.image.WritableRaster JavaDoc;
34 import java.util.ArrayList JavaDoc;
35 import java.util.List JavaDoc;
36
37
38 /**
39  * This implements a masking operation by multiply the alpha channel of
40  * one image by a luminance image (the mask).
41  *
42  * @author <a HREF="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
43  * @version $Id: MultiplyAlphaRed.java,v 1.6 2004/08/18 07:14:08 vhardy Exp $ */

44 public class MultiplyAlphaRed extends AbstractRed {
45
46     /**
47      * Multiply the alpha of one image with a mask image.
48      * The size of the resultant image is the intersection of the
49      * two image bounds. If you want the end image to be the size
50      * of one or the other please use the PadRed operator.
51      *
52      * @param src The image to convert to multiply the alpha of
53      * @param alpha The mask image to multiply the alpha channel of src
54      * with.
55      */

56     public MultiplyAlphaRed(CachableRed src, CachableRed alpha) {
57         super(makeList(src, alpha),
58               makeBounds(src,alpha),
59               fixColorModel(src),
60               fixSampleModel(src),
61               src.getTileGridXOffset(),
62               src.getTileGridYOffset(),
63               null);
64     }
65
66     public boolean is_INT_PACK_BYTE_COMP(SampleModel JavaDoc srcSM,
67                                          SampleModel JavaDoc alpSM) {
68           // Check SampleModel types DirectColorModel
69
if(!(srcSM instanceof SinglePixelPackedSampleModel JavaDoc)) return false;
70         if(!(alpSM instanceof ComponentSampleModel JavaDoc)) return false;
71
72         // Check transfer types
73
if(srcSM.getDataType() != DataBuffer.TYPE_INT) return false;
74         if(alpSM.getDataType() != DataBuffer.TYPE_BYTE) return false;
75
76
77         SinglePixelPackedSampleModel JavaDoc sppsm;
78         sppsm = (SinglePixelPackedSampleModel JavaDoc)srcSM;
79
80         int [] masks = sppsm.getBitMasks();
81         if(masks.length != 4) return false;
82         if(masks[0] != 0x00ff0000) return false;
83         if(masks[1] != 0x0000ff00) return false;
84         if(masks[2] != 0x000000ff) return false;
85         if(masks[3] != 0xff000000) return false;
86  
87         ComponentSampleModel JavaDoc csm;
88         csm = (ComponentSampleModel JavaDoc)alpSM;
89         if (csm.getNumBands() != 1) return false;
90         if (csm.getPixelStride() != 1) return false;
91
92         return true;
93    }
94
95     public WritableRaster JavaDoc INT_PACK_BYTE_COMP_Impl (WritableRaster JavaDoc wr) {
96           // Get my source.
97
CachableRed srcRed = (CachableRed)getSources().get(0);
98         CachableRed alphaRed = (CachableRed)getSources().get(1);
99
100         // Already has alpha channel so we use it.
101
srcRed.copyData(wr);
102
103         Rectangle JavaDoc rgn = wr.getBounds();
104         rgn = rgn.intersection(alphaRed.getBounds());
105             
106         Raster JavaDoc r = alphaRed.getData(rgn);
107
108         ComponentSampleModel JavaDoc csm;
109         csm = (ComponentSampleModel JavaDoc)r.getSampleModel();
110         final int alpScanStride = csm.getScanlineStride();
111
112         DataBufferByte JavaDoc alpDB = (DataBufferByte JavaDoc)r.getDataBuffer();
113         final int alpBase
114             = (alpDB.getOffset() +
115                csm.getOffset(rgn.x-r.getSampleModelTranslateX(),
116                              rgn.y-r.getSampleModelTranslateY()));
117
118             
119           // Access the pixel data array
120
final byte alpPixels[] = alpDB.getBankData()[0];
121
122         SinglePixelPackedSampleModel JavaDoc sppsm;
123         sppsm = (SinglePixelPackedSampleModel JavaDoc)wr.getSampleModel();
124         final int srcScanStride = sppsm.getScanlineStride();
125
126         DataBufferInt JavaDoc srcDB = (DataBufferInt JavaDoc)wr.getDataBuffer();
127         final int srcBase
128             = (srcDB.getOffset() +
129                sppsm.getOffset(rgn.x-wr.getSampleModelTranslateX(),
130                                rgn.y-wr.getSampleModelTranslateY()));
131
132           // Access the pixel data array
133
final int srcPixels[] = srcDB.getBankData()[0];
134
135         ColorModel JavaDoc cm = srcRed.getColorModel();
136
137         if (cm.isAlphaPremultiplied()) {
138             // For alpha premult we need to multiply all comps.
139
for (int y=0; y<rgn.height; y++) {
140                 int sp = srcBase + y*srcScanStride;
141                 int ap = alpBase + y*alpScanStride;
142                 int end = sp + rgn.width;
143
144                 while (sp<end) {
145                     int a = ((int)alpPixels[ap++])&0xFF;
146                     final int pix = srcPixels[sp];
147                     srcPixels[sp] =
148                         ((((((pix>>>24) ) *a)&0xFF00)<<16) |
149                          (((((pix>>>16)&0xFF) *a)&0xFF00)<<8 ) |
150                          (((((pix>>> 8)&0xFF) *a)&0xFF00) ) |
151                          (((((pix )&0xFF) *a)&0xFF00)>>8 ));
152                     sp++;
153                 }
154             }
155                 
156         } else {
157               // For non-alpha premult we only need to multiply alpha.
158
for (int y=0; y<rgn.height; y++) {
159                 int sp = srcBase + y*srcScanStride;
160                 int ap = alpBase + y*alpScanStride;
161                 int end = sp + rgn.width;
162                 while (sp<end) {
163                     int a = ((int)alpPixels[ap++])&0xFF;
164                     int sa = srcPixels[sp]>>>24;
165                     srcPixels[sp] = ((((sa*a) & 0xFF00)<<16)|
166                                      srcPixels[sp]&0x00FFFFFF);
167                     sp++;
168                 }
169             }
170         }
171
172         return wr;
173     }
174
175     public WritableRaster JavaDoc copyData(WritableRaster JavaDoc wr) {
176         // Get my source.
177
CachableRed srcRed = (CachableRed)getSources().get(0);
178         CachableRed alphaRed = (CachableRed)getSources().get(1);
179
180         if (is_INT_PACK_BYTE_COMP(srcRed.getSampleModel(),
181                                   alphaRed.getSampleModel()))
182             return INT_PACK_BYTE_COMP_Impl(wr);
183
184         ColorModel JavaDoc cm = srcRed.getColorModel();
185         if (cm.hasAlpha()) {
186             // Already has alpha channel so we use it.
187
srcRed.copyData(wr);
188
189             Rectangle JavaDoc rgn = wr.getBounds();
190             if (rgn.intersects(alphaRed.getBounds()))
191                 rgn = rgn.intersection(alphaRed.getBounds());
192             else
193                 return wr;
194             
195             int [] wrData = null;
196             int [] alphaData = null;
197
198             Raster JavaDoc r = alphaRed.getData(rgn);
199             int w = rgn.width;
200
201             final int bands = wr.getSampleModel().getNumBands();
202
203             if (cm.isAlphaPremultiplied()) {
204                 for (int y=rgn.y; y<rgn.y+rgn.height; y++) {
205                     wrData = wr.getPixels (rgn.x, y, w, 1, wrData);
206                     alphaData = r .getSamples(rgn.x, y, w, 1, 0, alphaData);
207                     int i=0, a, b;
208                           // 4 is the most common case.
209
// 2 is probably next most common...
210
switch (bands) {
211                     case 2:
212                         for (int x=0; x<alphaData.length; x++) {
213                             a = alphaData[x]&0xFF;
214                             wrData[i] = ((wrData[i]&0xFF)*a)>>8; ++i;
215                             wrData[i] = ((wrData[i]&0xFF)*a)>>8; ++i;
216                         }
217                         break;
218                     case 4:
219                         for (int x=0; x<alphaData.length; x++) {
220                             a = alphaData[x]&0xFF;
221                             wrData[i] = ((wrData[i]&0xFF)*a)>>8; ++i;
222                             wrData[i] = ((wrData[i]&0xFF)*a)>>8; ++i;
223                             wrData[i] = ((wrData[i]&0xFF)*a)>>8; ++i;
224                             wrData[i] = ((wrData[i]&0xFF)*a)>>8; ++i;
225                         }
226                         break;
227                     default:
228                         for (int x=0; x<alphaData.length; x++) {
229                             a = alphaData[x]&0xFF;
230                             for (b=0; b<bands; b++) {
231                                 wrData[i] = ((wrData[i]&0xFF)*a)>>8;
232                                 ++i;
233                             }
234                         }
235                     }
236                     wr.setPixels(rgn.x, y, w, 1, wrData);
237                 }
238             } else {
239                 int b = srcRed.getSampleModel().getNumBands()-1;
240                 for (int y=rgn.y; y<rgn.y+rgn.height; y++) {
241                     wrData = wr.getSamples(rgn.x, y, w, 1, b, wrData);
242                     alphaData = r .getSamples(rgn.x, y, w, 1, 0, alphaData);
243                     for (int i=0; i<wrData.length; i++) {
244                         wrData[i] = ((wrData[i]&0xFF)*(alphaData[i]&0xFF))>>8;
245                     }
246                     wr.setSamples(rgn.x, y, w, 1, b, wrData);
247                 }
248             }
249
250             return wr;
251         }
252
253         // No alpha in source, so we hide the alpha channel in wr and
254
// have our source fill wr with color info...
255
int [] bands = new int[wr.getNumBands()-1];
256         for (int i=0; i<bands.length; i++)
257             bands[i] = i;
258
259         WritableRaster JavaDoc subWr;
260         subWr = wr.createWritableChild(wr.getMinX(), wr.getMinY(),
261                                        wr.getWidth(), wr.getHeight(),
262                                        wr.getMinX(), wr.getMinY(),
263                                        bands);
264
265         srcRed.copyData(subWr);
266
267         Rectangle JavaDoc rgn = wr.getBounds();
268         rgn = rgn.intersection(alphaRed.getBounds());
269             
270
271         bands = new int [] { wr.getNumBands()-1 };
272         subWr = wr.createWritableChild(rgn.x, rgn.y,
273                                        rgn.width, rgn.height,
274                                        rgn.x, rgn.y,
275                                        bands);
276         alphaRed.copyData(subWr);
277
278         return wr;
279     }
280
281     public static List JavaDoc makeList(CachableRed src1, CachableRed src2) {
282         List JavaDoc ret = new ArrayList JavaDoc(2);
283         ret.add(src1);
284         ret.add(src2);
285         return ret;
286     }
287
288     public static Rectangle JavaDoc makeBounds(CachableRed src1, CachableRed src2) {
289         Rectangle JavaDoc r1 = src1.getBounds();
290         Rectangle JavaDoc r2 = src2.getBounds();
291         return r1.intersection(r2);
292     }
293
294     public static SampleModel JavaDoc fixSampleModel(CachableRed src) {
295         ColorModel JavaDoc cm = src.getColorModel();
296         SampleModel JavaDoc srcSM = src.getSampleModel();
297
298         if (cm.hasAlpha())
299             return srcSM;
300
301         int w = srcSM.getWidth();
302         int h = srcSM.getHeight();
303         int b = srcSM.getNumBands()+1;
304         int [] offsets = new int[b];
305         for (int i=0; i < b; i++)
306             offsets[i] = i;
307
308         // Really should check DataType range in srcSM...
309
return new PixelInterleavedSampleModel JavaDoc(DataBuffer.TYPE_BYTE,
310                                                w, h, b, w*b, offsets);
311     }
312
313     public static ColorModel JavaDoc fixColorModel(CachableRed src) {
314         ColorModel JavaDoc cm = src.getColorModel();
315
316         if (cm.hasAlpha())
317             return cm;
318
319         int b = src.getSampleModel().getNumBands()+1;
320         int [] bits = new int[b];
321         for (int i=0; i < b; i++)
322             bits[i] = 8;
323
324         ColorSpace JavaDoc cs = cm.getColorSpace();
325
326         return new ComponentColorModel JavaDoc(cs, bits, true, false,
327                                        Transparency.TRANSLUCENT,
328                                        DataBuffer.TYPE_BYTE);
329     }
330 }
331
Popular Tags