1 18 package org.apache.batik.ext.awt.image.rendered; 19 20 import java.awt.Rectangle ; 21 import java.awt.RenderingHints ; 22 import java.awt.color.ColorSpace ; 23 import java.awt.geom.Point2D ; 24 import java.awt.geom.Rectangle2D ; 25 import java.awt.image.BufferedImage ; 26 import java.awt.image.BufferedImageOp ; 27 import java.awt.image.ColorModel ; 28 import java.awt.image.DataBuffer ; 29 import java.awt.image.DataBufferInt ; 30 import java.awt.image.DirectColorModel ; 31 import java.awt.image.Raster ; 32 import java.awt.image.RasterOp ; 33 import java.awt.image.SampleModel ; 34 import java.awt.image.SinglePixelPackedSampleModel ; 35 import java.awt.image.WritableRaster ; 36 37 import org.apache.batik.ext.awt.image.GraphicsUtil; 38 39 47 public class MorphologyOp implements BufferedImageOp , RasterOp { 48 51 private int radiusX; 52 55 private int radiusY; 56 60 private boolean doDilation; 61 62 65 private final int rangeX; 66 67 70 private final int rangeY; 71 72 75 private final ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB); 76 77 80 private final ColorSpace lRGB = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); 81 82 92 public MorphologyOp (int radiusX, int radiusY, boolean doDilation){ 93 if (radiusX<=0 || radiusY<=0){ 94 throw new IllegalArgumentException (new String ("The radius of X-axis or Y-axis should not be Zero or Negatives.")); 95 } 96 else { 97 this.radiusX = radiusX; 98 this.radiusY = radiusY; 99 this.doDilation = doDilation; 100 rangeX = 2*radiusX + 1; 101 rangeY = 2*radiusY + 1; 102 } 103 } 104 105 public Rectangle2D getBounds2D(Raster src){ 106 checkCompatible(src.getSampleModel()); 107 return new Rectangle (src.getMinX(), src.getMinY(), src.getWidth(), src.getHeight()); 108 } 109 110 public Rectangle2D getBounds2D(BufferedImage src){ 111 return new Rectangle (0, 0, src.getWidth(), src.getHeight()); 112 } 113 114 public Point2D getPoint2D(Point2D srcPt, Point2D destPt){ 115 if(destPt==null) 117 destPt = new Point2D.Float (); 118 destPt.setLocation(srcPt.getX(), srcPt.getY()); 119 return destPt; 120 } 121 122 private void checkCompatible(ColorModel colorModel, 123 SampleModel sampleModel){ 124 ColorSpace cs = colorModel.getColorSpace(); 125 126 if((!cs .equals (sRGB)) && (!cs .equals( lRGB))) 128 throw new IllegalArgumentException ("Expected CS_sRGB or CS_LINEAR_RGB color model"); 129 130 if(!(colorModel instanceof DirectColorModel )) 132 throw new IllegalArgumentException ("colorModel should be an instance of DirectColorModel"); 133 134 if(sampleModel.getDataType() != DataBuffer.TYPE_INT) 136 throw new IllegalArgumentException ("colorModel's transferType should be DataBuffer.TYPE_INT"); 137 138 DirectColorModel dcm = (DirectColorModel )colorModel; 140 if(dcm.getRedMask() != 0x00ff0000) 141 throw new IllegalArgumentException ("red mask in source should be 0x00ff0000"); 142 if(dcm.getGreenMask() != 0x0000ff00) 143 throw new IllegalArgumentException ("green mask in source should be 0x0000ff00"); 144 if(dcm.getBlueMask() != 0x000000ff) 145 throw new IllegalArgumentException ("blue mask in source should be 0x000000ff"); 146 if(dcm.getAlphaMask() != 0xff000000) 147 throw new IllegalArgumentException ("alpha mask in source should be 0xff000000"); 148 } 149 150 private boolean isCompatible(ColorModel colorModel, 151 SampleModel sampleModel){ 152 ColorSpace cs = colorModel.getColorSpace(); 153 if((cs != ColorSpace.getInstance(ColorSpace.CS_sRGB)) 155 && 156 (cs != ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB))) 157 return false; 158 159 if(!(colorModel instanceof DirectColorModel )) 161 return false; 162 163 if(sampleModel.getDataType() != DataBuffer.TYPE_INT) 165 return false; 166 167 DirectColorModel dcm = (DirectColorModel )colorModel; 169 if(dcm.getRedMask() != 0x00ff0000) 170 return false; 171 if(dcm.getGreenMask() != 0x0000ff00) 172 return false; 173 if(dcm.getBlueMask() != 0x000000ff) 174 return false; 175 if(dcm.getAlphaMask() != 0xff000000) 176 return false; 177 return true; 178 } 179 180 private void checkCompatible(SampleModel model){ 181 if(!(model instanceof SinglePixelPackedSampleModel )) 183 throw new IllegalArgumentException 184 ("MorphologyOp only works with Rasters " + 185 "using SinglePixelPackedSampleModels"); 186 int nBands = model.getNumBands(); 188 if(nBands!=4) 189 throw new IllegalArgumentException 190 ("MorphologyOp only words with Rasters having 4 bands"); 191 if(model.getDataType()!=DataBuffer.TYPE_INT) 193 throw new IllegalArgumentException 194 ("MorphologyOp only works with Rasters using DataBufferInt"); 195 196 int bitOffsets[]=((SinglePixelPackedSampleModel )model).getBitOffsets(); 198 for(int i=0; i<bitOffsets.length; i++){ 199 if(bitOffsets[i]%8 != 0) 200 throw new IllegalArgumentException 201 ("MorphologyOp only works with Rasters using 8 bits " + 202 "per band : " + i + " : " + bitOffsets[i]); 203 } 204 } 205 206 public RenderingHints getRenderingHints(){ 207 return null; 208 } 209 210 public WritableRaster createCompatibleDestRaster(Raster src){ 211 checkCompatible(src.getSampleModel()); 212 return src.createCompatibleWritableRaster(); 214 } 215 216 public BufferedImage createCompatibleDestImage(BufferedImage src, 217 ColorModel destCM){ 218 BufferedImage dest = null; 219 if(destCM==null) 220 destCM = src.getColorModel(); 221 222 WritableRaster wr; 223 wr = destCM.createCompatibleWritableRaster(src.getWidth(), 224 src.getHeight()); 225 checkCompatible(destCM, wr.getSampleModel()); 226 227 dest = new BufferedImage (destCM, wr, 228 destCM.isAlphaPremultiplied(), null); 229 return dest; 230 } 231 232 236 static final boolean isBetter (final int v1, final int v2, final boolean doDilation) { 237 if (v1 > v2) 238 return doDilation; 239 if (v1 < v2) 240 return !doDilation; 241 return true; 242 } 243 244 248 private void specialProcessRow(Raster src, WritableRaster dest){ 249 final int w = src.getWidth(); 250 final int h = src.getHeight(); 251 252 DataBufferInt srcDB = (DataBufferInt )src.getDataBuffer(); 254 DataBufferInt dstDB = (DataBufferInt )dest.getDataBuffer(); 255 256 SinglePixelPackedSampleModel sppsm; 258 sppsm = (SinglePixelPackedSampleModel )src.getSampleModel(); 259 260 final int srcOff = srcDB.getOffset() + 261 sppsm.getOffset(src.getMinX() - src.getSampleModelTranslateX(), 262 src.getMinY() - src.getSampleModelTranslateY()); 263 264 265 sppsm = (SinglePixelPackedSampleModel )dest.getSampleModel(); 266 final int dstOff = dstDB.getOffset() + 267 sppsm.getOffset(dest.getMinX() - dest.getSampleModelTranslateX(), 268 dest.getMinY() - dest.getSampleModelTranslateY()); 269 270 final int srcScanStride = ((SinglePixelPackedSampleModel )src.getSampleModel()).getScanlineStride(); 273 final int dstScanStride = ((SinglePixelPackedSampleModel )dest.getSampleModel()).getScanlineStride(); 274 275 final int srcPixels[] = srcDB.getBankData()[0]; 277 final int destPixels[] = dstDB.getBankData()[0]; 278 279 int sp, dp; 281 282 286 int bufferHead; 288 289 int maxIndexA; 290 int maxIndexR; 291 int maxIndexG; 292 int maxIndexB; 293 294 int pel, currentPixel, lastPixel; 296 int a,r,g,b; 297 int a1,r1,g1,b1; 298 299 if (w<=radiusX){ 302 for (int i=0; i<h; i++){ 303 sp = srcOff + i*srcScanStride; 305 dp = dstOff + i*dstScanStride; 306 pel = srcPixels[sp++]; 307 a = pel>>>24; 308 r = pel&0xff0000; 309 g = pel&0xff00; 310 b = pel&0xff; 311 312 for (int k=1; k<w; k++){ 313 currentPixel = srcPixels[sp++]; 314 a1 = currentPixel>>>24; 315 r1 = currentPixel&0xff0000; 316 g1 = currentPixel&0xff00; 317 b1 = currentPixel&0xff; 318 319 if (isBetter(a1, a, doDilation)){ 320 a = a1; 321 } 322 if (isBetter(r1, r, doDilation)){ 323 r = r1; 324 } 325 if (isBetter(g1, g, doDilation)){ 326 g = g1; 327 } 328 if (isBetter(b1, b, doDilation)){ 329 b = b1; 330 } 331 } 332 for (int k=0; k<w; k++){ 334 destPixels[dp++] = (a << 24) | r | g | b; 335 } 336 } 337 } 338 339 else { 341 342 final int [] bufferA = new int [w]; 344 final int [] bufferR = new int [w]; 345 final int [] bufferG = new int [w]; 346 final int [] bufferB = new int [w]; 347 348 for (int i=0; i<h; i++){ 349 sp = srcOff + i*srcScanStride; 352 dp = dstOff + i*dstScanStride; 353 354 bufferHead = 0; 355 maxIndexA = 0; 356 maxIndexR = 0; 357 maxIndexG = 0; 358 maxIndexB = 0; 359 360 pel = srcPixels[sp++]; 361 a = pel>>>24; 362 r = pel&0xff0000; 363 g = pel&0xff00; 364 b = pel&0xff; 365 bufferA[0] = a; 366 bufferR[0] = r; 367 bufferG[0] = g; 368 bufferB[0] = b; 369 370 for (int k=1; k<=radiusX; k++){ 371 currentPixel = srcPixels[sp++]; 372 a1 = currentPixel>>>24; 373 r1 = currentPixel&0xff0000; 374 g1 = currentPixel&0xff00; 375 b1 = currentPixel&0xff; 376 bufferA[k] = a1; 377 bufferR[k] = r1; 378 bufferG[k] = g1; 379 bufferB[k] = b1; 380 381 if (isBetter(a1, a, doDilation)){ 382 a = a1; 383 maxIndexA = k; 384 } 385 if (isBetter(r1, r, doDilation)){ 386 r = r1; 387 maxIndexR = k; 388 } 389 if (isBetter(g1, g, doDilation)){ 390 g = g1; 391 maxIndexG = k; 392 } 393 if (isBetter(b1, b, doDilation)){ 394 b = b1; 395 maxIndexB = k; 396 } 397 } 398 destPixels[dp++] = (a << 24) | r | g | b; 399 400 for (int j=1; j<=w-radiusX-1; j++){ 404 lastPixel = srcPixels[sp++]; 405 406 408 a = bufferA[maxIndexA]; 410 a1 = lastPixel>>>24; 411 bufferA[j+radiusX] = a1; 412 if (isBetter(a1, a, doDilation)){ 413 a = a1; 414 maxIndexA = j+radiusX; 415 } 416 417 419 r = bufferR[maxIndexR]; 420 r1 = lastPixel&0xff0000; 421 bufferR[j+radiusX] = r1; 422 if (isBetter(r1, r, doDilation)){ 423 r = r1; 424 maxIndexR = j+radiusX; 425 } 426 427 429 g = bufferG[maxIndexG]; 430 g1 = lastPixel&0xff00; 431 bufferG[j+radiusX] = g1; 432 if (isBetter(g1, g, doDilation)){ 433 g = g1; 434 maxIndexG = j+radiusX; 435 } 436 437 439 b = bufferB[maxIndexB]; 440 b1 = lastPixel&0xff; 441 bufferB[j+radiusX] = b1; 442 if (isBetter(b1, b, doDilation)){ 443 b = b1; 444 maxIndexB = j+radiusX; 445 } 446 451 destPixels[dp++] = (a << 24) | r | g | b; 452 } 453 for (int j = w-radiusX; j<= radiusX; j++){ 456 destPixels[dp] = destPixels[dp-1]; 457 dp++; 458 } 459 for (int j = radiusX+1; j<w; j++){ 462 463 if (maxIndexA == bufferHead){ 464 a = bufferA[bufferHead+1]; 465 maxIndexA = bufferHead+1; 466 for (int m= bufferHead+2; m< w; m++){ 467 a1 = bufferA[m]; 468 if (isBetter(a1, a, doDilation)){ 469 a = a1; 470 maxIndexA = m; 471 } 472 } 473 } 474 else { 475 a = bufferA[maxIndexA]; 476 } 477 if (maxIndexR == bufferHead){ 478 r = bufferR[bufferHead+1]; 479 maxIndexR = bufferHead+1; 480 for (int m= bufferHead+2; m< w; m++){ 481 r1 = bufferR[m]; 482 if (isBetter(r1, r, doDilation)){ 483 r = r1; 484 maxIndexR = m; 485 } 486 } 487 } 488 else { 489 r = bufferR[maxIndexR]; 490 } 491 492 if (maxIndexG == bufferHead){ 493 g = bufferG[bufferHead+1]; 494 maxIndexG = bufferHead+1; 495 for (int m= bufferHead+2; m< w; m++){ 496 g1 = bufferG[m]; 497 if (isBetter(g1, g, doDilation)){ 498 g = g1; 499 maxIndexG = m; 500 } 501 } 502 } 503 else { 505 g = bufferG[maxIndexG]; 506 } 507 508 if (maxIndexB == bufferHead){ 509 b = bufferB[bufferHead+1]; 510 maxIndexB = bufferHead+1; 511 for (int m= bufferHead+2; m< w; m++){ 512 b1 = bufferB[m]; 513 if (isBetter(b1, b, doDilation)){ 514 b = b1; 515 maxIndexB = m; 516 } 517 } 518 } 519 else { 521 b = bufferB[maxIndexB]; 522 } 523 524 bufferHead++; 526 527 destPixels[dp++] = (a << 24) | r | g | b; 528 } 529 } 531 } } 533 534 538 private void specialProcessColumn(Raster src, WritableRaster dest){ 539 540 final int w = src.getWidth(); 541 final int h = src.getHeight(); 542 543 DataBufferInt dstDB = (DataBufferInt )dest.getDataBuffer(); 545 546 final int dstOff = dstDB.getOffset(); 548 549 final int dstScanStride = ((SinglePixelPackedSampleModel )dest.getSampleModel()).getScanlineStride(); 552 553 final int destPixels[] = dstDB.getBankData()[0]; 555 556 int dp, cp; 558 559 563 int bufferHead; 565 566 int maxIndexA; 567 int maxIndexR; 568 int maxIndexG; 569 int maxIndexB; 570 571 int pel, currentPixel, lastPixel; 573 int a,r,g,b; 574 int a1,r1,g1,b1; 575 576 if (h<=radiusY){ 579 for (int j=0; j<w; j++){ 580 dp = dstOff + j; 581 cp = dstOff + j; 582 pel = destPixels[cp]; 583 cp += dstScanStride; 584 a = pel>>>24; 585 r = pel&0xff0000; 586 g = pel&0xff00; 587 b = pel&0xff; 588 589 for (int k=1; k<h; k++){ 590 currentPixel = destPixels[cp]; 591 cp += dstScanStride; 592 a1 = currentPixel>>>24; 593 r1 = currentPixel&0xff0000; 594 g1 = currentPixel&0xff00; 595 b1 = currentPixel&0xff; 596 597 if (isBetter(a1, a, doDilation)){ 598 a = a1; 599 } 600 if (isBetter(r1, r, doDilation)){ 601 r = r1; 602 } 603 if (isBetter(g1, g, doDilation)){ 604 g = g1; 605 } 606 if (isBetter(b1, b, doDilation)){ 607 b = b1; 608 } 609 } 610 for (int k=0; k<h; k++){ 611 destPixels[dp] = (a << 24) | r | g | b; 612 dp += dstScanStride; 613 } 614 } 616 } 617 618 else { 620 621 final int [] bufferA = new int [h]; 623 final int [] bufferR = new int [h]; 624 final int [] bufferG = new int [h]; 625 final int [] bufferB = new int [h]; 626 627 for (int j=0; j<w; j++){ 628 dp = dstOff + j; 631 cp = dstOff + j; 632 633 bufferHead = 0; 634 maxIndexA = 0; 635 maxIndexR = 0; 636 maxIndexG = 0; 637 maxIndexB = 0; 638 639 pel = destPixels[cp]; 640 cp += dstScanStride; 641 a = pel>>>24; 642 r = pel&0xff0000; 643 g = pel&0xff00; 644 b = pel&0xff; 645 bufferA[0] = a; 646 bufferR[0] = r; 647 bufferG[0] = g; 648 bufferB[0] = b; 649 650 for (int k=1; k<=radiusY; k++){ 651 currentPixel = destPixels[cp]; 652 cp += dstScanStride; 653 a1 = currentPixel>>>24; 654 r1 = currentPixel&0xff0000; 655 g1 = currentPixel&0xff00; 656 b1 = currentPixel&0xff; 657 bufferA[k] = a1; 658 bufferR[k] = r1; 659 bufferG[k] = g1; 660 bufferB[k] = b1; 661 662 if (isBetter(a1, a, doDilation)){ 663 a = a1; 664 maxIndexA = k; 665 } 666 if (isBetter(r1, r, doDilation)){ 667 r = r1; 668 maxIndexR = k; 669 } 670 if (isBetter(g1, g, doDilation)){ 671 g = g1; 672 maxIndexG = k; 673 } 674 if (isBetter(b1, b, doDilation)){ 675 b = b1; 676 maxIndexB = k; 677 } 678 } 679 destPixels[dp] = (a << 24) | r | g | b; 681 dp += dstScanStride; 682 683 for (int i=1; i<=h-radiusY-1; i++){ 687 lastPixel = destPixels[cp]; 688 cp += dstScanStride; 689 690 692 a = bufferA[maxIndexA]; 693 a1 = lastPixel>>>24; 694 bufferA[i+radiusY] = a1; 695 if (isBetter(a1, a, doDilation)){ 696 a = a1; 697 maxIndexA = i+radiusY; 698 } 699 700 702 r = bufferR[maxIndexR]; 703 r1 = lastPixel&0xff0000; 704 bufferR[i+radiusY] = r1; 705 if (isBetter(r1, r, doDilation)){ 706 r = r1; 707 maxIndexR = i+radiusY; 708 } 709 710 712 g = bufferG[maxIndexG]; 713 g1 = lastPixel&0xff00; 714 bufferG[i+radiusY] = g1; 715 if (isBetter(g1, g, doDilation)){ 716 g = g1; 717 maxIndexG = i+radiusY; 718 } 719 720 722 b = bufferB[maxIndexB]; 723 b1 = lastPixel&0xff; 724 bufferB[i+radiusY] = b1; 725 if (isBetter(b1, b, doDilation)){ 726 b = b1; 727 maxIndexB = i+radiusY; 728 } 729 734 destPixels[dp] = (a << 24) | r | g | b; 735 dp += dstScanStride; 736 } 737 for (int i = h-radiusY; i<= radiusY; i++){ 740 destPixels[dp] = destPixels[dp-dstScanStride]; 741 dp += dstScanStride; 742 } 743 745 for (int i = radiusY+1; i<h; i++){ 746 747 if (maxIndexA == bufferHead){ 748 a = bufferA[bufferHead+1]; 749 maxIndexA = bufferHead+1; 750 for (int m= bufferHead+2; m< h; m++){ 751 a1 = bufferA[m]; 752 if (isBetter(a1, a, doDilation)){ 753 a = a1; 754 maxIndexA = m; 755 } 756 } 757 } 758 else { 759 a = bufferA[maxIndexA]; 760 } 761 if (maxIndexR == bufferHead){ 762 r = bufferR[bufferHead+1]; 763 maxIndexR = bufferHead+1; 764 for (int m= bufferHead+2; m< h; m++){ 765 r1 = bufferR[m]; 766 if (isBetter(r1, r, doDilation)){ 767 r = r1; 768 maxIndexR = m; 769 } 770 } 771 } 772 else { 773 r = bufferR[maxIndexR]; 774 } 775 776 if (maxIndexG == bufferHead){ 777 g = bufferG[bufferHead+1]; 778 maxIndexG = bufferHead+1; 779 for (int m= bufferHead+2; m< h; m++){ 780 g1 = bufferG[m]; 781 if (isBetter(g1, g, doDilation)){ 782 g = g1; 783 maxIndexG = m; 784 } 785 } 786 } 787 else { 789 g = bufferG[maxIndexG]; 790 } 791 792 if (maxIndexB == bufferHead){ 793 b = bufferB[bufferHead+1]; 794 maxIndexB = bufferHead+1; 795 for (int m= bufferHead+2; m< h; m++){ 796 b1 = bufferB[m]; 797 if (isBetter(b1, b, doDilation)){ 798 b = b1; 799 maxIndexB = m; 800 } 801 } 802 } 803 else { 805 b = bufferB[maxIndexB]; 806 } 807 808 bufferHead++; 810 811 destPixels[dp] = (a << 24) | r | g | b; 812 dp += dstScanStride; 813 } 814 } 816 } } 818 819 832 public WritableRaster filter(Raster src, WritableRaster dest){ 833 834 840 if(dest!=null) checkCompatible(dest.getSampleModel()); 842 else { 843 if(src==null) 844 throw new IllegalArgumentException ("src should not be null when dest is null"); 845 else dest = createCompatibleDestRaster(src); 846 } 847 848 final int w = src.getWidth(); 849 final int h = src.getHeight(); 850 851 DataBufferInt srcDB = (DataBufferInt )src.getDataBuffer(); 853 DataBufferInt dstDB = (DataBufferInt )dest.getDataBuffer(); 854 855 final int srcOff = srcDB.getOffset(); 857 final int dstOff = dstDB.getOffset(); 858 859 final int srcScanStride = ((SinglePixelPackedSampleModel )src.getSampleModel()).getScanlineStride(); 862 final int dstScanStride = ((SinglePixelPackedSampleModel )dest.getSampleModel()).getScanlineStride(); 863 864 final int srcPixels[] = srcDB.getBankData()[0]; 866 final int destPixels[] = dstDB.getBankData()[0]; 867 868 int sp, dp, cp; 870 871 875 int bufferHead; 877 878 int maxIndexA; 879 int maxIndexR; 880 int maxIndexG; 881 int maxIndexB; 882 883 int pel, currentPixel, lastPixel; 885 int a,r,g,b; 886 int a1,r1,g1,b1; 887 888 903 if (w<=2*radiusX){ 907 specialProcessRow(src, dest); 908 } 909 910 else { 913 914 final int [] bufferA = new int [rangeX]; 915 final int [] bufferR = new int [rangeX]; 916 final int [] bufferG = new int [rangeX]; 917 final int [] bufferB = new int [rangeX]; 918 919 for (int i=0; i<h; i++){ 920 sp = srcOff + i*srcScanStride; 923 dp = dstOff + i*dstScanStride; 924 bufferHead = 0; 925 maxIndexA = 0; 926 maxIndexR = 0; 927 maxIndexG = 0; 928 maxIndexB = 0; 929 930 pel = srcPixels[sp++]; 935 a = pel>>>24; 936 r = pel&0xff0000; 937 g = pel&0xff00; 938 b = pel&0xff; 939 bufferA[0] = a; 940 bufferR[0] = r; 941 bufferG[0] = g; 942 bufferB[0] = b; 943 944 for (int k=1; k<=radiusX; k++){ 945 currentPixel = srcPixels[sp++]; 946 a1 = currentPixel>>>24; 947 r1 = currentPixel&0xff0000; 948 g1 = currentPixel&0xff00; 949 b1 = currentPixel&0xff; 950 bufferA[k] = a1; 951 bufferR[k] = r1; 952 bufferG[k] = g1; 953 bufferB[k] = b1; 954 955 if (isBetter(a1, a, doDilation)){ 956 a = a1; 957 maxIndexA = k; 958 } 959 if (isBetter(r1, r, doDilation)){ 960 r = r1; 961 maxIndexR = k; 962 } 963 if (isBetter(g1, g, doDilation)){ 964 g = g1; 965 maxIndexG = k; 966 } 967 if (isBetter(b1, b, doDilation)){ 968 b = b1; 969 maxIndexB = k; 970 } 971 } 972 destPixels[dp++] = (a << 24) | r | g | b; 973 974 for (int j=1; j<=radiusX; j++){ 978 lastPixel = srcPixels[sp++]; 979 980 982 a = bufferA[maxIndexA]; 984 a1 = lastPixel>>>24; 985 bufferA[j+radiusX] = a1; 986 if (isBetter(a1, a, doDilation)){ 987 a = a1; 988 maxIndexA = j+radiusX; 989 } 990 991 993 r = bufferR[maxIndexR]; 994 r1 = lastPixel&0xff0000; 995 bufferR[j+radiusX] = r1; 996 if (isBetter(r1, r, doDilation)){ 997 r = r1; 998 maxIndexR = j+radiusX; 999 } 1000 1001 1003 g = bufferG[maxIndexG]; 1004 g1 = lastPixel&0xff00; 1005 bufferG[j+radiusX] = g1; 1006 if (isBetter(g1, g, doDilation)){ 1007 g = g1; 1008 maxIndexG = j+radiusX; 1009 } 1010 1011 1013 b = bufferB[maxIndexB]; 1014 b1 = lastPixel&0xff; 1015 bufferB[j+radiusX] = b1; 1016 if (isBetter(b1, b, doDilation)){ 1017 b = b1; 1018 maxIndexB = j+radiusX; 1019 } 1020 1025 destPixels[dp++] = (a << 24) | r | g | b; 1026 } 1027 1028 for (int j=radiusX+1; j<=w-1-radiusX; j++){ 1033 lastPixel = srcPixels[sp++]; 1034 a1 = lastPixel>>>24; 1035 r1 = lastPixel&0xff0000; 1036 g1 = lastPixel&0xff00; 1037 b1 = lastPixel&0xff; 1038 bufferA[bufferHead] = a1; 1039 bufferR[bufferHead] = r1; 1040 bufferG[bufferHead] = g1; 1041 bufferB[bufferHead] = b1; 1042 1043 if (maxIndexA == bufferHead){ 1047 a = bufferA[0]; 1048 maxIndexA = 0; 1049 for (int m= 1; m< rangeX; m++){ 1050 a1 = bufferA[m]; 1051 if (isBetter(a1, a, doDilation)){ 1052 a = a1; 1053 maxIndexA = m; 1054 } 1055 } 1056 } 1057 else { 1059 a = bufferA[maxIndexA]; 1060 if (isBetter(a1, a, doDilation)){ 1061 a = a1; 1062 maxIndexA = bufferHead; 1063 } 1064 } 1065 1066 1070 if (maxIndexR == bufferHead){ 1071 r = bufferR[0]; 1072 maxIndexR = 0; 1073 for (int m= 1; m< rangeX; m++){ 1074 r1 = bufferR[m]; 1075 if (isBetter(r1, r, doDilation)){ 1076 r = r1; 1077 maxIndexR = m; 1078 } 1079 } 1080 } 1081 else { 1083 r = bufferR[maxIndexR]; 1084 if (isBetter(r1, r, doDilation)){ 1085 r = r1; 1086 maxIndexR = bufferHead; 1087 } 1088 } 1089 1090 1094 if (maxIndexG == bufferHead){ 1095 g = bufferG[0]; 1096 maxIndexG = 0; 1097 for (int m= 1; m< rangeX; m++){ 1098 g1 = bufferG[m]; 1099 if (isBetter(g1, g, doDilation)){ 1100 g = g1; 1101 maxIndexG = m; 1102 } 1103 } 1104 } 1105 else { 1107 g = bufferG[maxIndexG]; 1108 if (isBetter(g1, g, doDilation)){ 1109 g = g1; 1110 maxIndexG = bufferHead; 1111 } 1112 } 1113 1114 1118 if (maxIndexB == bufferHead){ 1119 b = bufferB[0]; 1120 maxIndexB = 0; 1121 for (int m= 1; m< rangeX; m++){ 1122 b1 = bufferB[m]; 1123 if (isBetter(b1, b, doDilation)){ 1124 b = b1; 1125 maxIndexB = m; 1126 } 1127 } 1128 } 1129 else { 1131 b = bufferB[maxIndexB]; 1132 if (isBetter(b1, b, doDilation)){ 1133 b = b1; 1134 maxIndexB = bufferHead; 1135 } 1136 } 1137 destPixels[dp++] = (a << 24) | r | g | b; 1138 bufferHead = (bufferHead+1)%rangeX; 1139 } 1140 1141 1145 int head; 1148 final int tail = (bufferHead == 0)?rangeX-1:bufferHead -1; 1150 int count = rangeX-1; 1151 1152 for (int j=w-radiusX; j<w; j++){ 1153 head = (bufferHead+1)%rangeX; 1154 if (maxIndexA == bufferHead){ 1156 a = bufferA[tail]; 1157 int hd = head; 1158 for(int m=1; m<count; m++) { 1159 a1 = bufferA[hd]; 1160 if (isBetter(a1, a, doDilation)){ 1161 a = a1; 1162 maxIndexA = hd; 1163 } 1164 hd = (hd+1)%rangeX; 1165 } 1166 } 1167 if (maxIndexR == bufferHead){ 1169 r = bufferR[tail]; 1170 int hd = head; 1171 for(int m=1; m<count; m++) { 1172 r1 = bufferR[hd]; 1173 if (isBetter(r1, r, doDilation)){ 1174 r = r1; 1175 maxIndexR = hd; 1176 } 1177 hd = (hd+1)%rangeX; 1178 } 1179 } 1180 if (maxIndexG == bufferHead){ 1182 g = bufferG[tail]; 1183 int hd = head; 1184 for(int m=1; m<count; m++) { 1185 g1 = bufferG[hd]; 1186 if (isBetter(g1, g, doDilation)){ 1187 g = g1; 1188 maxIndexG = hd; 1189 } 1190 hd = (hd+1)%rangeX; 1191 } 1192 } 1193 if (maxIndexB == bufferHead){ 1195 b = bufferB[tail]; 1196 int hd = head; 1197 for(int m=1; m<count; m++) { 1198 b1 = bufferB[hd]; 1199 if (isBetter(b1, b, doDilation)){ 1200 b = b1; 1201 maxIndexB = hd; 1202 } 1203 hd = (hd+1)%rangeX; 1204 } 1205 } 1206 destPixels[dp++] = (a << 24) | r | g | b; 1207 bufferHead = (bufferHead+1)%rangeX; 1208 count--; 1210 } 1212 } 1214 } 1216 1222 if (h<=2*radiusY){ 1225 specialProcessColumn(src, dest); 1226 } 1227 1228 else { 1231 final int [] bufferA = new int [rangeY]; 1232 final int [] bufferR = new int [rangeY]; 1233 final int [] bufferG = new int [rangeY]; 1234 final int [] bufferB = new int [rangeY]; 1235 1236 for (int j=0; j<w; j++){ 1237 dp = dstOff + j; 1240 cp = dstOff + j; 1241 bufferHead = 0; 1242 maxIndexA = 0; 1243 maxIndexR = 0; 1244 maxIndexG = 0; 1245 maxIndexB = 0; 1246 1247 pel = destPixels[cp]; 1249 cp += dstScanStride; 1250 a = pel>>>24; 1251 r = pel&0xff0000; 1252 g = pel&0xff00; 1253 b = pel&0xff; 1254 bufferA[0] = a; 1255 bufferR[0] = r; 1256 bufferG[0] = g; 1257 bufferB[0] = b; 1258 1259 for (int k=1; k<=radiusY; k++){ 1260 currentPixel = destPixels[cp]; 1261 cp += dstScanStride; 1262 a1 = currentPixel>>>24; 1263 r1 = currentPixel&0xff0000; 1264 g1 = currentPixel&0xff00; 1265 b1 = currentPixel&0xff; 1266 bufferA[k] = a1; 1267 bufferR[k] = r1; 1268 bufferG[k] = g1; 1269 bufferB[k] = b1; 1270 1271 if (isBetter(a1, a, doDilation)){ 1272 a = a1; 1273 maxIndexA = k; 1274 } 1275 if (isBetter(r1, r, doDilation)){ 1276 r = r1; 1277 maxIndexR = k; 1278 } 1279 if (isBetter(g1, g, doDilation)){ 1280 g = g1; 1281 maxIndexG = k; 1282 } 1283 if (isBetter(b1, b, doDilation)){ 1284 b = b1; 1285 maxIndexB = k; 1286 } 1287 } 1288 destPixels[dp] = (a << 24) | r | g | b; 1289 dp += dstScanStride; 1291 1292 for (int i=1; i<=radiusY; i++){ 1294 int maxI = i+radiusY; 1295 lastPixel = destPixels[cp]; 1297 cp += dstScanStride; 1298 1299 a = bufferA[maxIndexA]; 1301 a1 = lastPixel>>>24; 1302 bufferA[maxI] = a1; 1303 if (isBetter(a1, a, doDilation)){ 1304 a = a1; 1305 maxIndexA = maxI; 1306 } 1307 1308 r = bufferR[maxIndexR]; 1310 r1 = lastPixel&0xff0000; 1311 bufferR[maxI] = r1; 1312 if (isBetter(r1, r, doDilation)){ 1313 r = r1; 1314 maxIndexR = maxI; 1315 } 1316 1317 g = bufferG[maxIndexG]; 1319 g1 = lastPixel&0xff00; 1320 bufferG[maxI] = g1; 1321 if (isBetter(g1, g, doDilation)){ 1322 g = g1; 1323 maxIndexG = maxI; 1324 } 1325 1326 b = bufferB[maxIndexB]; 1328 b1 = lastPixel&0xff; 1329 bufferB[maxI] = b1; 1330 if (isBetter(b1, b, doDilation)){ 1331 b = b1; 1332 maxIndexB = maxI; 1333 } 1334 destPixels[dp] = (a << 24) | r | g | b; 1335 dp += dstScanStride; 1336 } 1337 1338 1343 for (int i=radiusY+1; i<=h-1-radiusY; i++){ 1344 1345 lastPixel = destPixels[cp]; 1346 cp += dstScanStride; 1347 a1 = lastPixel>>>24; 1348 r1 = lastPixel&0xff0000; 1349 g1 = lastPixel&0xff00; 1350 b1 = lastPixel&0xff; 1351 bufferA[bufferHead] = a1; 1352 bufferR[bufferHead] = r1; 1353 bufferG[bufferHead] = g1; 1354 bufferB[bufferHead] = b1; 1355 1356 1360 1362 if (maxIndexA == bufferHead){ 1364 a = bufferA[0]; 1365 maxIndexA = 0; 1366 for (int m= 1; m<= 2*radiusY; m++){ 1367 a1 = bufferA[m]; 1368 if (isBetter(a1, a, doDilation)){ 1369 a = a1; 1370 maxIndexA = m; 1371 } 1372 } 1373 } 1374 else { 1376 a = bufferA[maxIndexA]; 1377 if (isBetter(a1, a, doDilation)){ 1378 a = a1; 1379 maxIndexA = bufferHead; 1380 } 1381 } 1382 1383 1385 if (maxIndexR == bufferHead){ 1386 r = bufferR[0]; 1387 maxIndexR = 0; 1388 for (int m= 1; m<= 2*radiusY; m++){ 1389 r1 = bufferR[m]; 1390 if (isBetter(r1, r, doDilation)){ 1391 r = r1; 1392 maxIndexR = m; 1393 } 1394 } 1395 } 1396 else { 1398 r = bufferR[maxIndexR]; 1399 if (isBetter(r1, r, doDilation)){ 1400 r = r1; 1401 maxIndexR = bufferHead; 1402 } 1403 } 1404 1405 if (maxIndexG == bufferHead){ 1407 g = bufferG[0]; 1408 maxIndexG = 0; 1409 for (int m= 1; m<= 2*radiusY; m++){ 1410 g1 = bufferG[m]; 1411 if (isBetter(g1, g, doDilation)){ 1412 g = g1; 1413 maxIndexG = m; 1414 } 1415 } 1416 } 1417 else { 1419 g = bufferG[maxIndexG]; 1420 if (isBetter(g1, g, doDilation)){ 1421 g = g1; 1422 maxIndexG = bufferHead; 1423 } 1424 } 1425 1426 if (maxIndexB == bufferHead){ 1428 b = bufferB[0]; 1429 maxIndexB = 0; 1430 for (int m= 1; m<= 2*radiusY; m++){ 1431 b1 = bufferB[m]; 1432 if (isBetter(b1, b, doDilation)){ 1433 b = b1; 1434 maxIndexB = m; 1435 } 1436 } 1437 } 1438 else { 1440 b = bufferB[maxIndexB]; 1441 if (isBetter(b1, b, doDilation)){ 1442 b = b1; 1443 maxIndexB = bufferHead; 1444 } 1445 } 1446 destPixels[dp] = (a << 24) | r | g | b; 1447 dp += dstScanStride; 1448 bufferHead = (bufferHead+1)%rangeY; 1449 } 1450 1451 1455 int head; 1458 final int tail = (bufferHead == 0)?2*radiusY:bufferHead -1; 1460 int count = rangeY-1; 1461 1462 for (int i= h-radiusY; i<h-1; i++){ 1463 head = (bufferHead +1)%rangeY; 1464 1465 if (maxIndexA == bufferHead){ 1466 a = bufferA[tail]; 1467 int hd = head; 1468 for (int m=1; m<count; m++){ 1469 a1 = bufferA[hd]; 1470 if (isBetter(a1, a, doDilation)){ 1471 a = a1; 1472 maxIndexA = hd; 1473 } 1474 hd = (hd+1)%rangeY; 1475 } 1476 } 1477 if (maxIndexR == bufferHead){ 1478 r = bufferR[tail]; 1479 int hd = head; 1480 for (int m=1; m<count; m++){ 1481 r1 = bufferR[hd]; 1482 if (isBetter(r1, r, doDilation)){ 1483 r = r1; 1484 maxIndexR = hd; 1485 } 1486 hd = (hd+1)%rangeY; 1487 } 1488 } 1489 if (maxIndexG == bufferHead){ 1490 g = bufferG[tail]; 1491 int hd = head; 1492 for (int m=1; m<count; m++){ 1493 g1 = bufferG[hd]; 1494 if (isBetter(g1, g, doDilation)){ 1495 g = g1; 1496 maxIndexG = hd; 1497 } 1498 hd = (hd+1)%rangeY; 1499 } 1500 } 1501 if (maxIndexB == bufferHead){ 1502 b = bufferB[tail]; 1503 int hd = head; 1504 for (int m=1; m<count; m++){ 1505 b1 = bufferB[hd]; 1506 if (isBetter(b1, b, doDilation)){ 1507 b = b1; 1508 maxIndexB = hd; 1509 } 1510 hd = (hd+1)%rangeY; 1511 } 1512 } 1513 destPixels[dp] = (a << 24) | r | g | b; 1514 dp += dstScanStride; 1515 bufferHead = (bufferHead+1)%rangeY; 1516 count--; 1518 } 1519 } 1521 } 1523 return dest; 1524 } 1526 1534 public BufferedImage filter(BufferedImage src, BufferedImage dest){ 1535 if (src == null) 1536 throw new NullPointerException ("Source image should not be null"); 1537 1538 BufferedImage origSrc = src; 1539 BufferedImage finalDest = dest; 1540 1541 if (!isCompatible(src.getColorModel(), src.getSampleModel())) { 1542 src = new BufferedImage (src.getWidth(), src.getHeight(), 1543 BufferedImage.TYPE_INT_ARGB_PRE); 1544 GraphicsUtil.copyData(origSrc, src); 1545 } 1546 else if (!src.isAlphaPremultiplied()) { 1547 ColorModel srcCM, srcCMPre; 1549 srcCM = src.getColorModel(); 1550 srcCMPre = GraphicsUtil.coerceColorModel(srcCM, true); 1551 1552 src = new BufferedImage (srcCMPre, src.getRaster(), 1553 true, null); 1554 1555 GraphicsUtil.copyData(origSrc, src); 1556 } 1557 1558 1559 if (dest == null) { 1560 dest = createCompatibleDestImage(src, null); 1561 finalDest = dest; 1562 } else if (!isCompatible(dest.getColorModel(), 1563 dest.getSampleModel())) { 1564 dest = createCompatibleDestImage(src, null); 1565 } else if (!dest.isAlphaPremultiplied()) { 1566 ColorModel dstCM, dstCMPre; 1568 dstCM = dest.getColorModel(); 1569 dstCMPre = GraphicsUtil.coerceColorModel(dstCM, true); 1570 1571 dest = new BufferedImage (dstCMPre, finalDest.getRaster(), 1572 true, null); 1573 } 1574 1575 filter(src.getRaster(), dest.getRaster()); 1576 1577 if ((src.getRaster() == origSrc.getRaster()) && 1579 (src.isAlphaPremultiplied() != origSrc.isAlphaPremultiplied())) { 1580 GraphicsUtil.copyData(src, origSrc); 1582 } 1583 1584 if ((dest.getRaster() != finalDest.getRaster()) || 1586 (dest.isAlphaPremultiplied() != finalDest.isAlphaPremultiplied())){ 1587 GraphicsUtil.copyData(dest, finalDest); 1589 } 1590 1591 return finalDest; 1592 } 1593 1598 1660} 1661 1662 1663 1664 1665 | Popular Tags |