Blame gegl/gegl-lookup.c

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