Ticket #13159: patch-mapview-separate-tile-source.patch
| File patch-mapview-separate-tile-source.patch, 49.9 KB (added by , 10 years ago) |
|---|
-
src/org/openstreetmap/josm/gui/dialogs/layer/LayerVisibilityAction.java
diff --git a/src/org/openstreetmap/josm/gui/dialogs/layer/LayerVisibilityAction.java b/src/org/openstreetmap/josm/gui/dialogs/layer/LayerVisibilityAction.java index 1c8a58f..538c714 100644
a b import org.openstreetmap.josm.gui.dialogs.LayerListDialog.LayerListModel; 28 28 import org.openstreetmap.josm.gui.layer.ImageryLayer; 29 29 import org.openstreetmap.josm.gui.layer.Layer; 30 30 import org.openstreetmap.josm.gui.layer.Layer.LayerAction; 31 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings; 31 32 import org.openstreetmap.josm.tools.GBC; 32 33 import org.openstreetmap.josm.tools.ImageProvider; 33 34 import org.openstreetmap.josm.tools.Utils; … … public final class LayerVisibilityAction extends AbstractAction implements IEnab 306 307 * This slider allows you to change the gamma value of a layer. 307 308 * 308 309 * @author Michael Zangl 309 * @see Imagery Layer#setGamma(double)310 * @see ImageryFilterSettings#setGamma(double) 310 311 */ 311 312 private class GammaFilterSlider extends FilterSlider<ImageryLayer> { 312 313 … … public final class LayerVisibilityAction extends AbstractAction implements IEnab 320 321 321 322 @Override 322 323 protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) { 323 double gamma = ((ImageryLayer) usedLayers.iterator().next()).get Gamma();324 double gamma = ((ImageryLayer) usedLayers.iterator().next()).getFilterSettings().getGamma(); 324 325 setRealValue(mapGammaToInterval(gamma)); 325 326 } 326 327 327 328 @Override 328 329 protected void applyValueToLayer(ImageryLayer layer) { 329 layer. setGamma(mapIntervalToGamma(getRealValue()));330 layer.getFilterSettings().setGamma(mapIntervalToGamma(getRealValue())); 330 331 } 331 332 332 333 @Override … … public final class LayerVisibilityAction extends AbstractAction implements IEnab 365 366 * This slider allows you to change the sharpness of a layer. 366 367 * 367 368 * @author Michael Zangl 368 * @see Imagery Layer#setSharpenLevel(double)369 * @see ImageryFilterSettings#setSharpenLevel(double) 369 370 */ 370 371 private class SharpnessSlider extends FilterSlider<ImageryLayer> { 371 372 … … public final class LayerVisibilityAction extends AbstractAction implements IEnab 379 380 380 381 @Override 381 382 protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) { 382 setRealValue(((ImageryLayer) usedLayers.iterator().next()).get SharpenLevel());383 setRealValue(((ImageryLayer) usedLayers.iterator().next()).getFilterSettings().getSharpenLevel()); 383 384 } 384 385 385 386 @Override 386 387 protected void applyValueToLayer(ImageryLayer layer) { 387 layer. setSharpenLevel(getRealValue());388 layer.getFilterSettings().setSharpenLevel(getRealValue()); 388 389 } 389 390 390 391 @Override … … public final class LayerVisibilityAction extends AbstractAction implements IEnab 402 403 * This slider allows you to change the colorfulness of a layer. 403 404 * 404 405 * @author Michael Zangl 405 * @see Imagery Layer#setColorfulness(double)406 * @see ImageryFilterSettings#setColorfulness(double) 406 407 */ 407 408 private class ColorfulnessSlider extends FilterSlider<ImageryLayer> { 408 409 … … public final class LayerVisibilityAction extends AbstractAction implements IEnab 416 417 417 418 @Override 418 419 protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) { 419 setRealValue(((ImageryLayer) usedLayers.iterator().next()).get Colorfulness());420 setRealValue(((ImageryLayer) usedLayers.iterator().next()).getFilterSettings().getColorfulness()); 420 421 } 421 422 422 423 @Override 423 424 protected void applyValueToLayer(ImageryLayer layer) { 424 layer. setColorfulness(getRealValue());425 layer.getFilterSettings().setColorfulness(getRealValue()); 425 426 } 426 427 427 428 @Override -
src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
diff --git a/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java b/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java index 79fad29..929aff8 100644
a b import org.openstreetmap.josm.gui.NavigatableComponent.ZoomChangeListener; 81 81 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 82 82 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 83 83 import org.openstreetmap.josm.gui.dialogs.LayerListPopup; 84 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings.FilterChangeListener; 84 85 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 85 86 import org.openstreetmap.josm.gui.util.GuiHelper; 86 87 import org.openstreetmap.josm.io.WMSLayerImporter; … … import org.openstreetmap.josm.tools.GBC; 98 99 * @since 8526 (copied from TMSLayer) 99 100 */ 100 101 public abstract class AbstractTileSourceLayer<T extends AbstractTMSTileSource> extends ImageryLayer 101 implements ImageObserver, TileLoaderListener, ZoomChangeListener {102 implements ImageObserver, TileLoaderListener, ZoomChangeListener, FilterChangeListener { 102 103 private static final String PREFERENCE_PREFIX = "imagery.generic"; 103 104 104 105 /** maximum zoom level supported */ … … implements ImageObserver, TileLoaderListener, ZoomChangeListener { 174 175 super(info); 175 176 setBackgroundLayer(true); 176 177 this.setVisible(true); 178 getFilterSettings().addFilterChangeListener(this); 179 } 180 181 @Override 182 public void filterChanged() { 183 redraw(); 177 184 } 178 185 179 186 protected abstract TileLoaderFactory getTileLoaderFactory(); … … implements ImageObserver, TileLoaderListener, ZoomChangeListener { 262 269 if (isVisible()) Main.map.repaint(); 263 270 } 264 271 265 @Override266 public void setGamma(double gamma) {267 super.setGamma(gamma);268 redraw();269 }270 271 @Override272 public void setSharpenLevel(double sharpenLevel) {273 super.setSharpenLevel(sharpenLevel);274 redraw();275 }276 277 @Override278 public void setColorfulness(double colorfulness) {279 super.setColorfulness(colorfulness);280 redraw();281 }282 283 272 /** 284 273 * Marks layer as needing redraw on offset change 285 274 */ -
src/org/openstreetmap/josm/gui/layer/ImageryLayer.java
diff --git a/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java b/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java index 4a6d290..3ab3633 100644
a b import static org.openstreetmap.josm.tools.I18n.trc; 8 8 import java.awt.Color; 9 9 import java.awt.Component; 10 10 import java.awt.GridBagLayout; 11 import java.awt.Rectangle;12 import java.awt.RenderingHints;13 import java.awt.Transparency;14 11 import java.awt.event.ActionEvent; 15 import java.awt.geom.Point2D;16 import java.awt.geom.Rectangle2D;17 12 import java.awt.image.BufferedImage; 18 13 import java.awt.image.BufferedImageOp; 19 import java.awt.image.ColorModel;20 import java.awt.image.ConvolveOp;21 import java.awt.image.DataBuffer;22 import java.awt.image.DataBufferByte;23 import java.awt.image.Kernel;24 import java.awt.image.LookupOp;25 import java.awt.image.ShortLookupTable;26 14 import java.util.ArrayList; 27 15 import java.util.List; 28 16 … … import org.openstreetmap.josm.data.imagery.OffsetBookmark; 45 33 import org.openstreetmap.josm.data.preferences.ColorProperty; 46 34 import org.openstreetmap.josm.data.preferences.IntegerProperty; 47 35 import org.openstreetmap.josm.gui.MenuScroller; 36 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings; 48 37 import org.openstreetmap.josm.gui.widgets.UrlLabel; 49 38 import org.openstreetmap.josm.tools.GBC; 50 39 import org.openstreetmap.josm.tools.ImageProvider; … … public abstract class ImageryLayer extends Layer { 75 64 protected double dx; 76 65 protected double dy; 77 66 78 protected GammaImageProcessor gammaImageProcessor = new GammaImageProcessor();79 protected SharpenImageProcessor sharpenImageProcessor = new SharpenImageProcessor();80 protected ColorfulImageProcessor collorfulnessImageProcessor = new ColorfulImageProcessor();81 82 67 private final ImageryAdjustAction adjustAction = new ImageryAdjustAction(this); 83 68 69 private final ImageryFilterSettings filterSettings = new ImageryFilterSettings(); 70 84 71 /** 85 72 * Constructs a new {@code ImageryLayer}. 86 73 * @param info imagery info … … public abstract class ImageryLayer extends Layer { 95 82 if (icon == null) { 96 83 icon = ImageProvider.get("imagery_small"); 97 84 } 98 addImageProcessor(collorfulnessImageProcessor);99 addImageProcessor(gammaImageProcessor);100 addImageProcessor(sharpenImageProcessor);101 sharpenImageProcessor.setSharpenLevel(1 + PROP_SHARPEN_LEVEL.get() / 2f);85 for (ImageProcessor processor : filterSettings.getProcessors()) { 86 addImageProcessor(processor); 87 } 88 filterSettings.setSharpenLevel(1 + PROP_SHARPEN_LEVEL.get() / 2f); 102 89 } 103 90 104 91 public double getPPD() { … … public abstract class ImageryLayer extends Layer { 258 245 } 259 246 260 247 /** 261 * An image processor which adjusts the gamma value of an image. 262 */ 263 public static class GammaImageProcessor implements ImageProcessor { 264 private double gamma = 1; 265 final short[] gammaChange = new short[256]; 266 private final LookupOp op3 = new LookupOp( 267 new ShortLookupTable(0, new short[][]{gammaChange, gammaChange, gammaChange}), null); 268 private final LookupOp op4 = new LookupOp( 269 new ShortLookupTable(0, new short[][]{gammaChange, gammaChange, gammaChange, gammaChange}), null); 270 271 /** 272 * Returns the currently set gamma value. 273 * @return the currently set gamma value 274 */ 275 public double getGamma() { 276 return gamma; 277 } 278 279 /** 280 * Sets a new gamma value, {@code 1} stands for no correction. 281 * @param gamma new gamma value 282 */ 283 public void setGamma(double gamma) { 284 this.gamma = gamma; 285 for (int i = 0; i < 256; i++) { 286 gammaChange[i] = (short) (255 * Math.pow(i / 255., gamma)); 287 } 288 } 289 290 @Override 291 public BufferedImage process(BufferedImage image) { 292 if (gamma == 1) { 293 return image; 294 } 295 try { 296 final int bands = image.getRaster().getNumBands(); 297 if (image.getType() != BufferedImage.TYPE_CUSTOM && bands == 3) { 298 return op3.filter(image, null); 299 } else if (image.getType() != BufferedImage.TYPE_CUSTOM && bands == 4) { 300 return op4.filter(image, null); 301 } 302 } catch (IllegalArgumentException ignore) { 303 Main.trace(ignore); 304 } 305 final int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; 306 final BufferedImage to = new BufferedImage(image.getWidth(), image.getHeight(), type); 307 to.getGraphics().drawImage(image, 0, 0, null); 308 return process(to); 309 } 310 311 @Override 312 public String toString() { 313 return "GammaImageProcessor [gamma=" + gamma + ']'; 314 } 315 } 316 317 /** 318 * Sharpens or blurs the image, depending on the sharpen value. 319 * <p> 320 * A positive sharpen level means that we sharpen the image. 321 * <p> 322 * A negative sharpen level let's us blur the image. -1 is the most useful value there. 323 * 324 * @author Michael Zangl 325 */ 326 public static class SharpenImageProcessor implements ImageProcessor { 327 private float sharpenLevel; 328 private ConvolveOp op; 329 330 private static float[] KERNEL_IDENTITY = new float[] { 331 0, 0, 0, 332 0, 1, 0, 333 0, 0, 0 334 }; 335 336 private static float[] KERNEL_BLUR = new float[] { 337 1f / 16, 2f / 16, 1f / 16, 338 2f / 16, 4f / 16, 2f / 16, 339 1f / 16, 2f / 16, 1f / 16 340 }; 341 342 private static float[] KERNEL_SHARPEN = new float[] { 343 -.5f, -1f, -.5f, 344 -1f, 7, -1f, 345 -.5f, -1f, -.5f 346 }; 347 348 /** 349 * Gets the current sharpen level. 350 * @return The level. 351 */ 352 public float getSharpenLevel() { 353 return sharpenLevel; 354 } 355 356 /** 357 * Sets the sharpening level. 358 * @param sharpenLevel The level. Clamped to be positive or 0. 359 */ 360 public void setSharpenLevel(float sharpenLevel) { 361 if (sharpenLevel < 0) { 362 this.sharpenLevel = 0; 363 } else { 364 this.sharpenLevel = sharpenLevel; 365 } 366 367 if (this.sharpenLevel < 0.95) { 368 op = generateMixed(this.sharpenLevel, KERNEL_IDENTITY, KERNEL_BLUR); 369 } else if (this.sharpenLevel > 1.05) { 370 op = generateMixed(this.sharpenLevel - 1, KERNEL_SHARPEN, KERNEL_IDENTITY); 371 } else { 372 op = null; 373 } 374 } 375 376 private ConvolveOp generateMixed(float aFactor, float[] a, float[] b) { 377 if (a.length != 9 || b.length != 9) { 378 throw new IllegalArgumentException("Illegal kernel array length."); 379 } 380 float[] values = new float[9]; 381 for (int i = 0; i < values.length; i++) { 382 values[i] = aFactor * a[i] + (1 - aFactor) * b[i]; 383 } 384 return new ConvolveOp(new Kernel(3, 3, values), ConvolveOp.EDGE_NO_OP, null); 385 } 386 387 @Override 388 public BufferedImage process(BufferedImage image) { 389 if (op != null) { 390 return op.filter(image, null); 391 } else { 392 return image; 393 } 394 } 395 396 @Override 397 public String toString() { 398 return "SharpenImageProcessor [sharpenLevel=" + sharpenLevel + ']'; 399 } 400 } 401 402 /** 403 * Adds or removes the colorfulness of the image. 404 * 405 * @author Michael Zangl 406 */ 407 public static class ColorfulImageProcessor implements ImageProcessor { 408 private ColorfulFilter op; 409 private double colorfulness = 1; 410 411 /** 412 * Gets the colorfulness value. 413 * @return The value 414 */ 415 public double getColorfulness() { 416 return colorfulness; 417 } 418 419 /** 420 * Sets the colorfulness value. Clamps it to 0+ 421 * @param colorfulness The value 422 */ 423 public void setColorfulness(double colorfulness) { 424 if (colorfulness < 0) { 425 this.colorfulness = 0; 426 } else { 427 this.colorfulness = colorfulness; 428 } 429 430 if (this.colorfulness < .95 || this.colorfulness > 1.05) { 431 op = new ColorfulFilter(this.colorfulness); 432 } else { 433 op = null; 434 } 435 } 436 437 @Override 438 public BufferedImage process(BufferedImage image) { 439 if (op != null) { 440 return op.filter(image, null); 441 } else { 442 return image; 443 } 444 } 445 446 @Override 447 public String toString() { 448 return "ColorfulImageProcessor [colorfulness=" + colorfulness + ']'; 449 } 450 } 451 452 private static class ColorfulFilter implements BufferedImageOp { 453 private final double colorfulness; 454 455 /** 456 * Create a new colorful filter. 457 * @param colorfulness The colorfulness as defined in the {@link ColorfulImageProcessor} class. 458 */ 459 ColorfulFilter(double colorfulness) { 460 this.colorfulness = colorfulness; 461 } 462 463 @Override 464 public BufferedImage filter(BufferedImage src, BufferedImage dest) { 465 if (src.getWidth() == 0 || src.getHeight() == 0) { 466 return src; 467 } 468 469 if (dest == null) { 470 dest = createCompatibleDestImage(src, null); 471 } 472 DataBuffer srcBuffer = src.getRaster().getDataBuffer(); 473 DataBuffer destBuffer = dest.getRaster().getDataBuffer(); 474 if (!(srcBuffer instanceof DataBufferByte) || !(destBuffer instanceof DataBufferByte)) { 475 Main.trace("Cannot apply color filter: Images do not use DataBufferByte."); 476 return src; 477 } 478 479 int type = src.getType(); 480 if (type != dest.getType()) { 481 Main.trace("Cannot apply color filter: Src / Dest differ in type (" + type + '/' + dest.getType() + ')'); 482 return src; 483 } 484 int redOffset, greenOffset, blueOffset, alphaOffset = 0; 485 switch (type) { 486 case BufferedImage.TYPE_3BYTE_BGR: 487 blueOffset = 0; 488 greenOffset = 1; 489 redOffset = 2; 490 break; 491 case BufferedImage.TYPE_4BYTE_ABGR: 492 case BufferedImage.TYPE_4BYTE_ABGR_PRE: 493 blueOffset = 1; 494 greenOffset = 2; 495 redOffset = 3; 496 break; 497 case BufferedImage.TYPE_INT_ARGB: 498 case BufferedImage.TYPE_INT_ARGB_PRE: 499 redOffset = 0; 500 greenOffset = 1; 501 blueOffset = 2; 502 alphaOffset = 3; 503 break; 504 default: 505 Main.trace("Cannot apply color filter: Source image is of wrong type (" + type + ")."); 506 return src; 507 } 508 doFilter((DataBufferByte) srcBuffer, (DataBufferByte) destBuffer, redOffset, greenOffset, blueOffset, 509 alphaOffset, src.getAlphaRaster() != null); 510 return dest; 511 } 512 513 private void doFilter(DataBufferByte src, DataBufferByte dest, int redOffset, int greenOffset, int blueOffset, 514 int alphaOffset, boolean hasAlpha) { 515 byte[] srcPixels = src.getData(); 516 byte[] destPixels = dest.getData(); 517 if (srcPixels.length != destPixels.length) { 518 Main.trace("Cannot apply color filter: Source/Dest lengths differ."); 519 return; 520 } 521 int entries = hasAlpha ? 4 : 3; 522 for (int i = 0; i < srcPixels.length; i += entries) { 523 int r = srcPixels[i + redOffset] & 0xff; 524 int g = srcPixels[i + greenOffset] & 0xff; 525 int b = srcPixels[i + blueOffset] & 0xff; 526 double luminosity = r * .21d + g * .72d + b * .07d; 527 destPixels[i + redOffset] = mix(r, luminosity); 528 destPixels[i + greenOffset] = mix(g, luminosity); 529 destPixels[i + blueOffset] = mix(b, luminosity); 530 if (hasAlpha) { 531 destPixels[i + alphaOffset] = srcPixels[i + alphaOffset]; 532 } 533 } 534 } 535 536 private byte mix(int color, double luminosity) { 537 int val = (int) (colorfulness * color + (1 - colorfulness) * luminosity); 538 if (val < 0) { 539 return 0; 540 } else if (val > 0xff) { 541 return (byte) 0xff; 542 } else { 543 return (byte) val; 544 } 545 } 546 547 @Override 548 public Rectangle2D getBounds2D(BufferedImage src) { 549 return new Rectangle(src.getWidth(), src.getHeight()); 550 } 551 552 @Override 553 public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) { 554 return new BufferedImage(src.getWidth(), src.getHeight(), src.getType()); 555 } 556 557 @Override 558 public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) { 559 return (Point2D) srcPt.clone(); 560 } 561 562 @Override 563 public RenderingHints getRenderingHints() { 564 return null; 565 } 566 567 } 568 569 /** 570 * Returns the currently set gamma value. 571 * @return the currently set gamma value 572 */ 573 public double getGamma() { 574 return gammaImageProcessor.getGamma(); 575 } 576 577 /** 578 * Sets a new gamma value, {@code 1} stands for no correction. 579 * @param gamma new gamma value 580 */ 581 public void setGamma(double gamma) { 582 gammaImageProcessor.setGamma(gamma); 583 } 584 585 /** 586 * Gets the current sharpen level. 587 * @return The sharpen level. 588 */ 589 public double getSharpenLevel() { 590 return sharpenImageProcessor.getSharpenLevel(); 591 } 592 593 /** 594 * Sets the sharpen level for the layer. 595 * <code>1</code> means no change in sharpness. 596 * Values in range 0..1 blur the image. 597 * Values above 1 are used to sharpen the image. 598 * @param sharpenLevel The sharpen level. 599 */ 600 public void setSharpenLevel(double sharpenLevel) { 601 sharpenImageProcessor.setSharpenLevel((float) sharpenLevel); 602 } 603 604 /** 605 * Gets the colorfulness of this image. 606 * @return The colorfulness 607 */ 608 public double getColorfulness() { 609 return collorfulnessImageProcessor.getColorfulness(); 610 } 611 612 /** 613 * Sets the colorfulness of this image. 614 * 0 means grayscale. 615 * 1 means normal colorfulness. 616 * Values greater than 1 are allowed. 617 * @param colorfulness The colorfulness. 248 * Gets the settings for the filter that is applied to this layer. 249 * @return The filter settings. 618 250 */ 619 public void setColorfulness(double colorfulness) {620 collorfulnessImageProcessor.setColorfulness(colorfulness);251 public ImageryFilterSettings getFilterSettings() { 252 return filterSettings; 621 253 } 622 254 623 255 /** -
new file src/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessor.java
diff --git a/src/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessor.java b/src/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessor.java new file mode 100644 index 0000000..dbb4023
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.layer.imagery; 3 4 import java.awt.Rectangle; 5 import java.awt.RenderingHints; 6 import java.awt.geom.Point2D; 7 import java.awt.geom.Rectangle2D; 8 import java.awt.image.BufferedImage; 9 import java.awt.image.BufferedImageOp; 10 import java.awt.image.ColorModel; 11 import java.awt.image.DataBuffer; 12 import java.awt.image.DataBufferByte; 13 14 import org.openstreetmap.josm.Main; 15 import org.openstreetmap.josm.gui.layer.ImageProcessor; 16 17 /** 18 * Adds or removes the colorfulness of the image. 19 * 20 * @author Michael Zangl 21 */ 22 public class ColorfulImageProcessor implements ImageProcessor { 23 private ColorfulFilter op; 24 private double colorfulness = 1; 25 26 /** 27 * Gets the colorfulness value. 28 * @return The value 29 */ 30 public double getColorfulness() { 31 return colorfulness; 32 } 33 34 /** 35 * Sets the colorfulness value. Clamps it to 0+ 36 * @param colorfulness The value 37 */ 38 public void setColorfulness(double colorfulness) { 39 if (colorfulness < 0) { 40 this.colorfulness = 0; 41 } else { 42 this.colorfulness = colorfulness; 43 } 44 45 if (this.colorfulness < .95 || this.colorfulness > 1.05) { 46 op = new ColorfulFilter(this.colorfulness); 47 } else { 48 op = null; 49 } 50 } 51 52 @Override 53 public BufferedImage process(BufferedImage image) { 54 if (op != null) { 55 return op.filter(image, null); 56 } else { 57 return image; 58 } 59 } 60 61 @Override 62 public String toString() { 63 return "ColorfulImageProcessor [colorfulness=" + colorfulness + ']'; 64 } 65 66 static class ColorfulFilter implements BufferedImageOp { 67 private final double colorfulness; 68 69 /** 70 * Create a new colorful filter. 71 * @param colorfulness The colorfulness as defined in the {@link ColorfulImageProcessor} class. 72 */ 73 ColorfulFilter(double colorfulness) { 74 this.colorfulness = colorfulness; 75 } 76 77 @Override 78 public BufferedImage filter(BufferedImage src, BufferedImage dest) { 79 if (src.getWidth() == 0 || src.getHeight() == 0) { 80 return src; 81 } 82 83 if (dest == null) { 84 dest = createCompatibleDestImage(src, null); 85 } 86 DataBuffer srcBuffer = src.getRaster().getDataBuffer(); 87 DataBuffer destBuffer = dest.getRaster().getDataBuffer(); 88 if (!(srcBuffer instanceof DataBufferByte) || !(destBuffer instanceof DataBufferByte)) { 89 Main.trace("Cannot apply color filter: Images do not use DataBufferByte."); 90 return src; 91 } 92 93 int type = src.getType(); 94 if (type != dest.getType()) { 95 Main.trace("Cannot apply color filter: Src / Dest differ in type (" + type + '/' + dest.getType() + ')'); 96 return src; 97 } 98 int redOffset, greenOffset, blueOffset, alphaOffset = 0; 99 switch (type) { 100 case BufferedImage.TYPE_3BYTE_BGR: 101 blueOffset = 0; 102 greenOffset = 1; 103 redOffset = 2; 104 break; 105 case BufferedImage.TYPE_4BYTE_ABGR: 106 case BufferedImage.TYPE_4BYTE_ABGR_PRE: 107 blueOffset = 1; 108 greenOffset = 2; 109 redOffset = 3; 110 break; 111 case BufferedImage.TYPE_INT_ARGB: 112 case BufferedImage.TYPE_INT_ARGB_PRE: 113 redOffset = 0; 114 greenOffset = 1; 115 blueOffset = 2; 116 alphaOffset = 3; 117 break; 118 default: 119 Main.trace("Cannot apply color filter: Source image is of wrong type (" + type + ")."); 120 return src; 121 } 122 doFilter((DataBufferByte) srcBuffer, (DataBufferByte) destBuffer, redOffset, greenOffset, blueOffset, 123 alphaOffset, src.getAlphaRaster() != null); 124 return dest; 125 } 126 127 private void doFilter(DataBufferByte src, DataBufferByte dest, int redOffset, int greenOffset, int blueOffset, 128 int alphaOffset, boolean hasAlpha) { 129 byte[] srcPixels = src.getData(); 130 byte[] destPixels = dest.getData(); 131 if (srcPixels.length != destPixels.length) { 132 Main.trace("Cannot apply color filter: Source/Dest lengths differ."); 133 return; 134 } 135 int entries = hasAlpha ? 4 : 3; 136 for (int i = 0; i < srcPixels.length; i += entries) { 137 int r = srcPixels[i + redOffset] & 0xff; 138 int g = srcPixels[i + greenOffset] & 0xff; 139 int b = srcPixels[i + blueOffset] & 0xff; 140 double luminosity = r * .21d + g * .72d + b * .07d; 141 destPixels[i + redOffset] = mix(r, luminosity); 142 destPixels[i + greenOffset] = mix(g, luminosity); 143 destPixels[i + blueOffset] = mix(b, luminosity); 144 if (hasAlpha) { 145 destPixels[i + alphaOffset] = srcPixels[i + alphaOffset]; 146 } 147 } 148 } 149 150 private byte mix(int color, double luminosity) { 151 int val = (int) (colorfulness * color + (1 - colorfulness) * luminosity); 152 if (val < 0) { 153 return 0; 154 } else if (val > 0xff) { 155 return (byte) 0xff; 156 } else { 157 return (byte) val; 158 } 159 } 160 161 @Override 162 public Rectangle2D getBounds2D(BufferedImage src) { 163 return new Rectangle(src.getWidth(), src.getHeight()); 164 } 165 166 @Override 167 public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) { 168 return new BufferedImage(src.getWidth(), src.getHeight(), src.getType()); 169 } 170 171 @Override 172 public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) { 173 return (Point2D) srcPt.clone(); 174 } 175 176 @Override 177 public RenderingHints getRenderingHints() { 178 return null; 179 } 180 181 } 182 } 183 No newline at end of file -
new file src/org/openstreetmap/josm/gui/layer/imagery/GammaImageProcessor.java
diff --git a/src/org/openstreetmap/josm/gui/layer/imagery/GammaImageProcessor.java b/src/org/openstreetmap/josm/gui/layer/imagery/GammaImageProcessor.java new file mode 100644 index 0000000..d72ae2a
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.layer.imagery; 3 4 import java.awt.Transparency; 5 import java.awt.image.BufferedImage; 6 import java.awt.image.LookupOp; 7 import java.awt.image.ShortLookupTable; 8 9 import org.openstreetmap.josm.Main; 10 import org.openstreetmap.josm.gui.layer.ImageProcessor; 11 12 /** 13 * An image processor which adjusts the gamma value of an image. 14 */ 15 public class GammaImageProcessor implements ImageProcessor { 16 private double gamma = 1; 17 final short[] gammaChange = new short[256]; 18 private final LookupOp op3 = new LookupOp( 19 new ShortLookupTable(0, new short[][]{gammaChange, gammaChange, gammaChange}), null); 20 private final LookupOp op4 = new LookupOp( 21 new ShortLookupTable(0, new short[][]{gammaChange, gammaChange, gammaChange, gammaChange}), null); 22 23 /** 24 * Returns the currently set gamma value. 25 * @return the currently set gamma value 26 */ 27 public double getGamma() { 28 return gamma; 29 } 30 31 /** 32 * Sets a new gamma value, {@code 1} stands for no correction. 33 * @param gamma new gamma value 34 */ 35 public void setGamma(double gamma) { 36 this.gamma = gamma; 37 for (int i = 0; i < 256; i++) { 38 gammaChange[i] = (short) (255 * Math.pow(i / 255., gamma)); 39 } 40 } 41 42 @Override 43 public BufferedImage process(BufferedImage image) { 44 if (gamma == 1) { 45 return image; 46 } 47 try { 48 final int bands = image.getRaster().getNumBands(); 49 if (image.getType() != BufferedImage.TYPE_CUSTOM && bands == 3) { 50 return op3.filter(image, null); 51 } else if (image.getType() != BufferedImage.TYPE_CUSTOM && bands == 4) { 52 return op4.filter(image, null); 53 } 54 } catch (IllegalArgumentException ignore) { 55 Main.trace(ignore); 56 } 57 final int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; 58 final BufferedImage to = new BufferedImage(image.getWidth(), image.getHeight(), type); 59 to.getGraphics().drawImage(image, 0, 0, null); 60 return process(to); 61 } 62 63 @Override 64 public String toString() { 65 return "GammaImageProcessor [gamma=" + gamma + ']'; 66 } 67 } 68 No newline at end of file -
new file src/org/openstreetmap/josm/gui/layer/imagery/ImageryFilterSettings.java
diff --git a/src/org/openstreetmap/josm/gui/layer/imagery/ImageryFilterSettings.java b/src/org/openstreetmap/josm/gui/layer/imagery/ImageryFilterSettings.java new file mode 100644 index 0000000..035aa4b
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.layer.imagery; 3 4 import java.util.Arrays; 5 import java.util.List; 6 import java.util.concurrent.CopyOnWriteArrayList; 7 8 import org.openstreetmap.josm.gui.layer.ImageProcessor; 9 10 /** 11 * This class holds the filter settings for an imagery layer. 12 * @author Michael Zangl 13 * @since xxx 14 */ 15 public class ImageryFilterSettings { 16 17 protected GammaImageProcessor gammaImageProcessor = new GammaImageProcessor(); 18 protected SharpenImageProcessor sharpenImageProcessor = new SharpenImageProcessor(); 19 protected ColorfulImageProcessor collorfulnessImageProcessor = new ColorfulImageProcessor(); 20 private List<FilterChangeListener> filterChangeListeners = new CopyOnWriteArrayList<>(); 21 22 /** 23 * Returns the currently set gamma value. 24 * @return the currently set gamma value 25 */ 26 public double getGamma() { 27 return gammaImageProcessor.getGamma(); 28 } 29 30 /** 31 * Sets a new gamma value, {@code 1} stands for no correction. 32 * @param gamma new gamma value 33 */ 34 public void setGamma(double gamma) { 35 gammaImageProcessor.setGamma(gamma); 36 fireListeners(); 37 } 38 39 /** 40 * Gets the current sharpen level. 41 * @return The sharpen level. 42 */ 43 public double getSharpenLevel() { 44 return sharpenImageProcessor.getSharpenLevel(); 45 } 46 47 /** 48 * Sets the sharpen level for the layer. 49 * <code>1</code> means no change in sharpness. 50 * Values in range 0..1 blur the image. 51 * Values above 1 are used to sharpen the image. 52 * @param sharpenLevel The sharpen level. 53 */ 54 public void setSharpenLevel(double sharpenLevel) { 55 sharpenImageProcessor.setSharpenLevel((float) sharpenLevel); 56 fireListeners(); 57 } 58 59 /** 60 * Gets the colorfulness of this image. 61 * @return The colorfulness 62 */ 63 public double getColorfulness() { 64 return collorfulnessImageProcessor.getColorfulness(); 65 } 66 67 /** 68 * Sets the colorfulness of this image. 69 * 0 means grayscale. 70 * 1 means normal colorfulness. 71 * Values greater than 1 are allowed. 72 * @param colorfulness The colorfulness. 73 */ 74 public void setColorfulness(double colorfulness) { 75 collorfulnessImageProcessor.setColorfulness(colorfulness); 76 fireListeners(); 77 } 78 79 /** 80 * Gets the image processors for this setting. 81 * @return The processors in the order in which they should be applied. 82 */ 83 public List<ImageProcessor> getProcessors() { 84 return Arrays.asList(collorfulnessImageProcessor, gammaImageProcessor, sharpenImageProcessor); 85 } 86 87 /** 88 * Adds a filter change listener 89 * @param l The listener 90 */ 91 public void addFilterChangeListener(FilterChangeListener l) { 92 filterChangeListeners.add(l); 93 } 94 95 /** 96 * Removes a filter change listener 97 * @param l The listener 98 */ 99 public void removeFilterChangeListener(FilterChangeListener l) { 100 filterChangeListeners.remove(l); 101 } 102 103 private void fireListeners() { 104 for (FilterChangeListener l : filterChangeListeners) { 105 l.filterChanged(); 106 } 107 } 108 109 /** 110 * A listener that listens to filter changes 111 * @author Michael Zangl 112 * @since xxx 113 */ 114 public interface FilterChangeListener { 115 /** 116 * Invoked when the filter is changed. 117 */ 118 void filterChanged(); 119 } 120 } -
new file src/org/openstreetmap/josm/gui/layer/imagery/SharpenImageProcessor.java
diff --git a/src/org/openstreetmap/josm/gui/layer/imagery/SharpenImageProcessor.java b/src/org/openstreetmap/josm/gui/layer/imagery/SharpenImageProcessor.java new file mode 100644 index 0000000..f459d4f
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.layer.imagery; 3 4 import java.awt.image.BufferedImage; 5 import java.awt.image.ConvolveOp; 6 import java.awt.image.Kernel; 7 8 import org.openstreetmap.josm.gui.layer.ImageProcessor; 9 10 /** 11 * Sharpens or blurs the image, depending on the sharpen value. 12 * <p> 13 * A positive sharpen level means that we sharpen the image. 14 * <p> 15 * A negative sharpen level let's us blur the image. -1 is the most useful value there. 16 * 17 * @author Michael Zangl 18 */ 19 public class SharpenImageProcessor implements ImageProcessor { 20 private float sharpenLevel = 1; 21 private ConvolveOp op; 22 23 private static float[] KERNEL_IDENTITY = new float[] { 24 0, 0, 0, 25 0, 1, 0, 26 0, 0, 0 27 }; 28 29 private static float[] KERNEL_BLUR = new float[] { 30 1f / 16, 2f / 16, 1f / 16, 31 2f / 16, 4f / 16, 2f / 16, 32 1f / 16, 2f / 16, 1f / 16 33 }; 34 35 private static float[] KERNEL_SHARPEN = new float[] { 36 -.5f, -1f, -.5f, 37 -1f, 7, -1f, 38 -.5f, -1f, -.5f 39 }; 40 41 /** 42 * Gets the current sharpen level. 43 * @return The level. 44 */ 45 public float getSharpenLevel() { 46 return sharpenLevel; 47 } 48 49 /** 50 * Sets the sharpening level. 51 * @param sharpenLevel The level. Clamped to be positive or 0. 52 */ 53 public void setSharpenLevel(float sharpenLevel) { 54 if (sharpenLevel < 0) { 55 this.sharpenLevel = 0; 56 } else { 57 this.sharpenLevel = sharpenLevel; 58 } 59 60 if (this.sharpenLevel < 0.95) { 61 op = generateMixed(this.sharpenLevel, KERNEL_IDENTITY, KERNEL_BLUR); 62 } else if (this.sharpenLevel > 1.05) { 63 op = generateMixed(this.sharpenLevel - 1, KERNEL_SHARPEN, KERNEL_IDENTITY); 64 } else { 65 op = null; 66 } 67 } 68 69 private ConvolveOp generateMixed(float aFactor, float[] a, float[] b) { 70 if (a.length != 9 || b.length != 9) { 71 throw new IllegalArgumentException("Illegal kernel array length."); 72 } 73 float[] values = new float[9]; 74 for (int i = 0; i < values.length; i++) { 75 values[i] = aFactor * a[i] + (1 - aFactor) * b[i]; 76 } 77 return new ConvolveOp(new Kernel(3, 3, values), ConvolveOp.EDGE_NO_OP, null); 78 } 79 80 @Override 81 public BufferedImage process(BufferedImage image) { 82 if (op != null) { 83 return op.filter(image, null); 84 } else { 85 return image; 86 } 87 } 88 89 @Override 90 public String toString() { 91 return "SharpenImageProcessor [sharpenLevel=" + sharpenLevel + ']'; 92 } 93 } 94 No newline at end of file -
test/unit/org/openstreetmap/josm/gui/layer/ImageryLayerTest.java
diff --git a/test/unit/org/openstreetmap/josm/gui/layer/ImageryLayerTest.java b/test/unit/org/openstreetmap/josm/gui/layer/ImageryLayerTest.java index 9194941..b5ce9d4 100644
a b 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.gui.layer; 3 3 4 import static org.junit.Assert.assertEquals; 4 import static org.junit.Assert.assertNotNull; 5 import static org.junit.Assert.assertSame; 5 6 6 import org.junit. BeforeClass;7 import org.junit.Rule; 7 8 import org.junit.Test; 8 import org.openstreetmap.josm.JOSMFixture; 9 import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings; 10 import org.openstreetmap.josm.testutils.JOSMTestRules; 11 12 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 9 13 10 14 /** 11 15 * Unit tests of {@link ImageryLayer} class. … … import org.openstreetmap.josm.JOSMFixture; 13 17 public class ImageryLayerTest { 14 18 15 19 /** 16 * Setup tests20 * For creating layers 17 21 */ 18 @BeforeClass 19 public static void setUpBeforeClass() { 20 JOSMFixture.createUnitTestFixture().init(true); 21 } 22 @Rule 23 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 24 public JOSMTestRules test = new JOSMTestRules().preferences(); 22 25 23 26 /** 24 * Unit test of {@link ImageryLayer.ColorfulImageProcessor#toString} 25 * and {@link ImageryLayer.GammaImageProcessor#toString()}. 26 * and {@link ImageryLayer.SharpenImageProcessor#toString()}. 27 * Unit test of {@link ImageryLayer#getFilterSettings()} 27 28 */ 28 29 @Test 29 public void test ToString() {30 public void testHasSettings() { 30 31 ImageryLayer layer = TMSLayerTest.createTmsLayer(); 31 assertEquals("ColorfulImageProcessor [colorfulness=1.0]", layer.collorfulnessImageProcessor.toString());32 assert Equals("GammaImageProcessor [gamma=1.0]", layer.gammaImageProcessor.toString());33 assert Equals("SharpenImageProcessor [sharpenLevel=1.0]", layer.sharpenImageProcessor.toString());32 ImageryFilterSettings settings = layer.getFilterSettings(); 33 assertNotNull(settings); 34 assertSame(settings, layer.getFilterSettings()); 34 35 } 35 36 } -
new file test/unit/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessorTest.java
diff --git a/test/unit/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessorTest.java b/test/unit/org/openstreetmap/josm/gui/layer/imagery/ColorfulImageProcessorTest.java new file mode 100644 index 0000000..9c68244
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.layer.imagery; 3 4 import static org.junit.Assert.assertEquals; 5 import static org.junit.Assert.assertTrue; 6 7 import java.awt.Color; 8 import java.awt.Graphics2D; 9 import java.awt.image.BufferedImage; 10 11 import org.junit.Rule; 12 import org.junit.Test; 13 import org.openstreetmap.josm.testutils.JOSMTestRules; 14 15 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 16 17 /** 18 * Tests for the {@link ColorfulImageProcessor} class. 19 * @author Michael Zangl 20 * @since xxx 21 */ 22 public class ColorfulImageProcessorTest { 23 24 private static final int TEST_IMAGE_SIZE = 5; 25 26 /** 27 * No special rules 28 */ 29 @Rule 30 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 31 public JOSMTestRules test = new JOSMTestRules(); 32 33 /** 34 * Test {@link ColorfulImageProcessor#setColorfulness(double)} and {@link ColorfulImageProcessor#getColorfulness()} 35 */ 36 @Test 37 public void testSetGet() { 38 ColorfulImageProcessor processor = new ColorfulImageProcessor(); 39 40 assertEquals(1, processor.getColorfulness(), 0.001); 41 42 processor.setColorfulness(2); 43 assertEquals(2, processor.getColorfulness(), 0.001); 44 45 processor.setColorfulness(0); 46 assertEquals(0, processor.getColorfulness(), 0.001); 47 48 processor.setColorfulness(0.78); 49 assertEquals(0.78, processor.getColorfulness(), 0.001); 50 51 processor.setColorfulness(1); 52 assertEquals(1, processor.getColorfulness(), 0.001); 53 54 processor.setColorfulness(-1); 55 assertEquals(0, processor.getColorfulness(), 0.001); 56 57 processor.setColorfulness(5); 58 assertEquals(5, processor.getColorfulness(), 0.001); 59 } 60 61 /** 62 * 63 */ 64 @Test 65 public void testProcessing() { 66 for (ConversionData data : new ConversionData[] { 67 new ConversionData(Color.BLACK, 1.5, Color.BLACK), 68 new ConversionData(Color.WHITE, 0.5, Color.WHITE), 69 new ConversionData(Color.GRAY, 0, Color.GRAY), 70 new ConversionData(Color.GREEN, 1, Color.GREEN), 71 new ConversionData(Color.RED, 1, Color.RED), 72 new ConversionData(Color.BLUE, 1, Color.BLUE), 73 new ConversionData(0x908050, 0, 0x808080), 74 new ConversionData(0x908070, 1, 0x908070), 75 new ConversionData(0x908070, 2, 0x9c7c5c), 76 new ConversionData(0x908070, 2, 0x9c7c5c), 77 new ConversionData(0xf02080, 2, 0xff00ac), 78 }) { 79 for (int type : new int[] { 80 BufferedImage.TYPE_3BYTE_BGR, 81 BufferedImage.TYPE_4BYTE_ABGR, 82 BufferedImage.TYPE_4BYTE_ABGR_PRE }) { 83 assertTrue(runProcessing(data, type)); 84 } 85 } 86 } 87 88 private boolean runProcessing(ConversionData data, int type) { 89 BufferedImage image = createImage(data.getOldColor(), type); 90 91 ColorfulImageProcessor processor = new ColorfulImageProcessor(); 92 processor.setColorfulness(data.getFactor()); 93 image = processor.process(image); 94 95 for (int x = 0; x < TEST_IMAGE_SIZE; x++) { 96 for (int y = 0; y < TEST_IMAGE_SIZE; y++) { 97 Color color = new Color(image.getRGB(x, y)); 98 assertEquals(data + ":" + type + ": red", data.getExpectedColor().getRed(), color.getRed(), 1.05); 99 assertEquals(data + ":" + type + ": green", data.getExpectedColor().getGreen(), color.getGreen(), 1.05); 100 assertEquals(data + ":" + type + ": blue", data.getExpectedColor().getBlue(), color.getBlue(), 1.05); 101 } 102 } 103 return true; 104 } 105 106 private BufferedImage createImage(Color color, int type) { 107 BufferedImage image = new BufferedImage(TEST_IMAGE_SIZE, TEST_IMAGE_SIZE, type); 108 Graphics2D graphics = image.createGraphics(); 109 graphics.setColor(color); 110 graphics.fillRect(0, 0, TEST_IMAGE_SIZE, TEST_IMAGE_SIZE); 111 return image; 112 } 113 114 private static class ConversionData { 115 private final Color oldColor; 116 private final double factor; 117 private final Color expectedColor; 118 119 ConversionData(Color oldColor, double factor, Color expectedColor) { 120 super(); 121 this.oldColor = oldColor; 122 this.factor = factor; 123 this.expectedColor = expectedColor; 124 } 125 126 public ConversionData(int oldColor, double factor, int expectedColor) { 127 this(new Color(oldColor), factor, new Color(expectedColor)); 128 } 129 130 Color getOldColor() { 131 return oldColor; 132 } 133 134 double getFactor() { 135 return factor; 136 } 137 138 Color getExpectedColor() { 139 return expectedColor; 140 } 141 142 @Override 143 public String toString() { 144 return "ConversionData [oldColor=" + oldColor + ", factor=" + factor + "]"; 145 } 146 } 147 148 /** 149 * Test {@link ColorfulImageProcessor#toString()} 150 */ 151 @Test 152 public void testToString() { 153 ColorfulImageProcessor processor = new ColorfulImageProcessor(); 154 assertEquals("ColorfulImageProcessor [colorfulness=1.0]", processor.toString()); 155 } 156 } -
new file test/unit/org/openstreetmap/josm/gui/layer/imagery/GammaImageProcessorTest.java
diff --git a/test/unit/org/openstreetmap/josm/gui/layer/imagery/GammaImageProcessorTest.java b/test/unit/org/openstreetmap/josm/gui/layer/imagery/GammaImageProcessorTest.java new file mode 100644 index 0000000..05b7c2b
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.layer.imagery; 3 4 import static org.junit.Assert.assertEquals; 5 6 import org.junit.Rule; 7 import org.junit.Test; 8 import org.openstreetmap.josm.testutils.JOSMTestRules; 9 10 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 11 12 /** 13 * Tests for the {@link GammaImageProcessor} class. 14 * @author Michael Zangl 15 * @since xxx 16 */ 17 public class GammaImageProcessorTest { 18 19 /** 20 * No special rules 21 */ 22 @Rule 23 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 24 public JOSMTestRules test = new JOSMTestRules(); 25 26 /** 27 * Test {@link GammaImageProcessor#setGamma(double)} and {@link GammaImageProcessor#getGamma()} 28 */ 29 @Test 30 public void testSetGet() { 31 GammaImageProcessor processor = new GammaImageProcessor(); 32 33 assertEquals(1, processor.getGamma(), 0.001); 34 35 processor.setGamma(2); 36 assertEquals(2, processor.getGamma(), 0.001); 37 38 processor.setGamma(0); 39 assertEquals(0, processor.getGamma(), 0.001); 40 41 processor.setGamma(0.78); 42 assertEquals(0.78, processor.getGamma(), 0.001); 43 44 processor.setGamma(1); 45 assertEquals(1, processor.getGamma(), 0.001); 46 47 processor.setGamma(-1); 48 assertEquals(-1, processor.getGamma(), 0.001); 49 50 processor.setGamma(5); 51 assertEquals(5, processor.getGamma(), 0.001); 52 } 53 54 /** 55 * Test {@link GammaImageProcessor#toString()} 56 */ 57 @Test 58 public void testToString() { 59 GammaImageProcessor processor = new GammaImageProcessor(); 60 assertEquals("GammaImageProcessor [gamma=1.0]", processor.toString()); 61 } 62 } -
new file test/unit/org/openstreetmap/josm/gui/layer/imagery/SharpenImageProcessorTest.java
diff --git a/test/unit/org/openstreetmap/josm/gui/layer/imagery/SharpenImageProcessorTest.java b/test/unit/org/openstreetmap/josm/gui/layer/imagery/SharpenImageProcessorTest.java new file mode 100644 index 0000000..85eb349
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.layer.imagery; 3 4 import static org.junit.Assert.assertEquals; 5 6 import org.junit.Rule; 7 import org.junit.Test; 8 import org.openstreetmap.josm.testutils.JOSMTestRules; 9 10 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 11 12 /** 13 * Tests for the {@link SharpenImageProcessor} class. 14 * @author Michael Zangl 15 * @since xxx 16 */ 17 public class SharpenImageProcessorTest { 18 19 /** 20 * No special rules 21 */ 22 @Rule 23 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 24 public JOSMTestRules test = new JOSMTestRules(); 25 26 /** 27 * Test {@link SharpenImageProcessor#setSharpenLevel(float)} and {@link SharpenImageProcessor#getSharpenLevel()} 28 */ 29 @Test 30 public void testSetGet() { 31 SharpenImageProcessor processor = new SharpenImageProcessor(); 32 33 assertEquals(1, processor.getSharpenLevel(), 0.001); 34 35 processor.setSharpenLevel(2); 36 assertEquals(2, processor.getSharpenLevel(), 0.001); 37 38 processor.setSharpenLevel(0); 39 assertEquals(0, processor.getSharpenLevel(), 0.001); 40 41 processor.setSharpenLevel(0.78f); 42 assertEquals(0.78, processor.getSharpenLevel(), 0.001); 43 44 processor.setSharpenLevel(1); 45 assertEquals(1, processor.getSharpenLevel(), 0.001); 46 47 processor.setSharpenLevel(-1); 48 assertEquals(-1, processor.getSharpenLevel(), 0.001); 49 50 processor.setSharpenLevel(5); 51 assertEquals(5, processor.getSharpenLevel(), 0.001); 52 } 53 54 /** 55 * Test {@link SharpenImageProcessor#toString()} 56 */ 57 @Test 58 public void testToString() { 59 SharpenImageProcessor processor = new SharpenImageProcessor(); 60 assertEquals("SharpenImageProcessor [gamma=1.0]", processor.toString()); 61 } 62 }
