Package org.jwildfire.transform

Source Code of org.jwildfire.transform.HDRComposeTransformer$MergeModeEditor

/*
  JWildfire - an image and animation processor written in Java
  Copyright (C) 1995-2011 Andreas Maschke

  This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
  General Public License as published by the Free Software Foundation; either version 2.1 of the
  License, or (at your option) any later version.
  This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License along with this software;
  if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jwildfire.transform;

import org.jwildfire.base.Property;
import org.jwildfire.base.PropertyCategory;
import org.jwildfire.base.mathlib.MathLib;
import org.jwildfire.image.SimpleHDRImage;
import org.jwildfire.image.WFImage;
import org.jwildfire.swing.Buffer;
import org.jwildfire.swing.Buffer.BufferType;
import org.jwildfire.swing.HDRImageBufferComboBoxEditor;

import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor;

public class HDRComposeTransformer extends Transformer {
  public enum MergeMode {
    ADD, BLUE, DARKEN, GREEN, HSL_ADD, LIGHTEN, MULTIPLY, NORMAL, RED, SUBTRACT
  }

  @Property(description = "Merge mode", editorClass = MergeModeEditor.class)
  private MergeMode mergeMode = MergeMode.NORMAL;
  @Property(category = PropertyCategory.PRIMARY, description = "Foreground image", editorClass = HDRImageBufferComboBoxEditor.class)
  private Buffer foreground;
  @Property(category = PropertyCategory.PRIMARY, description = "Foreground transparency")
  private double transparency = 0.0;
  @Property(category = PropertyCategory.PRIMARY, description = "Foreground intensity")
  private double intensity = 1.0;

  @Override
  protected void performImageTransformation(WFImage pImg) {
    SimpleHDRImage fgImg = foreground.getHDRImage();
    SimpleHDRImage bgImg = (SimpleHDRImage) pImg;
    if ((fgImg.getImageWidth() != bgImg.getImageWidth()) || (fgImg.getImageHeight() != bgImg.getImageHeight())) {
      throw new IllegalArgumentException();
    }
    SimpleHDRImage res = new SimpleHDRImage(fgImg.getImageWidth(), fgImg.getImageHeight());
    float fgRGB[] = new float[3];
    float bgRGB[] = new float[3];
    float r, g, b;
    float trans = (float) transparency * 0.01f;
    if (trans < 0.0f) {
      trans = 0.0f;
    }
    else if (trans > 1.0f) {
      trans = 1.0f;
    }
    float invTrans = 1.0f - trans;
    float fgScale = (float) intensity;
    float bgScale = (float) intensity;
    float fgRed, fgGreen, fgBlue;
    float bgRed, bgGreen, bgBlue;
    float mergedRed, mergedGreen, mergedBlue;
    HSLTransformer fgHSL = new HSLTransformer();
    HSLTransformer bgHSL = new HSLTransformer();
    HSLTransformer mergedHSL = new HSLTransformer();

    float lum[] = new float[2];
    fgImg.getMinMaxLum(lum);
    float fgLumMin = lum[0];
    float fgLumMax = lum[1];
    if ((fgLumMax - fgLumMin) < MathLib.EPSILON) {
      fgLumMax = fgLumMin + (float) MathLib.EPSILON;
    }
    bgImg.getMinMaxLum(lum);
    float bgLumMin = lum[0];
    float bgLumMax = lum[1];
    if ((bgLumMax - bgLumMin) < MathLib.EPSILON) {
      bgLumMax = bgLumMin + (float) MathLib.EPSILON;
    }
    bgScale *= (fgLumMax - fgLumMin) / (bgLumMax - bgLumMin);
    for (int i = 0; i < fgImg.getImageHeight(); i++) {
      for (int j = 0; j < fgImg.getImageWidth(); j++) {
        fgImg.getRGBValues(fgRGB, j, i);
        fgRed = fgRGB[0] * fgScale;
        fgGreen = fgRGB[1] * fgScale;
        fgBlue = fgRGB[2] * fgScale;
        bgRed = bgRGB[0] * bgScale;
        bgGreen = bgRGB[1] * bgScale;
        bgBlue = bgRGB[2] * bgScale;
        bgImg.getRGBValues(bgRGB, j, i);
        switch (mergeMode) {
          case MULTIPLY:
            mergedRed = fgRed * bgRed;
            mergedGreen = fgGreen * bgGreen;
            mergedBlue = fgBlue * bgBlue;
            break;
          case ADD:
            mergedRed = (fgRed + bgRed) * 0.5f;
            mergedGreen = (fgGreen + bgGreen) * 0.5f;
            mergedBlue = (fgBlue + bgBlue) * 0.5f;
            break;
          case SUBTRACT:
            mergedRed = bgRed - fgRed;
            if (mergedRed < 0.0f) {
              mergedRed = 0.0f;
            }
            mergedGreen = bgGreen - fgGreen;
            if (mergedGreen < 0.0f) {
              mergedGreen = 0.0f;
            }
            mergedBlue = bgBlue - fgBlue;
            if (mergedBlue < 0.0f) {
              mergedBlue = 0.0f;
            }
            break;
          case RED:
            mergedRed = fgRed;
            mergedGreen = bgGreen;
            mergedBlue = bgBlue;
            break;
          case GREEN:
            mergedRed = bgRed;
            mergedGreen = fgGreen;
            mergedBlue = bgBlue;
            break;
          case BLUE:
            mergedRed = bgRed;
            mergedGreen = bgGreen;
            mergedBlue = fgBlue;
            break;
          case LIGHTEN: {
            float fgLum = SimpleHDRImage.calcLum(fgRed, fgGreen, fgBlue);
            float bgLum = SimpleHDRImage.calcLum(bgRed, bgGreen, bgBlue);
            if (fgLum > bgLum) {
              mergedRed = fgRed;
              mergedGreen = fgGreen;
              mergedBlue = fgBlue;
            }
            else {
              mergedRed = bgRed;
              mergedGreen = bgGreen;
              mergedBlue = bgBlue;
            }
          }
            break;
          case DARKEN: {
            float fgLum = SimpleHDRImage.calcLum(fgRed, fgGreen, fgBlue);
            float bgLum = SimpleHDRImage.calcLum(bgRed, bgGreen, bgBlue);
            if (fgLum < bgLum) {
              mergedRed = fgRed;
              mergedGreen = fgGreen;
              mergedBlue = fgBlue;
            }
            else {
              mergedRed = bgRed;
              mergedGreen = bgGreen;
              mergedBlue = bgBlue;
            }
          }
            break;
          case HSL_ADD:
            fgHSL.setRGB(fgRed, fgGreen, fgBlue);
            bgHSL.setRGB(bgRed, bgGreen, bgBlue);
            mergedHSL.setHSL(fgHSL.getHue() + bgHSL.getHue(), fgHSL.getSaturation() + bgHSL.getSaturation(), fgHSL.getLuminosity() + bgHSL.getLuminosity(), fgHSL.getAmp());
            mergedRed = mergedHSL.getRed();
            mergedGreen = mergedHSL.getGreen();
            mergedBlue = mergedHSL.getBlue();
            break;
          default:
            mergedRed = fgRed;
            mergedGreen = fgGreen;
            mergedBlue = fgBlue;
            break;
        }
        r = mergedRed * invTrans + bgRed * trans;
        g = mergedGreen * invTrans + bgGreen * trans;
        b = mergedBlue * invTrans + bgBlue * trans;
        res.setRGB(j, i, r, g, b);
      }
    }

    ((SimpleHDRImage) pImg).assignImage(res);
  }

  @Override
  public void initDefaultParams(WFImage pImg) {
    mergeMode = MergeMode.NORMAL;
  }

  public MergeMode getMergeMode() {
    return mergeMode;
  }

  public void setMergeMode(MergeMode mergeMode) {
    this.mergeMode = mergeMode;
  }

  public Buffer getForeground() {
    return foreground;
  }

  public void setForeground(Buffer foreground) {
    this.foreground = foreground;
  }

  public double getTransparency() {
    return transparency;
  }

  public void setTransparency(double transparency) {
    this.transparency = transparency;
  }

  @Override
  public BufferType getBufferType() {
    return BufferType.HDR_IMAGE;
  }

  @Override
  public boolean supports3DOutput() {
    return false;
  }

  @Override
  public boolean acceptsInputBufferType(BufferType pBufferType) {
    return pBufferType.equals(BufferType.HDR_IMAGE);
  }

  public double getIntensity() {
    return intensity;
  }

  public void setIntensity(double intensity) {
    this.intensity = intensity;
  }

  public class HSLTransformer {
    private float red, green, blue, amp;
    private float hue, saturation, luminosity;
    private static final float EPSILON = 0.000001f;

    private float _max(float x, float y) {
      return (((x) > (y)) ? (x) : (y));
    }

    private float _min(float x, float y) {
      return (((x) < (y)) ? (x) : (y));
    }

    public void setRGB(float pRed, float pGreen, float pBlue) {
      this.red = pRed;
      this.green = pGreen;
      this.blue = pBlue;
      this.hue = 1.0f;
      this.saturation = 0.0f;
      this.luminosity = 0.0f;
      this.amp = _max(_max(pRed, pGreen), pBlue);
      if (amp < 0.00001f) {
        return;
      }
      float r = pRed / amp;
      float g = pGreen / amp;
      float b = pBlue / amp;
      float max = _max(r, _max(g, b));
      float min = _min(r, _min(g, b));
      this.luminosity = (min + max) / 2.0f;
      if (Math.abs(this.luminosity) <= EPSILON) {
        return;
      }
      this.saturation = max - min;
      if (Math.abs(this.saturation) <= EPSILON) {
        return;
      }

      this.saturation /= ((this.luminosity) <= 0.5f) ? (min + max) : (2.0f - max - min);
      if (Math.abs(r - max) < EPSILON) {
        this.hue = ((g == min) ? 5.0f + (max - b) / (max - min) : 1.0f - (max - g) / (max - min));
      }
      else {
        if (Math.abs(g - max) < EPSILON) {
          this.hue = ((b == min) ? 1.0f + (max - r) / (max - min) : 3.0f - (max - b) / (max - min));
        }
        else {
          this.hue = ((r == min) ? 3.0f + (max - g) / (max - min) : 5.0f - (max - r) / (max - min));
        }
      }
      this.hue /= 6.0f;
    }

    private float limit_int(float pVal) {
      if (pVal < 0.0f) {
        return 0.0f;
      }
      else if (pVal > 1.0f) {
        return 1.0f;
      }
      else {
        return pVal;
      }
    }

    public void setHSL(float pHue, float pSaturation, float pLuminosity, float amp) {
      this.luminosity = limit_int(pLuminosity);
      this.saturation = limit_int(pSaturation);
      this.hue = limit_int(pHue);
      this.amp = amp;
      float v = (luminosity <= 0.5f) ? (luminosity * (1.0f + saturation))
          : (luminosity + saturation - luminosity * saturation);
      if (v <= 0) {
        this.red = 0.0f;
        this.green = 0.0f;
        this.blue = 0.0f;
        this.amp = 0.0f;
        return;
      }
      this.hue *= 6.0f;
      if (this.hue < 0.0f)
        this.hue = 0.0f;
      else if (this.hue > 6.0f)
        this.hue = 6.0f;
      float y = this.luminosity + this.luminosity - v;
      float x = y + (v - y) * (this.hue - (int) this.hue);
      float z = v - (v - y) * (this.hue - (int) this.hue);
      float r, g, b;
      switch ((int) hue) {
        case 0:
          r = v;
          g = x;
          b = y;
          break;
        case 1:
          r = z;
          g = v;
          b = y;
          break;
        case 2:
          r = y;
          g = v;
          b = x;
          break;
        case 3:
          r = y;
          g = z;
          b = v;
          break;
        case 4:
          r = x;
          g = y;
          b = v;
          break;
        case 5:
          r = v;
          g = y;
          b = z;
          break;
        default:
          r = v;
          g = y;
          b = z;
      }
      this.red = r * this.amp;
      this.green = g * this.amp;
      this.blue = b * this.amp;
    }

    public float getRed() {
      return red;
    }

    public float getGreen() {
      return green;
    }

    public float getBlue() {
      return blue;
    }

    public float getHue() {
      return hue;
    }

    public float getSaturation() {
      return saturation;
    }

    public float getLuminosity() {
      return luminosity;
    }

    public float getAmp() {
      return amp;
    }
  }

  public static class MergeModeEditor extends ComboBoxPropertyEditor {
    public MergeModeEditor() {
      super();
      setAvailableValues(new MergeMode[] { MergeMode.ADD, MergeMode.BLUE, MergeMode.DARKEN, MergeMode.GREEN, MergeMode.HSL_ADD, MergeMode.LIGHTEN, MergeMode.MULTIPLY, MergeMode.NORMAL, MergeMode.RED, MergeMode.SUBTRACT });
    }
  }

}
TOP

Related Classes of org.jwildfire.transform.HDRComposeTransformer$MergeModeEditor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.