/*
 * GStreamer
 * Copyright (C) 2013 Miguel Casas-Sanchez <miguelecasassanchez@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Alternatively, the contents of this file may be used under the
 * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
 * which case the following provisions apply instead of the ones
 * mentioned above:
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

/**
 * SECTION:element-retinex
 *
 * Basic and multiscale retinex for colour image enhancement, see article:
 *
 * Rahman, Zia-ur, Daniel J. Jobson, and Glenn A. Woodell. "Multi-scale retinex for
 * color image enhancement." Image Processing, 1996. Proceedings., International
 * Conference on. Vol. 3. IEEE, 1996.
 *
 * <refsect2>
 * <title>Example launch line</title>
 * |[
 * gst-launch-1.0 videotestsrc ! decodebin ! videoconvert ! retinex ! videoconvert ! xvimagesink
 * ]|
 * </refsect2>
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "gstretinex.h"
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/imgproc/imgproc.hpp>

GST_DEBUG_CATEGORY_STATIC (gst_retinex_debug);
#define GST_CAT_DEFAULT gst_retinex_debug

using namespace cv;
/* Filter signals and args */
enum
{
  /* FILL ME */
  LAST_SIGNAL
};

enum
{
  PROP_0,
  PROP_METHOD,
  PROP_SCALES
};
typedef enum
{
  METHOD_BASIC,
  METHOD_MULTISCALE
} GstRetinexMethod;

#define DEFAULT_METHOD METHOD_BASIC
#define DEFAULT_SCALES 3

#define GST_TYPE_RETINEX_METHOD (gst_retinex_method_get_type ())
static GType
gst_retinex_method_get_type (void)
{
  static GType etype = 0;
  if (etype == 0) {
    static const GEnumValue values[] = {
      {METHOD_BASIC, "Basic retinex restoration", "basic"},
      {METHOD_MULTISCALE, "Mutiscale retinex restoration", "multiscale"},
      {0, NULL, NULL},
    };
    etype = g_enum_register_static ("GstRetinexMethod", values);
  }
  return etype;
}

G_DEFINE_TYPE (GstRetinex, gst_retinex, GST_TYPE_OPENCV_VIDEO_FILTER);
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")));

static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")));


static void gst_retinex_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_retinex_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);

static GstFlowReturn gst_retinex_transform_ip (GstOpencvVideoFilter * filter,
    GstBuffer * buff, IplImage * img);
static gboolean gst_retinex_set_caps (GstOpencvVideoFilter* btrans,
     gint in_width, gint in_height, gint in_depth, gint in_channels,
    gint out_width, gint out_height, gint out_depth, gint out_channels);

static void gst_retinex_release_all_images (GstRetinex * filter);

static gboolean gst_retinex_stop (GstBaseTransform * basesrc);

