Blame gegl/gegl-lookup.c

Packit bc1512
/* This file is part of GEGL
Packit bc1512
 *
Packit bc1512
 * GEGL is free software; you can redistribute it and/or
Packit bc1512
 * modify it under the terms of the GNU Lesser General Public
Packit bc1512
 * License as published by the Free Software Foundation; either
Packit bc1512
 * version 3 of the License, or (at your option) any later version.
Packit bc1512
 *
Packit bc1512
 * GEGL is distributed in the hope that it will be useful,
Packit bc1512
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bc1512
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit bc1512
 * Lesser General Public License for more details.
Packit bc1512
 *
Packit bc1512
 * You should have received a copy of the GNU Lesser General Public
Packit bc1512
 * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
Packit bc1512
 *
Packit bc1512
 * Copyright 2009 Øyvind Kolås.
Packit bc1512
 */
Packit bc1512
Packit bc1512
#include "config.h"
Packit bc1512
Packit bc1512
#include <glib-object.h>
Packit bc1512
Packit bc1512
#include "gegl.h"
Packit bc1512
#include "gegl-lookup.h"
Packit bc1512
Packit bc1512
GeglLookup *
Packit bc1512
gegl_lookup_new_full (GeglLookupFunction function,
Packit bc1512
                      gpointer           data,
Packit bc1512
                      gfloat             start,
Packit bc1512
                      gfloat             end,
Packit bc1512
                      gfloat             precision)
Packit bc1512
{
Packit bc1512
  GeglLookup *lookup;
Packit bc1512
  union
Packit bc1512
  {
Packit bc1512
    float   f;
Packit bc1512
    guint32 i;
Packit bc1512
  } u;
Packit bc1512
  gint positive_min, positive_max, negative_min, negative_max;
Packit bc1512
  gint shift;
Packit bc1512
Packit bc1512
  /* normalize input parameters */
Packit bc1512
  if (start > end)
Packit bc1512
    { /* swap */
Packit bc1512
      u.f = start;
Packit bc1512
      start = end;
Packit bc1512
      end = u.f;
Packit bc1512
    }
Packit bc1512
Packit bc1512
       if (precision <= 0.000005) shift =  0; /* checked for later */
Packit bc1512
  else if (precision <= 0.000010) shift =  8;
Packit bc1512
  else if (precision <= 0.000020) shift =  9;
Packit bc1512
  else if (precision <= 0.000040) shift = 10;
Packit bc1512
  else if (precision <= 0.000081) shift = 11;
Packit bc1512
  else if (precision <= 0.000161) shift = 12;
Packit bc1512
  else if (precision <= 0.000324) shift = 14;
Packit bc1512
  else if (precision <= 0.000649) shift = 15;
Packit bc1512
  else shift = 16; /* a bit better than 8bit sRGB quality */
Packit bc1512
Packit bc1512
  /* Adjust slightly away from 0.0, saving many entries close to 0, this
Packit bc1512
   * causes lookups very close to zero to be passed directly to the
Packit bc1512
   * function instead.
Packit bc1512
   */
Packit bc1512
  if (start == 0.0)
Packit bc1512
    start = precision;
Packit bc1512
  if (end == 0.0)
Packit bc1512
    end = -precision;
Packit bc1512
Packit bc1512
  /* Compute start and */
Packit bc1512
Packit bc1512
  if (start < 0.0 || end < 0.0)
Packit bc1512
    {
Packit bc1512
      if (end < 0.0)
Packit bc1512
        {
Packit bc1512
          u.f = start;
Packit bc1512
          positive_max = u.i >> shift;
Packit bc1512
          u.f = end;
Packit bc1512
          positive_min = u.i >> shift;
Packit bc1512
          negative_min = positive_max;
Packit bc1512
          negative_max = positive_max;
Packit bc1512
        }
Packit bc1512
      else
Packit bc1512
        {
Packit bc1512
          u.f = 0 - precision;
Packit bc1512
          positive_min = u.i >> shift;
Packit bc1512
          u.f = start;
Packit bc1512
          positive_max = u.i >> shift;
Packit bc1512
Packit bc1512
          u.f = 0 + precision;
Packit bc1512
          negative_min = u.i >> shift;
Packit bc1512
          u.f = end;
Packit bc1512
          negative_max = u.i >> shift;
Packit bc1512
        }
Packit bc1512
    }
Packit bc1512
  else
Packit bc1512
    {
Packit bc1512
      u.f = start;
Packit bc1512
      positive_min = u.i >> shift;
Packit bc1512
      u.f = end;
Packit bc1512
      positive_max = u.i >> shift;
Packit bc1512
      negative_min = positive_max;
Packit bc1512
      negative_max = positive_max;
Packit bc1512
    }
Packit bc1512
Packit bc1512
  if (shift == 0) /* short circuit, do not use ranges */
Packit bc1512
    {
Packit bc1512
      positive_min = positive_max = negative_min = negative_max = 0;
Packit bc1512
    }
Packit bc1512
Packit bc1512
  if ((positive_max-positive_min) + (negative_max-negative_min) > GEGL_LOOKUP_MAX_ENTRIES)
Packit bc1512
    {
Packit bc1512
      /* Reduce the size of the cache tables to fit within the bittable
Packit bc1512
       * budget (the maximum allocation is around 2.18mb of memory
Packit bc1512
       */
Packit bc1512
Packit bc1512
      gint diff = (positive_max-positive_min) + (negative_max-negative_min) - GEGL_LOOKUP_MAX_ENTRIES;
Packit bc1512
Packit bc1512
      if (negative_max - negative_min > 0)
Packit bc1512
        {
Packit bc1512
          if (negative_max - negative_min >= diff)
Packit bc1512
            {
Packit bc1512
              negative_max -= diff;
Packit bc1512
              diff = 0;
Packit bc1512
            }
Packit bc1512
          else
Packit bc1512
            {
Packit bc1512
              diff -= negative_max - negative_min;
Packit bc1512
              negative_max = negative_min;
Packit bc1512
            }
Packit bc1512
        }
Packit bc1512
      if (diff)
Packit bc1512
        positive_max-=diff;
Packit bc1512
    }
Packit bc1512
Packit bc1512
  lookup = g_malloc0 (sizeof (GeglLookup) + sizeof (gfloat) *
Packit bc1512
                                                  ((positive_max-positive_min)+
Packit bc1512
                                                   (negative_max-negative_min)));
Packit bc1512
Packit bc1512
  lookup->positive_min = positive_min;
Packit bc1512
  lookup->positive_max = positive_max;
Packit bc1512
  lookup->negative_min = negative_min;
Packit bc1512
  lookup->negative_max = negative_max;
Packit bc1512
  lookup->shift = shift;
Packit bc1512
  lookup->function = function;
Packit bc1512
  lookup->data = data;
Packit bc1512
Packit bc1512
  return lookup;
Packit bc1512
}
Packit bc1512
Packit bc1512
GeglLookup *
Packit bc1512
gegl_lookup_new (GeglLookupFunction function,
Packit bc1512
                 gpointer           data)
Packit bc1512
{
Packit bc1512
  return gegl_lookup_new_full (function, data, 0, 1.0, 0.000010);
Packit bc1512
}
Packit bc1512
Packit bc1512
void
Packit bc1512
gegl_lookup_free (GeglLookup *lookup)
Packit bc1512
{
Packit bc1512
  g_free (lookup);
Packit bc1512
}