package de.eisfeldj.augendiagnosefx.fxelements; import de.eisfeldj.augendiagnosefx.util.imagefile.ImageUtil; import de.eisfeldj.augendiagnosefx.util.imagefile.ImageUtil.Resolution; import de.eisfeldj.augendiagnosefx.util.imagefile.JpegMetadata; import javafx.scene.image.Image; import javafx.scene.paint.Color; /** * Pane containing an image that can be resized and can display overlays. */ public class OverlayImageView extends SizableImageView { /** * The limiting value of contrast (to avoid infinity or gray). */ private static final float CONTRAST_LIMIT = 0.98f; /** * The current overlay displayed. */ private Integer mOverlayType; /** * The current overlay color displayed. */ private Color mOverlayColor; /** * The current brightness of the image. */ private float mBrightness = 0; /** * The current contrast of the image. */ private float mContrast = 1; /** * The current saturation of the image. */ private float mSaturation = 1; /** * The current color temperature of the image. */ private float mColorTemperature = 0; /** * The current resolution of the image - used to adapt zoomFactor if resolution changes. */ private Resolution mCurrentResolution = Resolution.NORMAL; /** * The current image width - used to adapt zoomFactor if resolution changes. */ private double mCurrentImageWidth; /** * Display the overlay. * * @param newOverlayType * The overlay type to be displayed. * @param newOverlayColor * The color of the overlay. * @param resolution * Indicator of the resolution of the image. */ public final void displayOverlay(final Integer newOverlayType, final Color newOverlayColor, final Resolution resolution) { mOverlayType = newOverlayType; mOverlayColor = newOverlayColor; mCurrentResolution = resolution; redisplay(mCurrentResolution); } /** * Change color settings. * * @param newBrightness * The brightness * @param newContrast * The contrast from slider * @param newSaturation * The saturation from slider * @param newColorTemperature * The color temperature * @param resolution * Indicator of the resolution of the image. */ public final void setColorSettings(final Float newBrightness, final Float newContrast, final Float newSaturation, final Float newColorTemperature, final Resolution resolution) { if (newBrightness != null) { mBrightness = newBrightness; } if (newContrast != null) { mContrast = seekbarContrastToStoredContrast(newContrast); } if (newSaturation != null) { mSaturation = seekbarSaturationToStoredSaturation(newSaturation); } if (newColorTemperature != null) { mColorTemperature = newColorTemperature; } redisplay(resolution); } /** * Initialize the color settings before displaying the image. * * @param newBrightness * The brightness * @param newContrast * The contrast from metadata * @param newSaturation * The saturation from metadata * @param newColorTemperature * The color temperature */ public final void initializeColorSettings(final float newBrightness, final float newContrast, final float newSaturation, final float newColorTemperature) { mBrightness = newBrightness; mContrast = newContrast; mSaturation = newSaturation; mColorTemperature = newColorTemperature; } /** * Redisplay. (Can be used to switch between non-thumbnail and thumbnail view. * * @param resolution * Indicator of the resolution of the image. */ public final void redisplay(final Resolution resolution) { Image newImage = ImageUtil.getImageForDisplay(getEyePhoto(), mOverlayType, mOverlayColor, mBrightness, mContrast, mSaturation, mColorTemperature, resolution); if (resolution != mCurrentResolution) { multiplyZoomProperty(mCurrentImageWidth / newImage.getWidth()); mCurrentImageWidth = newImage.getWidth(); mCurrentResolution = resolution; } getImageView().setImage(newImage); } /* * Override in order to ensure that brightness/contrast are kept in case sliders have been initialized from * metadata. * * (non-Javadoc) * * @see de.eisfeldj.augendiagnosefx.fxelements.SizableImageView#displayImage(javafx.scene.image.Image) */ @Override protected final void displayImage(final Image image) { Image enhancedImage = ImageUtil.getImageForDisplay(getEyePhoto(), mOverlayType, mOverlayColor, mBrightness, mContrast, mSaturation, mColorTemperature, Resolution.NORMAL); mCurrentResolution = Resolution.NORMAL; mCurrentImageWidth = enhancedImage.getWidth(); super.displayImage(enhancedImage); } @Override public final void setImage(final JpegMetadata metadata, final Image image) { super.setImage(metadata, image); mCurrentResolution = Resolution.NORMAL; mCurrentImageWidth = image.getWidth(); } /** * Convert contrast from (-1,1) scale to (0,infty) scale. * * @param seekbarContrast * the contrast on (-1,1) scale. * @return the contrast on (0,infty) scale. */ public static float seekbarContrastToStoredContrast(final float seekbarContrast) { float contrastImd = (float) (Math.asin(seekbarContrast) * 2 / Math.PI); return 2f / (1f - contrastImd * CONTRAST_LIMIT) - 1f; } /** * Convert contrast from (0,infty) scale to (-1,1) scale. * * @param storedContrast * the contrast on (0,infty) scale. * @return the contrast on (-1,1) scale. */ public static float storedContrastToSeekbarContrast(final float storedContrast) { float contrastImd = (1f - 2f / (storedContrast + 1f)) / CONTRAST_LIMIT; return (float) Math.sin(Math.PI * contrastImd / 2); } /** * Convert saturation from (-1,1) scale to (1/3,infty) scale. * * @param seekbarSaturation * the saturation on (-1,1) scale. * @return the saturation on (1/3,infty) scale. */ public static float seekbarSaturationToStoredSaturation(final float seekbarSaturation) { return 4f / 3 / (1f - seekbarSaturation * CONTRAST_LIMIT) - 1f / 3; // MAGIC_NUMBER } /** * Convert saturation from (0,infty) scale to (-1,1) scale. * * @param storedSaturation * the saturation on (0,infty) scale. * @return the saturation on (-1,1) scale. */ public static float storedSaturationToSeekbarSaturation(final float storedSaturation) { return (1f - 4f / 3 / (storedSaturation + 1f / 3)) / CONTRAST_LIMIT; // MAGIC_NUMBER } /** * Clone the contents from another instance. * * @param view The other instance. */ public void cloneContents(final OverlayImageView view) { super.cloneContents(view); mOverlayType = view.mOverlayType; mOverlayColor = view.mOverlayColor; mCurrentResolution = view.mCurrentResolution; mBrightness = view.mBrightness; mContrast = view.mContrast; mSaturation = view.mSaturation; mColorTemperature = view.mColorTemperature; } }