in batik-awt-util/src/main/java/org/apache/batik/ext/awt/image/rendered/MorphologyOp.java [539:818]
private void specialProcessColumn(Raster src, WritableRaster dest){
final int w = src.getWidth();
final int h = src.getHeight();
// Access the integer buffer for each image.
DataBufferInt dstDB = (DataBufferInt)dest.getDataBuffer();
// Offset defines where in the stack the real data begin
final int dstOff = dstDB.getOffset();
// Stride is the distance between two consecutive column elements,
// in the one-dimention dataBuffer
final int dstScanStride = ((SinglePixelPackedSampleModel)dest.getSampleModel()).getScanlineStride();
// Access the pixel value array
final int[] destPixels = dstDB.getBankData()[0];
// The pointer of src and dest indicating where the pixel values are
int dp, cp;
// 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;
// Here all the pixels share the same
// max/min value
if (h<=radiusY){
for (int j=0; j<w; j++){
dp = dstOff + j;
cp = dstOff + j;
pel = destPixels[cp];
cp += dstScanStride;
a = pel>>>24;
r = pel&0xff0000;
g = pel&0xff00;
b = pel&0xff;
for (int k=1; k<h; k++){
currentPixel = destPixels[cp];
cp += dstScanStride;
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;
}
}
for (int k=0; k<h; k++){
destPixels[dp] = (a << 24) | r | g | b;
dp += dstScanStride;
}
// return to the first pixel of the next column
}
}
// When radiusY < h <= 2*radiusY
else {
// The height of the circular buffer is h
final int [] bufferA = new int [h];
final int [] bufferR = new int [h];
final int [] bufferG = new int [h];
final int [] bufferB = new int [h];
for (int j=0; j<w; j++){
// initialization of pointers, indice
// at the head of each column
dp = dstOff + j;
cp = dstOff + j;
bufferHead = 0;
maxIndexA = 0;
maxIndexR = 0;
maxIndexG = 0;
maxIndexB = 0;
pel = destPixels[cp];
cp += dstScanStride;
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<=radiusY; k++){
currentPixel = destPixels[cp];
cp += dstScanStride;
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;
}
}
// fill the first pixel of each column
destPixels[dp] = (a << 24) | r | g | b;
dp += dstScanStride;
//
// 1 <= i <= h-1-radiusY : The upper margin of each column.
//
for (int i=1; i<=h-radiusY-1; i++){
lastPixel = destPixels[cp];
cp += dstScanStride;
// here is the Alpha channel
a = bufferA[maxIndexA];
a1 = lastPixel>>>24;
bufferA[i+radiusY] = a1;
if (isBetter(a1, a, doDilation)){
a = a1;
maxIndexA = i+radiusY;
}
// now we deal with the Red channel
r = bufferR[maxIndexR];
r1 = lastPixel&0xff0000;
bufferR[i+radiusY] = r1;
if (isBetter(r1, r, doDilation)){
r = r1;
maxIndexR = i+radiusY;
}
// now we deal with the Green channel
g = bufferG[maxIndexG];
g1 = lastPixel&0xff00;
bufferG[i+radiusY] = g1;
if (isBetter(g1, g, doDilation)){
g = g1;
maxIndexG = i+radiusY;
}
// now we deal with the Blue channel
b = bufferB[maxIndexB];
b1 = lastPixel&0xff;
bufferB[i+radiusY] = b1;
if (isBetter(b1, b, doDilation)){
b = b1;
maxIndexB = i+radiusY;
}
// 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;
dp += dstScanStride;
}
// Now is the inner body of the column
// when radiusY < h <= 2*radiusY
for (int i = h-radiusY; i<= radiusY; i++){
destPixels[dp] = destPixels[dp-dstScanStride];
dp += dstScanStride;
}
// The circular buffer is full now
for (int i = radiusY+1; i<h; i++){
if (maxIndexA == bufferHead){
a = bufferA[bufferHead+1];
maxIndexA = bufferHead+1;
for (int m= bufferHead+2; m< h; 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< h; 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< h; 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< h; 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;
dp += dstScanStride;
}
// return to the first pixel of the next column
}
} // when radiusY < h <= 2*radiusY
}