function.cc

来自「source code: Covert TXT to PDF」· CC 代码 · 共 1,522 行 · 第 1/3 页

CC
1,522
字号
//========================================================================//// Function.cc//// Copyright 2001-2002 Glyph & Cog, LLC////========================================================================#include <aconf.h>#ifdef USE_GCC_PRAGMAS#pragma implementation#endif#include <stdlib.h>#include <string.h>#include <ctype.h>#include <math.h>#include "gmem.h"#include "Object.h"#include "Dict.h"#include "Stream.h"#include "Error.h"#include "Function.h"//------------------------------------------------------------------------// Function//------------------------------------------------------------------------Function::Function() {}Function::~Function() {}Function *Function::parse(Object *funcObj) {  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;}GBool Function::init(Dict *dict) {  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;}//------------------------------------------------------------------------// IdentityFunction//------------------------------------------------------------------------IdentityFunction::IdentityFunction() {  int i;  // fill these in with arbitrary values just in case they get used  // somewhere  m = funcMaxInputs;  n = funcMaxOutputs;  for (i = 0; i < funcMaxInputs; ++i) {    domain[i][0] = 0;    domain[i][1] = 1;  }  hasRange = gFalse;}IdentityFunction::~IdentityFunction() {}void IdentityFunction::transform(double *in, double *out) {  int i;  for (i = 0; i < funcMaxOutputs; ++i) {    out[i] = in[i];  }}//------------------------------------------------------------------------// SampledFunction//------------------------------------------------------------------------SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {  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;}SampledFunction::~SampledFunction() {  if (samples) {    gfree(samples);  }}SampledFunction::SampledFunction(SampledFunction *func) {  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));}void SampledFunction::transform(double *in, double *out) {  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 = e[j & 1][m - 1];      for (k = m - 2; 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];    }  }}//------------------------------------------------------------------------// ExponentialFunction//------------------------------------------------------------------------ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {  Object obj1, obj2;  GBool hasN;  int i;  ok = gFalse;  //----- initialize the generic stuff  if (!init(dict)) {    goto err1;  }  if (m != 1) {    error(-1, "Exponential function with more than one input");    goto err1;  }  hasN = hasRange;  //----- default values  for (i = 0; i < funcMaxOutputs; ++i) {    c0[i] = 0;    c1[i] = 1;  }  //----- C0  if (dict->lookup("C0", &obj1)->isArray()) {    if (!hasN) {      n = obj1.arrayGetLength();      hasN = gTrue;    } else if (obj1.arrayGetLength() != n) {      error(-1, "Function's C0 array is wrong length");      goto err2;    }    for (i = 0; i < n; ++i) {      obj1.arrayGet(i, &obj2);      if (!obj2.isNum()) {	error(-1, "Illegal value in function C0 array");	goto err3;      }      c0[i] = obj2.getNum();      obj2.free();    }  }  obj1.free();  //----- C1  if (dict->lookup("C1", &obj1)->isArray()) {    if (!hasN) {      n = obj1.arrayGetLength();      hasN = gTrue;    } else if (obj1.arrayGetLength() != n) {      error(-1, "Function's C1 array is wrong length");      goto err2;    }    for (i = 0; i < n; ++i) {      obj1.arrayGet(i, &obj2);      if (!obj2.isNum()) {	error(-1, "Illegal value in function C1 array");	goto err3;      }      c1[i] = obj2.getNum();      obj2.free();    }  }  obj1.free();  //----- N (exponent)  if (!dict->lookup("N", &obj1)->isNum()) {    error(-1, "Function has missing or invalid N");    goto err2;  }  e = obj1.getNum();  obj1.free();  // this isn't supposed to happen, but I've run into (broken) PDF  // files where it does  if (!hasN) {    error(-1, "Exponential function does not define number of output values");    n = 1;  }  ok = gTrue;  return; err3:  obj2.free(); err2:  obj1.free(); err1:  return;}ExponentialFunction::~ExponentialFunction() {}ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {  memcpy(this, func, sizeof(ExponentialFunction));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?