Back to index

tetex-bin  3.0
Public Member Functions | Static Public Member Functions | Protected Attributes | Private Member Functions | Private Attributes
SampledFunction Class Reference

#include <Function.h>

Inheritance diagram for SampledFunction:
Inheritance graph
[legend]
Collaboration diagram for SampledFunction:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 SampledFunction (Object *funcObj, Dict *dict)
virtual ~SampledFunction ()
virtual Functioncopy ()
virtual void transform (double *in, double *out)
virtual GBool isOk ()
GBool init (Dict *dict)
int getInputSize ()
int getOutputSize ()

Static Public Member Functions

static Functionparse (Object *funcObj)

Protected Attributes

int m
int n
double domain [funcMaxInputs][2]
double range [funcMaxOutputs][2]
GBool hasRange

Private Member Functions

 SampledFunction (SampledFunction *func)

Private Attributes

int sampleSize [funcMaxInputs]
double encode [funcMaxInputs][2]
double decode [funcMaxOutputs][2]
double * samples
GBool ok

Detailed Description

Definition at line 87 of file Function.h.


Constructor & Destructor Documentation

SampledFunction::SampledFunction ( Object funcObj,
Dict dict 
)

Definition at line 186 of file Function.cc.

                                                            {
  Stream *str;
  int nSamples, sampleBits;
  double sampleMul;
  Object obj1, obj2;
  Guint buf, bitMask;
  int bits;
  int s;
  int i;

  samples = NULL;
  ok = gFalse;

  //----- initialize the generic stuff
  if (!init(dict)) {
    goto err1;
  }
  if (!hasRange) {
    error(-1, "Type 0 function is missing range");
    goto err1;
  }

  //----- get the stream
  if (!funcObj->isStream()) {
    error(-1, "Type 0 function isn't a stream");
    goto err1;
  }
  str = funcObj->getStream();

  //----- Size
  if (!dict->lookup("Size", &obj1)->isArray() ||
      obj1.arrayGetLength() != m) {
    error(-1, "Function has missing or invalid size array");
    goto err2;
  }
  for (i = 0; i < m; ++i) {
    obj1.arrayGet(i, &obj2);
    if (!obj2.isInt()) {
      error(-1, "Illegal value in function size array");
      goto err3;
    }
    sampleSize[i] = obj2.getInt();
    obj2.free();
  }
  obj1.free();

  //----- BitsPerSample
  if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
    error(-1, "Function has missing or invalid BitsPerSample");
    goto err2;
  }
  sampleBits = obj1.getInt();
  sampleMul = 1.0 / (double)((1 << sampleBits) - 1);
  obj1.free();

  //----- Encode
  if (dict->lookup("Encode", &obj1)->isArray() &&
      obj1.arrayGetLength() == 2*m) {
    for (i = 0; i < m; ++i) {
      obj1.arrayGet(2*i, &obj2);
      if (!obj2.isNum()) {
       error(-1, "Illegal value in function encode array");
       goto err3;
      }
      encode[i][0] = obj2.getNum();
      obj2.free();
      obj1.arrayGet(2*i+1, &obj2);
      if (!obj2.isNum()) {
       error(-1, "Illegal value in function encode array");
       goto err3;
      }
      encode[i][1] = obj2.getNum();
      obj2.free();
    }
  } else {
    for (i = 0; i < m; ++i) {
      encode[i][0] = 0;
      encode[i][1] = sampleSize[i] - 1;
    }
  }
  obj1.free();

  //----- Decode
  if (dict->lookup("Decode", &obj1)->isArray() &&
      obj1.arrayGetLength() == 2*n) {
    for (i = 0; i < n; ++i) {
      obj1.arrayGet(2*i, &obj2);
      if (!obj2.isNum()) {
       error(-1, "Illegal value in function decode array");
       goto err3;
      }
      decode[i][0] = obj2.getNum();
      obj2.free();
      obj1.arrayGet(2*i+1, &obj2);
      if (!obj2.isNum()) {
       error(-1, "Illegal value in function decode array");
       goto err3;
      }
      decode[i][1] = obj2.getNum();
      obj2.free();
    }
  } else {
    for (i = 0; i < n; ++i) {
      decode[i][0] = range[i][0];
      decode[i][1] = range[i][1];
    }
  }
  obj1.free();

  //----- samples
  nSamples = n;
  for (i = 0; i < m; ++i)
    nSamples *= sampleSize[i];
  samples = (double *)gmalloc(nSamples * sizeof(double));
  buf = 0;
  bits = 0;
  bitMask = (1 << sampleBits) - 1;
  str->reset();
  for (i = 0; i < nSamples; ++i) {
    if (sampleBits == 8) {
      s = str->getChar();
    } else if (sampleBits == 16) {
      s = str->getChar();
      s = (s << 8) + str->getChar();
    } else if (sampleBits == 32) {
      s = str->getChar();
      s = (s << 8) + str->getChar();
      s = (s << 8) + str->getChar();
      s = (s << 8) + str->getChar();
    } else {
      while (bits < sampleBits) {
       buf = (buf << 8) | (str->getChar() & 0xff);
       bits += 8;
      }
      s = (buf >> (bits - sampleBits)) & bitMask;
      bits -= sampleBits;
    }
    samples[i] = (double)s * sampleMul;
  }
  str->close();

  ok = gTrue;
  return;

 err3:
  obj2.free();
 err2:
  obj1.free();
 err1:
  return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 338 of file Function.cc.

                                  {
  if (samples) {
    gfree(samples);
  }
}

