in batik-awt-util/src/main/java/org/apache/batik/ext/awt/image/rendered/MorphologyOp.java [249:533]
private void specialProcessRow(Raster src, WritableRaster dest){
final int w = src.getWidth();
final int h = src.getHeight();
// Access the integer buffer for each image.
DataBufferInt srcDB = (DataBufferInt)src.getDataBuffer();
DataBufferInt dstDB = (DataBufferInt)dest.getDataBuffer();
// Offset defines where in the stack the real data begin
SinglePixelPackedSampleModel sppsm;
sppsm = (SinglePixelPackedSampleModel)src.getSampleModel();
final int srcOff = srcDB.getOffset() +
sppsm.getOffset(src.getMinX() - src.getSampleModelTranslateX(),
src.getMinY() - src.getSampleModelTranslateY());
sppsm = (SinglePixelPackedSampleModel)dest.getSampleModel();
final int dstOff = dstDB.getOffset() +
sppsm.getOffset(dest.getMinX() - dest.getSampleModelTranslateX(),
dest.getMinY() - dest.getSampleModelTranslateY());
// Stride is the distance between two consecutive column elements,
// in the one-dimention dataBuffer
final int srcScanStride = ((SinglePixelPackedSampleModel)src.getSampleModel()).getScanlineStride();
final int dstScanStride = ((SinglePixelPackedSampleModel)dest.getSampleModel()).getScanlineStride();
// Access the pixel value array
final int[] srcPixels = srcDB.getBankData()[0];
final int[] destPixels = dstDB.getBankData()[0];
// The pointer of src and dest indicating where the pixel values are
int sp, dp;
// Declaration for the circular buffer's implementation
// These are the circular buffers' head pointer and
// the index pointers
// bufferHead points to the leftmost element in the circular buffer
int bufferHead;
int maxIndexA;
int maxIndexR;
int maxIndexG;
int maxIndexB;
// Temp variables
int pel, currentPixel, lastPixel;
int a,r,g,b;
int a1,r1,g1,b1;
// If image width is less than or equal to the radiusX,
// all the pixels share the same max/min value
if (w<=radiusX){
for (int i=0; i<h; i++){
// pointing to the first pixels of each row
sp = srcOff + i*srcScanStride;
dp = dstOff + i*dstScanStride;
pel = srcPixels[sp++];
a = pel>>>24;
r = pel&0xff0000;
g = pel&0xff00;
b = pel&0xff;
for (int k=1; k<w; k++){
currentPixel = srcPixels[sp++];
a1 = currentPixel>>>24;
r1 = currentPixel&0xff0000;
g1 = currentPixel&0xff00;
b1 = currentPixel&0xff;
if (isBetter(a1, a, doDilation)){
a = a1;
}
if (isBetter(r1, r, doDilation)){
r = r1;
}
if (isBetter(g1, g, doDilation)){
g = g1;
}
if (isBetter(b1, b, doDilation)){
b = b1;
}
}
// all the element share the same max/min value
for (int k=0; k<w; k++){
destPixels[dp++] = (a << 24) | r | g | b;
}
}
}
// When radiusX < w <= 2*radiusX
else {
// The width of the circular buffer is w
final int [] bufferA = new int [w];
final int [] bufferR = new int [w];
final int [] bufferG = new int [w];
final int [] bufferB = new int [w];
for (int i=0; i<h; i++){
// initialization of pointers, indice
// at the head of each row
sp = srcOff + i*srcScanStride;
dp = dstOff + i*dstScanStride;
bufferHead = 0;
maxIndexA = 0;
maxIndexR = 0;
maxIndexG = 0;
maxIndexB = 0;
pel = srcPixels[sp++];
a = pel>>>24;
r = pel&0xff0000;
g = pel&0xff00;
b = pel&0xff;
bufferA[0] = a;
bufferR[0] = r;
bufferG[0] = g;
bufferB[0] = b;
for (int k=1; k<=radiusX; k++){
currentPixel = srcPixels[sp++];
a1 = currentPixel>>>24;
r1 = currentPixel&0xff0000;
g1 = currentPixel&0xff00;
b1 = currentPixel&0xff;
bufferA[k] = a1;
bufferR[k] = r1;
bufferG[k] = g1;
bufferB[k] = b1;
if (isBetter(a1, a, doDilation)){
a = a1;
maxIndexA = k;
}
if (isBetter(r1, r, doDilation)){
r = r1;
maxIndexR = k;
}
if (isBetter(g1, g, doDilation)){
g = g1;
maxIndexG = k;
}
if (isBetter(b1, b, doDilation)){
b = b1;
maxIndexB = k;
}
}
destPixels[dp++] = (a << 24) | r | g | b;
//
// 1 <= j <= w-radiusX-1 : The left margin of each row.
//
for (int j=1; j<=w-radiusX-1; j++){
lastPixel = srcPixels[sp++];
// here is the Alpha channel
// we retrieve the previous max/min value
a = bufferA[maxIndexA];
a1 = lastPixel>>>24;
bufferA[j+radiusX] = a1;
if (isBetter(a1, a, doDilation)){
a = a1;
maxIndexA = j+radiusX;
}
// now we deal with the Red channel
r = bufferR[maxIndexR];
r1 = lastPixel&0xff0000;
bufferR[j+radiusX] = r1;
if (isBetter(r1, r, doDilation)){
r = r1;
maxIndexR = j+radiusX;
}
// now we deal with the Green channel
g = bufferG[maxIndexG];
g1 = lastPixel&0xff00;
bufferG[j+radiusX] = g1;
if (isBetter(g1, g, doDilation)){
g = g1;
maxIndexG = j+radiusX;
}
// now we deal with the Blue channel
b = bufferB[maxIndexB];
b1 = lastPixel&0xff;
bufferB[j+radiusX] = b1;
if (isBetter(b1, b, doDilation)){
b = b1;
maxIndexB = j+radiusX;
}
// now we have gone through the four channels and
// updated the index array. then we'll pack the
// new max/min value according to each channel's
// max/min vlue
destPixels[dp++] = (a << 24) | r | g | b;
}
// Now is the inner body of the row:
// all elements in this segment share the same max/min value
for (int j = w-radiusX; j<= radiusX; j++){
destPixels[dp] = destPixels[dp-1];
dp++;
}
// Now the circular buffer is full
// Now is the right margin of the row when radiusX < w <= 2*radiusX
for (int j = radiusX+1; j<w; j++){
if (maxIndexA == bufferHead){
a = bufferA[bufferHead+1];
maxIndexA = bufferHead+1;
for (int m= bufferHead+2; m< w; m++){
a1 = bufferA[m];
if (isBetter(a1, a, doDilation)){
a = a1;
maxIndexA = m;
}
}
}
else {
a = bufferA[maxIndexA];
}
if (maxIndexR == bufferHead){
r = bufferR[bufferHead+1];
maxIndexR = bufferHead+1;
for (int m= bufferHead+2; m< w; m++){
r1 = bufferR[m];
if (isBetter(r1, r, doDilation)){
r = r1;
maxIndexR = m;
}
}
}
else {
r = bufferR[maxIndexR];
}
if (maxIndexG == bufferHead){
g = bufferG[bufferHead+1];
maxIndexG = bufferHead+1;
for (int m= bufferHead+2; m< w; m++){
g1 = bufferG[m];
if (isBetter(g1, g, doDilation)){
g = g1;
maxIndexG = m;
}
}
}
// we can reuse the previous max/min value
else {
g = bufferG[maxIndexG];
}
if (maxIndexB == bufferHead){
b = bufferB[bufferHead+1];
maxIndexB = bufferHead+1;
for (int m= bufferHead+2; m< w; m++){
b1 = bufferB[m];
if (isBetter(b1, b, doDilation)){
b = b1;
maxIndexB = m;
}
}
}
// we can reuse the previous max/min value
else {
b = bufferB[maxIndexB];
}
// discard the leftmost element
bufferHead++;
destPixels[dp++] = (a << 24) | r | g | b;
}
// return to the first pixel of the next row
}
}// When radiusX < w <=2*radiusX
}