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 + -
显示快捷键?