Here is the call graph for this function:

Definition at line 344 of file Function.cc.

                                                      {
  int nSamples, i;

  memcpy(this, func, sizeof(SampledFunction));

  nSamples = n;
  for (i = 0; i < m; ++i) {
    nSamples *= sampleSize[i];
  }
  samples = (double *)gmalloc(nSamples * sizeof(double));
  memcpy(samples, func->samples, nSamples * sizeof(double));
}

Here is the call graph for this function:


Member Function Documentation

virtual Function* SampledFunction::copy ( ) [inline, virtual]

Implements Function.

Definition at line 92 of file Function.h.

{ return new SampledFunction(this); }

Here is the call graph for this function:

int Function::getInputSize ( ) [inline, inherited]

Definition at line 49 of file Function.h.

{ return m; }

Here is the caller graph for this function:

int Function::getOutputSize ( ) [inline, inherited]

Definition at line 50 of file Function.h.

{ return n; }

Here is the caller graph for this function:

GBool Function::init ( Dict dict) [inherited]

Definition at line 81 of file Function.cc.

                               {
  Object obj1, obj2;
  int i;

  //----- Domain
  if (!dict->lookup("Domain", &obj1)->isArray()) {
    error(-1, "Function is missing domain");
    goto err2;
  }
  m = obj1.arrayGetLength() / 2;
  if (m > funcMaxInputs) {
    error(-1, "Functions with more than %d inputs are unsupported",
         funcMaxInputs);
    goto err2;
  }
  for (i = 0; i < m; ++i) {
    obj1.arrayGet(2*i, &obj2);
    if (!obj2.isNum()) {
      error(-1, "Illegal value in function domain array");
      goto err1;
    }
    domain[i][0] = obj2.getNum();
    obj2.free();
    obj1.arrayGet(2*i+1, &obj2);
    if (!obj2.isNum()) {
      error(-1, "Illegal value in function domain array");
      goto err1;
    }
    domain[i][1] = obj2.getNum();
    obj2.free();
  }
  obj1.free();

  //----- Range
  hasRange = gFalse;
  n = 0;
  if (dict->lookup("Range", &obj1)->isArray()) {
    hasRange = gTrue;
    n = obj1.arrayGetLength() / 2;
    if (n > funcMaxOutputs) {
      error(-1, "Functions with more than %d outputs are unsupported",
           funcMaxOutputs);
      goto err2;
    }
    for (i = 0; i < n; ++i) {
      obj1.arrayGet(2*i, &obj2);
      if (!obj2.isNum()) {
       error(-1, "Illegal value in function range array");
       goto err1;
      }
      range[i][0] = obj2.getNum();
      obj2.free();
      obj1.arrayGet(2*i+1, &obj2);
      if (!obj2.isNum()) {
       error(-1, "Illegal value in function range array");
       goto err1;
      }
      range[i][1] = obj2.getNum();
      obj2.free();
    }
  }
  obj1.free();

  return gTrue;

 err1:
  obj2.free();
 err2:
  obj1.free();
  return gFalse;
}

