package org.apache.batik.ext.awt.image.rendered;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.PixelInterleavedSampleModel;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
import java.util.ArrayList;
import java.util.List;
public class MultiplyAlphaRed extends AbstractRed {
public MultiplyAlphaRed(CachableRed src, CachableRed alpha) {
super(makeList(src, alpha),
makeBounds(src,alpha),
fixColorModel(src),
fixSampleModel(src),
src.getTileGridXOffset(),
src.getTileGridYOffset(),
null);
}
public boolean is_INT_PACK_BYTE_COMP(SampleModel srcSM,
SampleModel alpSM) {
if(!(srcSM instanceof SinglePixelPackedSampleModel)) return false;
if(!(alpSM instanceof ComponentSampleModel)) return false;
if(srcSM.getDataType() != DataBuffer.TYPE_INT) return false;
if(alpSM.getDataType() != DataBuffer.TYPE_BYTE) return false;
SinglePixelPackedSampleModel sppsm;
sppsm = (SinglePixelPackedSampleModel)srcSM;
int [] masks = sppsm.getBitMasks();
if(masks.length != 4) return false;
if(masks[0] != 0x00ff0000) return false;
if(masks[1] != 0x0000ff00) return false;
if(masks[2] != 0x000000ff) return false;
if(masks[3] != 0xff000000) return false;
ComponentSampleModel csm;
csm = (ComponentSampleModel)alpSM;
if (csm.getNumBands() != 1) return false;
if (csm.getPixelStride() != 1) return false;
return true;
}
public WritableRaster INT_PACK_BYTE_COMP_Impl (WritableRaster wr) {
CachableRed srcRed = (CachableRed)getSources().get(0);
CachableRed alphaRed = (CachableRed)getSources().get(1);
srcRed.copyData(wr);
Rectangle rgn = wr.getBounds();
rgn = rgn.intersection(alphaRed.getBounds());
Raster r = alphaRed.getData(rgn);
ComponentSampleModel csm;
csm = (ComponentSampleModel)r.getSampleModel();
final int alpScanStride = csm.getScanlineStride();
DataBufferByte alpDB = (DataBufferByte)r.getDataBuffer();
final int alpBase
= (alpDB.getOffset() +
csm.getOffset(rgn.x-r.getSampleModelTranslateX(),
rgn.y-r.getSampleModelTranslateY()));
final byte[] alpPixels = alpDB.getBankData()[0];
SinglePixelPackedSampleModel sppsm;
sppsm = (SinglePixelPackedSampleModel)wr.getSampleModel();
final int srcScanStride = sppsm.getScanlineStride();
DataBufferInt srcDB = (DataBufferInt)wr.getDataBuffer();
final int srcBase
= (srcDB.getOffset() +
sppsm.getOffset(rgn.x-wr.getSampleModelTranslateX(),
rgn.y-wr.getSampleModelTranslateY()));
final int[] srcPixels = srcDB.getBankData()[0];
ColorModel cm = srcRed.getColorModel();
if (cm.isAlphaPremultiplied()) {
for (int y=0; y<rgn.height; y++) {
int sp = srcBase + y*srcScanStride;
int ap = alpBase + y*alpScanStride;
int end = sp + rgn.width;
while (sp<end) {
int a = alpPixels[ap++] &0xFF;
final int pix = srcPixels[sp];
srcPixels[sp] =
((((((pix>>>24) ) *a)&0xFF00)<<16) |
(((((pix>>>16)&0xFF) *a)&0xFF00)<<8 ) |
(((((pix>>> 8)&0xFF) *a)&0xFF00) ) |
(((((pix )&0xFF) *a)&0xFF00)>>8 ));
sp++;
}
}
} else {
for (int y=0; y<rgn.height; y++) {
int sp = srcBase + y*srcScanStride;
int ap = alpBase + y*alpScanStride;
int end = sp + rgn.width;
while (sp<end) {
int a = alpPixels[ap++] &0xFF;
int sa = srcPixels[sp]>>>24;
srcPixels[sp] = ((((sa*a) & 0xFF00)<<16)|
srcPixels[sp]&0x00FFFFFF);
sp++;
}
}
}
return wr;
}
public WritableRaster copyData(WritableRaster wr) {
CachableRed srcRed = (CachableRed)getSources().get(0);
CachableRed alphaRed = (CachableRed)getSources().get(1);
if (is_INT_PACK_BYTE_COMP(srcRed.getSampleModel(),
alphaRed.getSampleModel()))
return INT_PACK_BYTE_COMP_Impl(wr);
ColorModel cm = srcRed.getColorModel();
if (cm.hasAlpha()) {
srcRed.copyData(wr);
Rectangle rgn = wr.getBounds();
if (rgn.intersects(alphaRed.getBounds()))
rgn = rgn.intersection(alphaRed.getBounds());
else
return wr;
int [] wrData = null;
int [] alphaData = null;
Raster r = alphaRed.getData(rgn);
int w = rgn.width;
final int bands = wr.getSampleModel().getNumBands();
if (cm.isAlphaPremultiplied()) {
for (int y=rgn.y; y<rgn.y+rgn.height; y++) {
wrData = wr.getPixels (rgn.x, y, w, 1, wrData);
alphaData = r .getSamples(rgn.x, y, w, 1, 0, alphaData);
int i=0, a, b;
switch (bands) {
case 2:
for (int anAlphaData2 : alphaData) {
a = anAlphaData2 & 0xFF;
wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
++i;
wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
++i;
}
break;
case 4:
for (int anAlphaData1 : alphaData) {
a = anAlphaData1 & 0xFF;
wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
++i;
wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
++i;
wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
++i;
wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
++i;
}
break;
default:
for (int anAlphaData : alphaData) {
a = anAlphaData & 0xFF;
for (b = 0; b < bands; b++) {
wrData[i] = ((wrData[i] & 0xFF) * a) >> 8;
++i;
}
}
}
wr.setPixels(rgn.x, y, w, 1, wrData);
}
} else {
int b = srcRed.getSampleModel().getNumBands()-1;
for (int y=rgn.y; y<rgn.y+rgn.height; y++) {
wrData = wr.getSamples(rgn.x, y, w, 1, b, wrData);
alphaData = r .getSamples(rgn.x, y, w, 1, 0, alphaData);
for (int i=0; i<wrData.length; i++) {
wrData[i] = ((wrData[i]&0xFF)*(alphaData[i]&0xFF))>>8;
}
wr.setSamples(rgn.x, y, w, 1, b, wrData);
}
}
return wr;
}
int [] bands = new int[wr.getNumBands()-1];
for (int i=0; i<bands.length; i++)
bands[i] = i;
WritableRaster subWr;
subWr = wr.createWritableChild(wr.getMinX(), wr.getMinY(),
wr.getWidth(), wr.getHeight(),
wr.getMinX(), wr.getMinY(),
bands);
srcRed.copyData(subWr);
Rectangle rgn = wr.getBounds();
rgn = rgn.intersection(alphaRed.getBounds());
bands = new int [] { wr.getNumBands()-1 };
subWr = wr.createWritableChild(rgn.x, rgn.y,
rgn.width, rgn.height,
rgn.x, rgn.y,
bands);
alphaRed.copyData(subWr);
return wr;
}
public static List makeList(CachableRed src1, CachableRed src2) {
List ret = new ArrayList(2);
ret.add(src1);
ret.add(src2);
return ret;
}
public static Rectangle makeBounds(CachableRed src1, CachableRed src2) {
Rectangle r1 = src1.getBounds();
Rectangle r2 = src2.getBounds();
return r1.intersection(r2);
}
public static SampleModel fixSampleModel(CachableRed src) {
ColorModel cm = src.getColorModel();
SampleModel srcSM = src.getSampleModel();
if (cm.hasAlpha())
return srcSM;
int w = srcSM.getWidth();
int h = srcSM.getHeight();
int b = srcSM.getNumBands()+1;
int [] offsets = new int[b];
for (int i=0; i < b; i++)
offsets[i] = i;
return new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
w, h, b, w*b, offsets);
}
public static ColorModel fixColorModel(CachableRed src) {
ColorModel cm = src.getColorModel();
if (cm.hasAlpha())
return cm;
int b = src.getSampleModel().getNumBands()+1;
int [] bits = new int[b];
for (int i=0; i < b; i++)
bits[i] = 8;
ColorSpace cs = cm.getColorSpace();
return new ComponentColorModel(cs, bits, true, false,
Transparency.TRANSLUCENT,
DataBuffer.TYPE_BYTE);
}
}