- Timestamp:
- 2016-04-12T23:08:55+02:00 (9 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
r10011 r10142 532 532 protected static final int SLIDER_STEPS = 100; 533 533 private static final double MAX_GAMMA_FACTOR = 2; 534 private static final double MAX_SHARPNESS_FACTOR = 2; 535 private static final double MAX_COLORFUL_FACTOR = 2; 534 536 private final LayerListModel model; 535 537 private final JPopupMenu popup; 536 private JSlider opacitySlider;537 private JSlider gammaSlider;538 538 private SideButton sideButton; 539 539 private JCheckBox visibilityCheckbox; 540 final OpacitySlider opacitySlider = new OpacitySlider(); 541 private final ArrayList<FilterSlider<?>> sliders = new ArrayList<>(); 540 542 541 543 /** … … 560 562 @Override 561 563 public void stateChanged(ChangeEvent e) { 562 setVisible (visibilityCheckbox.isSelected());564 setVisibleFlag(visibilityCheckbox.isSelected()); 563 565 } 564 566 }); 565 567 content.add(visibilityCheckbox, GBC.eop()); 566 568 567 content.add(new JLabel(ImageProvider.get("dialogs/layerlist", "transparency")), GBC.std().span(1, 2).insets(0, 0, 5, 0)); 568 content.add(new JLabel(tr("Opacity")), GBC.eol()); 569 opacitySlider = new JSlider(JSlider.HORIZONTAL); 570 opacitySlider.setMaximum(SLIDER_STEPS); 571 opacitySlider.addChangeListener(new ChangeListener() { 572 @Override 573 public void stateChanged(ChangeEvent e) { 574 setOpacityValue(readOpacityValue(), opacitySlider.getValueIsAdjusting()); 575 } 576 }); 577 opacitySlider.setToolTipText(tr("Adjust opacity of the layer.")); 578 content.add(opacitySlider, GBC.eop()); 579 580 content.add(new JLabel(ImageProvider.get("dialogs/layerlist", "gamma")), GBC.std().span(1, 2).insets(0, 0, 5, 0)); 581 content.add(new JLabel(tr("Gamma")), GBC.eol()); 582 gammaSlider = new JSlider(JSlider.HORIZONTAL); 583 gammaSlider.setMaximum(SLIDER_STEPS); 584 gammaSlider.addChangeListener(new ChangeListener() { 585 @Override 586 public void stateChanged(ChangeEvent e) { 587 setGammaValue(readGammaValue()); 588 } 589 }); 590 gammaSlider.setToolTipText(tr("Adjust gamma value of the layer.")); 591 content.add(gammaSlider, GBC.eol()); 592 } 593 594 protected double readOpacityValue() { 595 return (double) opacitySlider.getValue() / SLIDER_STEPS; 596 } 597 598 protected double readGammaValue() { 599 return (double) gammaSlider.getValue() / SLIDER_STEPS * MAX_GAMMA_FACTOR; 600 } 601 602 protected void setVisible(boolean visible) { 569 addSlider(content, opacitySlider); 570 addSlider(content, new ColorfulnessSlider()); 571 addSlider(content, new GammaFilterSlider()); 572 addSlider(content, new SharpnessSlider()); 573 } 574 575 private void addSlider(JPanel content, FilterSlider<?> slider) { 576 content.add(new JLabel(slider.getIcon()), GBC.std().span(1, 2).insets(0, 0, 5, 0)); 577 content.add(new JLabel(slider.getLabel()), GBC.eol()); 578 content.add(slider, GBC.eop()); 579 sliders.add(slider); 580 } 581 582 protected void setVisibleFlag(boolean visible) { 603 583 for (Layer l : model.getSelectedLayers()) { 604 584 l.setVisible(visible); 605 585 } 606 586 updateValues(); 607 }608 609 protected void setOpacityValue(double value, boolean adjusting) {610 if (value <= 0 && !adjusting) {611 setVisible(false);612 } else {613 for (Layer l : model.getSelectedLayers()) {614 l.setOpacity(value);615 }616 }617 }618 619 protected void setGammaValue(double value) {620 for (ImageryLayer imageryLayer : Utils.filteredCollection(model.getSelectedLayers(), ImageryLayer.class)) {621 imageryLayer.setGamma(value);622 }623 587 } 624 588 … … 648 612 visibilityCheckbox.setSelected(allVisible && !allHidden); 649 613 650 updateOpacitySlider(layers, allHidden); 651 652 updateGammaSlider(layers, allHidden); 653 } 654 655 private void updateGammaSlider(List<Layer> layers, boolean allHidden) { 656 Collection<ImageryLayer> gammaLayers = Utils.filteredCollection(layers, ImageryLayer.class); 657 if (gammaLayers.isEmpty() || allHidden) { 658 gammaSlider.setEnabled(false); 659 } else { 660 gammaSlider.setEnabled(true); 661 double gamma = gammaLayers.iterator().next().getGamma(); 662 gammaSlider.setValue((int) (gamma * SLIDER_STEPS / MAX_GAMMA_FACTOR)); 663 } 664 } 665 666 private void updateOpacitySlider(List<Layer> layers, boolean allHidden) { 667 if (layers.isEmpty() || allHidden) { 668 opacitySlider.setEnabled(false); 669 } else { 670 opacitySlider.setEnabled(true); 614 for (FilterSlider<?> slider : sliders) { 615 slider.updateSlider(layers, allHidden); 616 } 617 } 618 619 @Override 620 public boolean supportLayers(List<Layer> layers) { 621 return !layers.isEmpty(); 622 } 623 624 @Override 625 public Component createMenuComponent() { 626 return new JMenuItem(this); 627 } 628 629 @Override 630 public void updateEnabledState() { 631 setEnabled(!model.getSelectedLayers().isEmpty()); 632 } 633 634 /** 635 * Sets the corresponding side button. 636 * @param sideButton the corresponding side button 637 */ 638 void setCorrespondingSideButton(SideButton sideButton) { 639 this.sideButton = sideButton; 640 } 641 642 /** 643 * This is a slider for a filter value. 644 * @author Michael Zangl 645 * 646 * @param <T> The layer type. 647 */ 648 private abstract class FilterSlider<T extends Layer> extends JSlider { 649 private final double minValue; 650 private final double maxValue; 651 private final Class<T> layerClassFilter; 652 653 /** 654 * Create a new filter slider. 655 * @param minValue The minimum value to map to the left side. 656 * @param maxValue The maximum value to map to the right side. 657 * @param layerClassFilter The type of layer influenced by this filter. 658 */ 659 FilterSlider(double minValue, double maxValue, Class<T> layerClassFilter) { 660 super(JSlider.HORIZONTAL); 661 this.minValue = minValue; 662 this.maxValue = maxValue; 663 this.layerClassFilter = layerClassFilter; 664 setMaximum(SLIDER_STEPS); 665 int tick = convertFromRealValue(1); 666 setMinorTickSpacing(tick); 667 setMajorTickSpacing(tick); 668 setPaintTicks(true); 669 670 addChangeListener(new ChangeListener() { 671 @Override 672 public void stateChanged(ChangeEvent e) { 673 onStateChanged(); 674 } 675 }); 676 } 677 678 /** 679 * Called whenever the state of the slider was changed. 680 * @see #getValueIsAdjusting() 681 * @see #getRealValue() 682 */ 683 protected void onStateChanged() { 684 Collection<T> layers = filterLayers(model.getSelectedLayers()); 685 for (T layer : layers) { 686 applyValueToLayer(layer); 687 } 688 } 689 690 protected void applyValueToLayer(T layer) { 691 } 692 693 protected double getRealValue() { 694 return convertToRealValue(getValue()); 695 } 696 697 protected double convertToRealValue(int value) { 698 double s = (double) value / SLIDER_STEPS; 699 return s * maxValue + (1-s) * minValue; 700 } 701 702 protected void setRealValue(double value) { 703 setValue(convertFromRealValue(value)); 704 } 705 706 protected int convertFromRealValue(double value) { 707 int i = (int) ((value - minValue) / (maxValue - minValue) * SLIDER_STEPS + .5); 708 if (i < getMinimum()) { 709 return getMinimum(); 710 } else if (i > getMaximum()) { 711 return getMaximum(); 712 } else { 713 return i; 714 } 715 } 716 717 public abstract ImageIcon getIcon(); 718 719 public abstract String getLabel(); 720 721 public void updateSlider(List<Layer> layers, boolean allHidden) { 722 Collection<? extends Layer> usedLayers = filterLayers(layers); 723 if (usedLayers.isEmpty() || allHidden) { 724 setEnabled(false); 725 } else { 726 setEnabled(true); 727 updateSliderWhileEnabled(usedLayers, allHidden); 728 } 729 } 730 731 protected Collection<T> filterLayers(List<Layer> layers) { 732 return Utils.filteredCollection(layers, layerClassFilter); 733 } 734 735 protected abstract void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden); 736 } 737 738 /** 739 * This slider allows you to change the opacity of a layer. 740 * 741 * @author Michael Zangl 742 * @see Layer#setOpacity(double) 743 */ 744 class OpacitySlider extends FilterSlider<Layer> { 745 /** 746 * Creaate a new {@link OpacitySlider}. 747 */ 748 OpacitySlider() { 749 super(0, 1, Layer.class); 750 setToolTipText(tr("Adjust opacity of the layer.")); 751 752 } 753 754 @Override 755 protected void onStateChanged() { 756 if (getRealValue() <= 0.001 && !getValueIsAdjusting()) { 757 setVisibleFlag(false); 758 } else { 759 super.onStateChanged(); 760 } 761 } 762 763 @Override 764 protected void applyValueToLayer(Layer layer) { 765 layer.setOpacity(getRealValue()); 766 } 767 768 @Override 769 protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) { 671 770 double opacity = 0; 672 for (Layer l : layers) {771 for (Layer l : usedLayers) { 673 772 opacity += l.getOpacity(); 674 773 } 675 opacity /= layers.size();774 opacity /= usedLayers.size(); 676 775 if (opacity == 0) { 677 776 opacity = 1; 678 setOpacityValue(opacity, false); 679 } 680 opacitySlider.setValue((int) (opacity * SLIDER_STEPS)); 681 } 682 } 683 684 @Override 685 public boolean supportLayers(List<Layer> layers) { 686 return !layers.isEmpty(); 687 } 688 689 @Override 690 public Component createMenuComponent() { 691 return new JMenuItem(this); 692 } 693 694 @Override 695 public void updateEnabledState() { 696 setEnabled(!model.getSelectedLayers().isEmpty()); 697 } 698 699 /** 700 * Sets the corresponding side button. 701 * @param sideButton the corresponding side button 702 */ 703 void setCorrespondingSideButton(SideButton sideButton) { 704 this.sideButton = sideButton; 777 setVisibleFlag(true); 778 } 779 setRealValue(opacity); 780 } 781 782 @Override 783 public String getLabel() { 784 return tr("Opacity"); 785 } 786 787 @Override 788 public ImageIcon getIcon() { 789 return ImageProvider.get("dialogs/layerlist", "transparency"); 790 } 791 792 @Override 793 public String toString() { 794 return "OpacitySlider [getRealValue()=" + getRealValue() + "]"; 795 } 796 } 797 798 /** 799 * This slider allows you to change the gamma value of a layer. 800 * 801 * @author Michael Zangl 802 * @see ImageryLayer#setGamma(double) 803 */ 804 private class GammaFilterSlider extends FilterSlider<ImageryLayer> { 805 806 /** 807 * Create a new {@link GammaFilterSlider} 808 */ 809 GammaFilterSlider() { 810 super(0, MAX_GAMMA_FACTOR, ImageryLayer.class); 811 setToolTipText(tr("Adjust gamma value of the layer.")); 812 } 813 814 @Override 815 protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) { 816 double gamma = ((ImageryLayer) usedLayers.iterator().next()).getGamma(); 817 setRealValue(gamma); 818 } 819 820 @Override 821 protected void applyValueToLayer(ImageryLayer layer) { 822 layer.setGamma(getRealValue()); 823 } 824 825 @Override 826 public ImageIcon getIcon() { 827 return ImageProvider.get("dialogs/layerlist", "gamma"); 828 } 829 830 @Override 831 public String getLabel() { 832 return tr("Gamma"); 833 } 834 } 835 836 /** 837 * This slider allows you to change the sharpness of a layer. 838 * 839 * @author Michael Zangl 840 * @see ImageryLayer#setSharpenLevel(double) 841 */ 842 private class SharpnessSlider extends FilterSlider<ImageryLayer> { 843 844 /** 845 * Creates a new {@link SharpnessSlider} 846 */ 847 SharpnessSlider() { 848 super(0, MAX_SHARPNESS_FACTOR, ImageryLayer.class); 849 setToolTipText(tr("Adjust sharpness/blur value of the layer.")); 850 } 851 852 @Override 853 protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) { 854 setRealValue(((ImageryLayer) usedLayers.iterator().next()).getSharpenLevel()); 855 } 856 857 @Override 858 protected void applyValueToLayer(ImageryLayer layer) { 859 layer.setSharpenLevel(getRealValue()); 860 } 861 862 @Override 863 public ImageIcon getIcon() { 864 return ImageProvider.get("dialogs/layerlist", "sharpness"); 865 } 866 867 @Override 868 public String getLabel() { 869 return tr("Sharpness"); 870 } 871 } 872 873 /** 874 * This slider allows you to change the colorfulness of a layer. 875 * 876 * @author Michael Zangl 877 * @see ImageryLayer#setColorfulness(double) 878 */ 879 private class ColorfulnessSlider extends FilterSlider<ImageryLayer> { 880 881 /** 882 * Create a new {@link ColorfulnessSlider} 883 */ 884 ColorfulnessSlider() { 885 super(0, MAX_COLORFUL_FACTOR, ImageryLayer.class); 886 setToolTipText(tr("Adjust colorfulness of the layer.")); 887 } 888 889 @Override 890 protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) { 891 setRealValue(((ImageryLayer) usedLayers.iterator().next()).getColorfulness()); 892 } 893 894 @Override 895 protected void applyValueToLayer(ImageryLayer layer) { 896 layer.setColorfulness(getRealValue()); 897 } 898 899 @Override 900 public ImageIcon getIcon() { 901 return ImageProvider.get("dialogs/layerlist", "colorfulness"); 902 } 903 904 @Override 905 public String getLabel() { 906 return tr("Colorfulness"); 907 } 705 908 } 706 909 } -
trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
r10001 r10142 259 259 } 260 260 261 @Override 262 public void setSharpenLevel(double sharpenLevel) { 263 super.setSharpenLevel(sharpenLevel); 264 redraw(); 265 } 266 267 @Override 268 public void setColorfulness(double colorfulness) { 269 super.setColorfulness(colorfulness); 270 redraw(); 271 } 272 261 273 /** 262 274 * Marks layer as needing redraw on offset change -
trunk/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java
r9983 r10142 9 9 import java.awt.Component; 10 10 import java.awt.GridBagLayout; 11 import java.awt.Rectangle; 12 import java.awt.RenderingHints; 11 13 import java.awt.Transparency; 12 14 import java.awt.event.ActionEvent; 15 import java.awt.geom.Point2D; 16 import java.awt.geom.Rectangle2D; 13 17 import java.awt.image.BufferedImage; 14 18 import java.awt.image.BufferedImageOp; 19 import java.awt.image.ColorModel; 15 20 import java.awt.image.ConvolveOp; 21 import java.awt.image.DataBuffer; 22 import java.awt.image.DataBufferByte; 16 23 import java.awt.image.Kernel; 17 24 import java.awt.image.LookupOp; … … 70 77 71 78 protected GammaImageProcessor gammaImageProcessor = new GammaImageProcessor(); 79 protected SharpenImageProcessor sharpenImageProcessor = new SharpenImageProcessor(); 80 protected ColorfulImageProcessor collorfulnessImageProcessor = new ColorfulImageProcessor(); 72 81 73 82 private final ImageryAdjustAction adjustAction = new ImageryAdjustAction(this); … … 87 96 icon = ImageProvider.get("imagery_small"); 88 97 } 89 addImageProcessor(c reateSharpener(PROP_SHARPEN_LEVEL.get()));98 addImageProcessor(collorfulnessImageProcessor); 90 99 addImageProcessor(gammaImageProcessor); 100 addImageProcessor(sharpenImageProcessor); 101 sharpenImageProcessor.setSharpenLevel(1 + PROP_SHARPEN_LEVEL.get() / 2f); 91 102 } 92 103 … … 233 244 } 234 245 235 public ImageProcessor createSharpener(int sharpenLevel) {236 final Kernel kernel;237 if (sharpenLevel == 1) {238 kernel = new Kernel(3, 3, new float[]{-0.25f, -0.5f, -0.25f, -0.5f, 4, -0.5f, -0.25f, -0.5f, -0.25f});239 } else if (sharpenLevel == 2) {240 kernel = new Kernel(3, 3, new float[]{-0.5f, -1, -0.5f, -1, 7, -1, -0.5f, -1, -0.5f});241 } else {242 return null;243 }244 BufferedImageOp op = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);245 return createImageProcessor(op, false);246 }247 248 246 /** 249 247 * An image processor which adjusts the gamma value of an image. … … 301 299 302 300 /** 301 * Sharpens or blurs the image, depending on the sharpen value. 302 * <p> 303 * A positive sharpen level means that we sharpen the image. 304 * <p> 305 * A negative sharpen level let's us blur the image. -1 is the most useful value there. 306 * 307 * @author Michael Zangl 308 */ 309 public static class SharpenImageProcessor implements ImageProcessor { 310 private float sharpenLevel = 0; 311 private ConvolveOp op; 312 313 private static float[] KERNEL_IDENTITY = new float[] { 314 0, 0, 0, 315 0, 1, 0, 316 0, 0, 0 317 }; 318 319 private static float[] KERNEL_BLUR = new float[] { 320 1f / 16, 2f / 16, 1f / 16, 321 2f / 16, 4f / 16, 2f / 16, 322 1f / 16, 2f / 16, 1f / 16 323 }; 324 325 private static float[] KERNEL_SHARPEN = new float[] { 326 -.5f, -1f, -.5f, 327 -1f, 7, -1f, 328 -.5f, -1f, -.5f 329 }; 330 331 /** 332 * Gets the current sharpen level. 333 * @return The level. 334 */ 335 public float getSharpenLevel() { 336 return sharpenLevel; 337 } 338 339 /** 340 * Sets the sharpening level. 341 * @param sharpenLevel The level. Clamped to be positive or 0. 342 */ 343 public void setSharpenLevel(float sharpenLevel) { 344 if (sharpenLevel < 0) { 345 this.sharpenLevel = 0; 346 } else { 347 this.sharpenLevel = sharpenLevel; 348 } 349 350 if (this.sharpenLevel < 0.95) { 351 op = generateMixed(this.sharpenLevel, KERNEL_IDENTITY, KERNEL_BLUR); 352 } else if (this.sharpenLevel > 1.05) { 353 op = generateMixed(this.sharpenLevel - 1, KERNEL_SHARPEN, KERNEL_IDENTITY); 354 } else { 355 op = null; 356 } 357 } 358 359 private ConvolveOp generateMixed(float aFactor, float[] a, float[] b) { 360 if (a.length != 9 || b.length != 9) { 361 throw new IllegalArgumentException("Illegal kernel array length."); 362 } 363 float[] values = new float[9]; 364 for (int i = 0; i < values.length; i++) { 365 values[i] = aFactor * a[i] + (1 - aFactor) * b[i]; 366 } 367 return new ConvolveOp(new Kernel(3, 3, values), ConvolveOp.EDGE_NO_OP, null); 368 } 369 370 @Override 371 public BufferedImage process(BufferedImage image) { 372 if (op != null) { 373 return op.filter(image, null); 374 } else { 375 return image; 376 } 377 } 378 379 @Override 380 public String toString() { 381 return "SharpenImageProcessor [sharpenLevel=" + sharpenLevel + "]"; 382 } 383 } 384 385 /** 386 * Adds or removes the colorfulness of the image. 387 * 388 * @author Michael Zangl 389 */ 390 public static class ColorfulImageProcessor implements ImageProcessor { 391 private ColorfulFilter op = null; 392 private double colorfulness = 1; 393 394 /** 395 * Gets the colorfulness value. 396 * @return The value 397 */ 398 public double getColorfulness() { 399 return colorfulness; 400 } 401 402 /** 403 * Sets the colorfulness value. Clamps it to 0+ 404 * @param colorfulness The value 405 */ 406 public void setColorfulness(double colorfulness) { 407 if (colorfulness < 0) { 408 this.colorfulness = 0; 409 } else { 410 this.colorfulness = colorfulness; 411 } 412 413 if (this.colorfulness < .95 || this.colorfulness > 1.05) { 414 op = new ColorfulFilter(this.colorfulness); 415 } else { 416 op = null; 417 } 418 } 419 420 @Override 421 public BufferedImage process(BufferedImage image) { 422 if (op != null) { 423 return op.filter(image, null); 424 } else { 425 return image; 426 } 427 } 428 429 @Override 430 public String toString() { 431 return "ColorfulImageProcessor [colorfulness=" + colorfulness + "]"; 432 } 433 } 434 435 private static class ColorfulFilter implements BufferedImageOp { 436 private final double colorfulness; 437 438 /** 439 * Create a new colorful filter. 440 * @param colorfulness The colorfulness as defined in the {@link ColorfulImageProcessor} class. 441 */ 442 ColorfulFilter(double colorfulness) { 443 this.colorfulness = colorfulness; 444 } 445 446 @Override 447 public BufferedImage filter(BufferedImage src, BufferedImage dest) { 448 if (src.getWidth() == 0 || src.getHeight() == 0) { 449 return src; 450 } 451 452 if (dest == null) { 453 dest = createCompatibleDestImage(src, null); 454 } 455 DataBuffer srcBuffer = src.getRaster().getDataBuffer(); 456 DataBuffer destBuffer = dest.getRaster().getDataBuffer(); 457 if (!(srcBuffer instanceof DataBufferByte) || !(destBuffer instanceof DataBufferByte)) { 458 Main.trace("Cannot apply color filter: Images do not use DataBufferByte."); 459 return src; 460 } 461 462 int type = src.getType(); 463 if (type != dest.getType()) { 464 Main.trace("Cannot apply color filter: Src / Dest differ in type (" + type + "/" + dest.getType() + ")"); 465 return src; 466 } 467 int redOffset, greenOffset, blueOffset, alphaOffset = 0; 468 switch (type) { 469 case BufferedImage.TYPE_3BYTE_BGR: 470 blueOffset = 0; 471 greenOffset = 1; 472 redOffset = 2; 473 break; 474 case BufferedImage.TYPE_4BYTE_ABGR: 475 case BufferedImage.TYPE_4BYTE_ABGR_PRE: 476 blueOffset = 1; 477 greenOffset = 2; 478 redOffset = 3; 479 break; 480 case BufferedImage.TYPE_INT_ARGB: 481 case BufferedImage.TYPE_INT_ARGB_PRE: 482 redOffset = 0; 483 greenOffset = 1; 484 blueOffset = 2; 485 alphaOffset = 3; 486 break; 487 default: 488 Main.trace("Cannot apply color filter: Source image is of wrong type (" + type + ")."); 489 return src; 490 } 491 doFilter((DataBufferByte) srcBuffer, (DataBufferByte) destBuffer, redOffset, greenOffset, blueOffset, 492 alphaOffset, src.getAlphaRaster() != null); 493 return dest; 494 } 495 496 private void doFilter(DataBufferByte src, DataBufferByte dest, int redOffset, int greenOffset, int blueOffset, 497 int alphaOffset, boolean hasAlpha) { 498 byte[] srcPixels = src.getData(); 499 byte[] destPixels = dest.getData(); 500 if (srcPixels.length != destPixels.length) { 501 Main.trace("Cannot apply color filter: Source/Dest lengths differ."); 502 return; 503 } 504 int entries = hasAlpha ? 4 : 3; 505 for (int i = 0; i < srcPixels.length; i += entries) { 506 int r = srcPixels[i + redOffset] & 0xff; 507 int g = srcPixels[i + greenOffset] & 0xff; 508 int b = srcPixels[i + blueOffset] & 0xff; 509 float luminosity = r * .21f + g * .72f + b * .07f; 510 destPixels[i + redOffset] = mix(r, luminosity); 511 destPixels[i + greenOffset] = mix(g, luminosity); 512 destPixels[i + blueOffset] = mix(b, luminosity); 513 if (hasAlpha) { 514 destPixels[i + alphaOffset] = srcPixels[i + alphaOffset]; 515 } 516 } 517 } 518 519 private byte mix(int color, float luminosity) { 520 int val = (int) (colorfulness * color + (1 - colorfulness) * luminosity); 521 if (val < 0) { 522 return 0; 523 } else if (val > 0xff) { 524 return (byte) 0xff; 525 } else { 526 return (byte) val; 527 } 528 } 529 530 @Override 531 public Rectangle2D getBounds2D(BufferedImage src) { 532 return new Rectangle(src.getWidth(), src.getHeight()); 533 } 534 535 @Override 536 public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) { 537 return new BufferedImage(src.getWidth(), src.getHeight(), src.getType()); 538 } 539 540 @Override 541 public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) { 542 return (Point2D) srcPt.clone(); 543 } 544 545 @Override 546 public RenderingHints getRenderingHints() { 547 return null; 548 } 549 550 } 551 552 /** 303 553 * Returns the currently set gamma value. 304 554 * @return the currently set gamma value … … 314 564 public void setGamma(double gamma) { 315 565 gammaImageProcessor.setGamma(gamma); 566 } 567 568 /** 569 * Gets the current sharpen level. 570 * @return The sharpen level. 571 */ 572 public double getSharpenLevel() { 573 return sharpenImageProcessor.getSharpenLevel(); 574 } 575 576 /** 577 * Sets the sharpen level for the layer. 578 * <code>1</code> means no change in sharpness. 579 * Values in range 0..1 blur the image. 580 * Values above 1 are used to sharpen the image. 581 * @param sharpenLevel The sharpen level. 582 */ 583 public void setSharpenLevel(double sharpenLevel) { 584 sharpenImageProcessor.setSharpenLevel((float) sharpenLevel); 585 } 586 587 /** 588 * Gets the colorfulness of this image. 589 * @return The colorfulness 590 */ 591 public double getColorfulness() { 592 return collorfulnessImageProcessor.getColorfulness(); 593 } 594 595 /** 596 * Sets the colorfulness of this image. 597 * 0 means grayscale. 598 * 1 means normal colorfulness. 599 * Values greater than 1 are allowed. 600 * @param colorfulness The colorfulness. 601 */ 602 public void setColorfulness(double colorfulness) { 603 collorfulnessImageProcessor.setColorfulness(colorfulness); 316 604 } 317 605
Note:
See TracChangeset
for help on using the changeset viewer.