Here is the call graph for this function:

Here is the caller graph for this function:

virtual GBool SampledFunction::isOk ( ) [inline, virtual]

Implements Function.

Definition at line 94 of file Function.h.

{ return ok; }
Function * Function::parse ( Object funcObj) [static, inherited]

Definition at line 36 of file Function.cc.

                                         {
  Function *func;
  Dict *dict;
  int funcType;
  Object obj1;

  if (funcObj->isStream()) {
    dict = funcObj->streamGetDict();
  } else if (funcObj->isDict()) {
    dict = funcObj->getDict();
  } else if (funcObj->isName("Identity")) {
    return new IdentityFunction();
  } else {
    error(-1, "Expected function dictionary or stream");
    return NULL;
  }

  if (!dict->lookup("FunctionType", &obj1)->isInt()) {
    error(-1, "Function type is missing or wrong type");
    obj1.free();
    return NULL;
  }
  funcType = obj1.getInt();
  obj1.free();

  if (funcType == 0) {
    func = new SampledFunction(funcObj, dict);
  } else if (funcType == 2) {
    func = new ExponentialFunction(funcObj, dict);
  } else if (funcType == 3) {
    func = new StitchingFunction(funcObj, dict);
  } else if (funcType == 4) {
    func = new PostScriptFunction(funcObj, dict);
  } else {
    error(-1, "Unimplemented function type (%d)", funcType);
    return NULL;
  }
  if (!func->isOk()) {
    delete func;
    return NULL;
  }

  return func;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void SampledFunction::transform ( double *  in,
double *  out 
) [virtual]

Implements Function.

Definition at line 357 of file Function.cc.

                                                       {
  double x;
  int e[2][funcMaxInputs];
  double efrac[funcMaxInputs];
  double s0[1 << funcMaxInputs], s1[1 << funcMaxInputs];
  int i, j, k, idx;

  // map input values into sample array
  for (i = 0; i < m; ++i) {
    x = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
        (encode[i][1] - encode[i][0]) + encode[i][0];
    if (x < 0) {
      x = 0;
    } else if (x > sampleSize[i] - 1) {
      x = sampleSize[i] - 1;
    }
    e[0][i] = (int)floor(x);
    e[1][i] = (int)ceil(x);
    efrac[i] = x - e[0][i];
  }

  // for each output, do m-linear interpolation
  for (i = 0; i < n; ++i) {

    // pull 2^m values out of the sample array
    for (j = 0; j < (1<<m); ++j) {
      idx = 0;
      for (k = m - 1; k >= 0; --k) {
       idx = idx * sampleSize[k] + e[(j >> k) & 1][k];
      }
      idx = idx * n + i;
      s0[j] = samples[idx];
    }

    // do m sets of interpolations
    for (j = 0; j < m; ++j) {
      for (k = 0; k < (1 << (m - j)); k += 2) {
       s1[k >> 1] = (1 - efrac[j]) * s0[k] + efrac[j] * s0[k+1];
      }
      memcpy(s0, s1, (1 << (m - j - 1)) * sizeof(double));
    }

    // map output value to range
    out[i] = s0[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
    if (out[i] < range[i][0]) {
      out[i] = range[i][0];
    } else if (out[i] > range[i][1]) {
      out[i] = range[i][1];
    }
  }
}

Here is the call graph for this function:


Member Data Documentation

Definition at line 105 of file Function.h.

double Function::domain[funcMaxInputs][2] [protected, inherited]

Definition at line 61 of file Function.h.

double SampledFunction::encode[funcMaxInputs][2] [private]

Definition at line 103 of file Function.h.

GBool Function::hasRange [protected, inherited]

Definition at line 64 of file Function.h.

int Function::m [protected, inherited]

Definition at line 59 of file Function.h.

int Function::n [protected, inherited]

Definition at line 59 of file Function.h.

Definition at line 107 of file Function.h.

double Function::range[funcMaxOutputs][2] [protected, inherited]

Definition at line 63 of file Function.h.

double* SampledFunction::samples [private]

Definition at line 106 of file Function.h.

Definition at line 101 of file Function.h.


The documentation for this class was generated from the following files: