?? function.cc
字號:
//========================================================================//// Function.cc//// Copyright 2001-2003 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 sampleBits; double sampleMul; Object obj1, obj2; Guint buf, bitMask; int bits; Guint s; int i; samples = NULL; sBuf = NULL; ok = gFalse; //----- initialize the generic stuff if (!init(dict)) { goto err1; } if (!hasRange) { error(-1, "Type 0 function is missing range"); goto err1; } if (m > sampledFuncMaxInputs) { error(-1, "Sampled functions with more than %d inputs are unsupported", sampledFuncMaxInputs); goto err1; } //----- buffer sBuf = (double *)gmallocn(1 << m, sizeof(double)); //----- 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(); idxMul[0] = n; for (i = 1; i < m; ++i) { idxMul[i] = idxMul[i-1] * sampleSize[i-1]; } //----- BitsPerSample if (!dict->lookup("BitsPerSample", &obj1)->isInt()) { error(-1, "Function has missing or invalid BitsPerSample"); goto err2; } sampleBits = obj1.getInt(); sampleMul = 1.0 / (pow(2.0, (double)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(); for (i = 0; i < m; ++i) { inputMul[i] = (encode[i][1] - encode[i][0]) / (domain[i][1] - domain[i][0]); } //----- 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 *)gmallocn(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); } if (sBuf) { gfree(sBuf); }}SampledFunction::SampledFunction(SampledFunction *func) { memcpy(this, func, sizeof(SampledFunction)); samples = (double *)gmallocn(nSamples, sizeof(double)); memcpy(samples, func->samples, nSamples * sizeof(double)); sBuf = (double *)gmallocn(1 << m, sizeof(double));}void SampledFunction::transform(double *in, double *out) { double x; int e[funcMaxInputs][2]; double efrac0[funcMaxInputs]; double efrac1[funcMaxInputs]; int i, j, k, idx, t; // map input values into sample array for (i = 0; i < m; ++i) { x = (in[i] - domain[i][0]) * inputMul[i] + encode[i][0]; if (x < 0) { x = 0; } else if (x > sampleSize[i] - 1) { x = sampleSize[i] - 1; } e[i][0] = (int)x; if ((e[i][1] = e[i][0] + 1) >= sampleSize[i]) { // this happens if in[i] = domain[i][1] e[i][1] = e[i][0]; } efrac1[i] = x - e[i][0]; efrac0[i] = 1 - efrac1[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 = i; for (k = 0, t = j; k < m; ++k, t >>= 1) { idx += idxMul[k] * (e[k][t & 1]); } sBuf[j] = samples[idx]; } // do m sets of interpolations for (j = 0, t = (1<<m); j < m; ++j, t >>= 1) { for (k = 0; k < t; k += 2) { sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k+1]; } } // map output value to range out[i] = sBuf[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; 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; } //----- C0 if (dict->lookup("C0", &obj1)->isArray()) { if (hasRange && obj1.arrayGetLength() != n) { error(-1, "Function's C0 array is wrong length"); goto err2; } n = obj1.arrayGetLength(); 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(); } } else { if (hasRange && n != 1) { error(-1, "Function's C0 array is wrong length"); goto err2; } n = 1; c0[0] = 0; } obj1.free(); //----- C1 if (dict->lookup("C1", &obj1)->isArray()) { 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(); } } else { if (n != 1) { error(-1, "Function's C1 array is wrong length"); goto err2; } c1[0] = 1; } 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(); ok = gTrue; return; err3: obj2.free(); err2: obj1.free(); err1: return;}ExponentialFunction::~ExponentialFunction() {}ExponentialFunction::ExponentialFunction(ExponentialFunction *func) { memcpy(this, func, sizeof(ExponentialFunction));}void ExponentialFunction::transform(double *in, double *out) { double x; int i; if (in[0] < domain[0][0]) { x = domain[0][0]; } else if (in[0] > domain[0][1]) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -