view libmpcodecs/vf_eq2.c @ 8388:45eb2d4d633c

The detection of a NetWM class window manager hints is tested before the test of a gnome class windomanager hints, since the gnome hints are outdated and replaced by the newer NetWM specification. Newer versions of Gnome support this standard, and therefore the test should be placed before the Gnome test. Windowmaker does not support NetWM and is checked after the NetWM test. In fact the new code should be placed also before the test for IceWM. Regarding other WMs such as KDE, IceWM the change is not tested. patch by Svante Signell <svante.signell@telia.com>
author arpi
date Sat, 07 Dec 2002 01:25:30 +0000
parents 916d5392dcc9
children 601ed700e1cc
line wrap: on
line source

/*
 * vf_eq2.c
 *
 * LUT-based software equalizer (brightness, contrast, gamma)
 *
 * Hampa Hug <hhug@student.ethz.ch>
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "../config.h"
#include "../mp_msg.h"

#include "img_format.h"
#include "mp_image.h"
#include "vf.h"

#ifdef USE_SETLOCALE
#include <locale.h>
#endif


typedef struct vf_priv_s {
  unsigned char *buf;
  int           buf_w;
  int           buf_h;

  double        contrast;
  double        bright;
  double        gamma;

  unsigned char lut[256];
} vf_eq2_t;


static
void create_lut (vf_eq2_t *eq2)
{
  unsigned i;
  double   c, b, g;
  double   v;

  c = eq2->contrast;
  b = eq2->bright;
  g = eq2->gamma;

  if ((g < 0.001) || (g > 1000.0)) {
    g = 1.0;
  }

  fprintf (stderr, "vf_eq2: c=%.2f b=%.2f g=%.4f\n", c, b, g);

  g = 1.0 / g;

  for (i = 0; i < 256; i++) {
    v = (double) i / 255.0;
    v = c * (v - 0.5) + 0.5 + b;

    if (v <= 0.0) {
      eq2->lut[i] = 0;
    }
    else {
      v = pow (v, g);

      if (v >= 1.0) {
        eq2->lut[i] = 255;
      }
      else {
        /* we divided by 255.0 so now we also multiply by 255.0, not
           by 256.0. "+ 0.5" ensures proper rounding */
        eq2->lut[i] = (unsigned char) (255.0 * v + 0.5);
      }
    }
  }
}

/* could inline this */
static
void process (unsigned char *dst, int dstride, unsigned char *src, int sstride,
  int w, int h, unsigned char lut[256])
{
  int i, j;

  for (j = 0; j < h; j++) {
    for (i = 0; i < w; i++) {
      dst[i] = lut[src[i]];
    }
    src += sstride;
    dst += dstride;
  }
}

static
int put_image (vf_instance_t *vf, mp_image_t *src)
{
  mp_image_t *dst;
  vf_eq2_t   *eq2;

  eq2 = vf->priv;

  if ((eq2->buf == NULL) || (eq2->buf_w != src->stride[0]) || (eq2->buf_h != src->h)) {
    eq2->buf = (unsigned char *) realloc (eq2->buf, src->stride[0] * src->h);
    eq2->buf_w = src->stride[0];
    eq2->buf_h = src->h;
  }

  dst = vf_get_image (vf->next, src->imgfmt, MP_IMGTYPE_EXPORT, 0, src->w, src->h);

  dst->stride[0] = src->stride[0];
  dst->stride[1] = src->stride[1];
  dst->stride[2] = src->stride[2];
  dst->planes[0] = vf->priv->buf;
  dst->planes[1] = src->planes[1];
  dst->planes[2] = src->planes[2];

  process (
    dst->planes[0], dst->stride[0], src->planes[0], src->stride[0],
    src->w, src->h, eq2->lut
  );

  return vf_next_put_image (vf, dst);
}

static
int control (vf_instance_t *vf, int request, void *data)
{
  vf_equalizer_t *eq;

  switch (request) {
    case VFCTRL_SET_EQUALIZER:
      eq = (vf_equalizer_t *) data;

      if (strcmp (eq->item, "gamma") == 0) {
        vf->priv->gamma = exp (log (8.0) * eq->value / 100.0);
        create_lut (vf->priv);
        return CONTROL_TRUE;
      }
      else if (strcmp (eq->item, "contrast") == 0) {
        vf->priv->contrast = (1.0 / 100.0) * (eq->value + 100);
        create_lut (vf->priv);
        return CONTROL_TRUE;
      }
      else if (strcmp (eq->item, "brightness") == 0) {
        vf->priv->bright = (1.0 / 100.0) * eq->value;
        create_lut (vf->priv);
        return CONTROL_TRUE;
      }
      break;

    case VFCTRL_GET_EQUALIZER:
      eq = (vf_equalizer_t *) data;
      if (strcmp (eq->item, "gamma") == 0) {
        eq->value = (int) (100.0 * log (vf->priv->gamma) / log (8.0));
        return CONTROL_TRUE;
      }
      else if (strcmp (eq->item, "contrast") == 0) {
        eq->value = (int) (100.0 * vf->priv->contrast) - 100;
        return CONTROL_TRUE;
      }
      else if (strcmp (eq->item, "brightness") == 0) {
        eq->value = (int) (100.0 * vf->priv->bright);
        return CONTROL_TRUE;
      }
      break;
  }

  return vf_next_control (vf, request, data);
}

static
int query_format (vf_instance_t *vf, unsigned fmt)
{
  switch (fmt) {
    case IMGFMT_YVU9:
    case IMGFMT_IF09:
    case IMGFMT_YV12:
    case IMGFMT_I420:
    case IMGFMT_IYUV:
    case IMGFMT_CLPL:
    case IMGFMT_Y800:
    case IMGFMT_Y8:
    case IMGFMT_NV12:
    case IMGFMT_444P:
    case IMGFMT_422P:
    case IMGFMT_411P:
      return vf_next_query_format (vf, fmt);
  }

  return 0;
}

static
void uninit (vf_instance_t *vf)
{
  if (vf->priv != NULL) {
    free (vf->priv->buf);
    free (vf->priv);
  }
}

static
int open (vf_instance_t *vf, char *args)
{
  vf_eq2_t *eq2;

  vf->control = control;
  vf->query_format = query_format;
  vf->put_image = put_image;
  vf->uninit = uninit;

  vf->priv = (vf_eq2_t *) malloc (sizeof (vf_eq2_t));
  eq2 = vf->priv;

  eq2->buf = NULL;
  eq2->buf_w = 0;
  eq2->buf_h = 0;

  eq2->gamma = 1.0;
  eq2->contrast = 1.0;
  eq2->bright = 0.0;

  if (args != NULL) {
#ifdef USE_SETLOCALE
    setlocale( LC_NUMERIC, "C" );
#endif
    sscanf (args, "%lf:%lf:%lf", &eq2->gamma, &eq2->contrast, &eq2->bright);
#ifdef USE_SETLOCALE
    setlocale( LC_NUMERIC, "" );
#endif
  }

  create_lut (eq2);

  return 1;
}

vf_info_t vf_info_eq2 = {
  "LUT-based software equalizer",
  "eq2",
  "Hampa Hug",
  "",
  &open
};