/* initialize the retinex's class */
static void
gst_retinex_class_init (GstRetinexClass * klass)
{
  GObjectClass *gobject_class = (GObjectClass *) klass;
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  GstBaseTransformClass *btrans_class = (GstBaseTransformClass *) klass;
  GstOpencvVideoFilterClass *cvbasefilter_class =
      (GstOpencvVideoFilterClass *) klass;

  gobject_class->set_property = gst_retinex_set_property;
  gobject_class->get_property = gst_retinex_get_property;

  cvbasefilter_class->cv_trans_ip_func = gst_retinex_transform_ip;
  cvbasefilter_class->cv_set_caps = gst_retinex_set_caps;

  btrans_class->stop = gst_retinex_stop;

  g_object_class_install_property (gobject_class, PROP_METHOD,
      g_param_spec_enum ("method",
          "Retinex method to use",
          "Retinex method to use",
          GST_TYPE_RETINEX_METHOD, DEFAULT_METHOD,
          (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));

  g_object_class_install_property (gobject_class, PROP_SCALES,
      g_param_spec_int ("scales", "scales",
          "Amount of gaussian filters (scales) used in multiscale retinex", 1,
          4, DEFAULT_SCALES,
          (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));

  gst_element_class_set_static_metadata (element_class,
      "Retinex image colour enhacement", "Filter/Effect/Video",
      "Multiscale retinex for colour image enhancement",
      "Miguel Casas-Sanchez <miguelecasassanchez@gmail.com>");

  gst_element_class_add_static_pad_template (element_class, &src_factory);
  gst_element_class_add_static_pad_template (element_class, &sink_factory);
}

/* initialize the new element
 * instantiate pads and add them to element
 * set pad calback functions
 * initialize instance structure
 */
static void
gst_retinex_init (GstRetinex * filter)
{
  filter->method = DEFAULT_METHOD;
  filter->scales = DEFAULT_SCALES;
  filter->current_scales = 0;
  gst_opencv_video_filter_set_in_place (GST_OPENCV_VIDEO_FILTER_CAST (filter),
      TRUE);
}


static void
gst_retinex_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstRetinex *retinex = GST_RETINEX (object);

  switch (prop_id) {
    case PROP_METHOD:
      retinex->method = g_value_get_enum (value);
      break;
    case PROP_SCALES:
      retinex->scales = g_value_get_int (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_retinex_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstRetinex *filter = GST_RETINEX (object);

  switch (prop_id) {
    case PROP_METHOD:
      g_value_set_enum (value, filter->method);
      break;
    case PROP_SCALES:
      g_value_set_int (value, filter->scales);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static gboolean
gst_retinex_set_caps (GstOpencvVideoFilter * filter, gint in_width, gint in_height,
    gint in_depth, gint in_channels, gint out_width, gint out_height,
    gint out_depth, gint out_channels)
{
  GstRetinex *retinex = GST_RETINEX (filter);
  CvSize size;

  size = cvSize (in_width, in_height);

  if (retinex->cvA)
    gst_retinex_release_all_images (retinex);

  retinex->cvA = cvCreateImage (size, IPL_DEPTH_32F, in_channels);
  retinex->cvB = cvCreateImage (size, IPL_DEPTH_32F, in_channels);
  retinex->cvC = cvCreateImage (size, IPL_DEPTH_32F, in_channels);
  retinex->cvD = cvCreateImage (size, IPL_DEPTH_32F, in_channels);

  return TRUE;
}

static gboolean
gst_retinex_stop (GstBaseTransform * basesrc)
{
  GstRetinex *filter = GST_RETINEX (basesrc);

  if (filter->cvA != NULL)
    gst_retinex_release_all_images (filter);

  g_free (filter->weights);
  filter->weights = NULL;
  g_free (filter->sigmas);
  filter->sigmas = NULL;

  return TRUE;
}

static void
gst_retinex_release_all_images (GstRetinex * filter)
{
  cvReleaseImage (&filter->cvA);
  cvReleaseImage (&filter->cvB);
  cvReleaseImage (&filter->cvC);
  cvReleaseImage (&filter->cvD);
}

static GstFlowReturn
gst_retinex_transform_ip (GstOpencvVideoFilter * filter, GstBuffer * buf,
        IplImage * img)
{
  GstRetinex *retinex = GST_RETINEX (filter);
  double sigma = 14.0;
  int gain = 128;
  int offset = 128;
  int filter_size;
  Mat icvD = cvarrToMat(retinex->cvD, false);

  /* Basic retinex restoration.  The image and a filtered image are converted
     to the log domain and subtracted.
     O = Log(I) - Log(H(I))
     where O is the output, H is a gaussian 2d filter and I is the input image. */
  if (METHOD_BASIC == retinex->method) {
    /*  Compute log image */
    cvConvert (img, retinex->cvA);
    cvLog (retinex->cvA, retinex->cvB);

    /*  Compute log of blured image */
    filter_size = (int) floor (sigma * 6) / 2;
    filter_size = filter_size * 2 + 1;

    cvConvert (img, retinex->cvD);
    GaussianBlur (icvD, icvD, Size (filter_size, filter_size), 0.0, 0.0);
    cvLog (retinex->cvD, retinex->cvC);

    /*  Compute difference */
    cvSub (retinex->cvB, retinex->cvC, retinex->cvA, NULL);

    /*  Restore */
    cvConvertScale (retinex->cvA, img, (float) gain,
        (float) offset);
  }
  /* Multiscale retinex restoration.  The image and a set of filtered images are
     converted to the log domain and subtracted from the original with some set
     of weights. Typicaly called with three equally weighted scales of fine,
     medium and wide standard deviations.
     O = Log(I) - sum_i [ wi * Log(H(I)) ]
     where O is the output, H is a gaussian 2d filter and I is the input image
     sum_i means summatory on var i with i in [0..scales) and wi are the weights */
  else if (METHOD_MULTISCALE == retinex->method) {
    int i;

    /* allocate or reallocate the weights and sigmas according to scales */
    if (retinex->current_scales != retinex->scales || !retinex->sigmas) {
      retinex->weights =
          (double *) g_realloc (retinex->weights,
          sizeof (double) * retinex->scales);
      retinex->sigmas =
          (double *) g_realloc (retinex->sigmas,
          sizeof (double) * retinex->scales);
      for (i = 0; i < retinex->scales; i++) {
        retinex->weights[i] = 1.0 / (double) retinex->scales;
        retinex->sigmas[i] = 10.0 + 4.0 * (double) retinex->scales;
      }
      retinex->current_scales = retinex->scales;
    }

    /*  Compute log image */
    cvConvert (img, retinex->cvA);
    cvLog (retinex->cvA, retinex->cvB);

    /*  Filter at each scale */
    for (i = 0; i < retinex->scales; i++) {
      filter_size = (int) floor (retinex->sigmas[i] * 6) / 2;
      filter_size = filter_size * 2 + 1;

      cvConvert (img, retinex->cvD);
      GaussianBlur (icvD, icvD, Size (filter_size, filter_size), 0.0, 0.0);
      cvLog (retinex->cvD, retinex->cvC);

      /*  Compute weighted difference */
      cvScale (retinex->cvC, retinex->cvC, retinex->weights[i], 0.0);
      cvSub (retinex->cvB, retinex->cvC, retinex->cvB, NULL);
    }

    /*  Restore */
    cvConvertScale (retinex->cvB, img, (float) gain,
        (float) offset);
  }

  return GST_FLOW_OK;
}

/* entry point to initialize the plug-in
 * initialize the plug-in itself
 * register the element factories and other features
 */
gboolean
gst_retinex_plugin_init (GstPlugin * plugin)
{
  /* debug category for fltering log messages
   *
   */
  GST_DEBUG_CATEGORY_INIT (gst_retinex_debug, "retinex",
      0, "Multiscale retinex for colour image enhancement");

  return gst_element_register (plugin, "retinex", GST_RANK_NONE,
      GST_TYPE_RETINEX);
}
