Skip to content

Commit

Permalink
Adds support of stitching functions (Function Type 3)
Browse files Browse the repository at this point in the history
  • Loading branch information
Borisvl committed Apr 12, 2012
1 parent 0ec6b82 commit 3a04163
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 77 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ To do:

Done:
-----
* support function type 3 rendering (stitching functions)
* support function type 4 rendering (subset of the PostScript language, specification taken from http://www.adobe.com/devnet/acrobat/pdfs/adobe_supplement_iso32000.pdf)
* support link annotations for being able to render links
* handle alternate colour spaces (colour space plus a function to be applied on the colour values)
Expand Down
22 changes: 0 additions & 22 deletions src/com/sun/pdfview/function/FunctionType0.java
Original file line number Diff line number Diff line change
Expand Up @@ -415,28 +415,6 @@ private float multicubicInterpolate(float[] encoded, int od) {
return multilinearInterpolate(encoded, od);
}

/**
* Perform a linear interpolation. Given a value x, and two points,
* (xmin, ymin), (xmax, ymax), where xmin <= x <= xmax, calculate a value
* y on the line from (xmin, ymin) to (xmax, ymax).
*
* @param x the x value of the input
* @param xmin the minimum x value
* @param ymin the minimum y value
* @param xmax the maximum x value
* @param ymax the maximum y value
* @return the y value interpolated from the given x
*/
public static float interpolate(float x, float xmin, float xmax,
float ymin, float ymax)
{
float value = (ymax - ymin) / (xmax - xmin);
value *= x - xmin;
value += ymin;

return value;
}

/**
* Get a sample based on an array of encoded values and a control
* map. For each bit in the map, if that bit is 0 the integer below
Expand Down
98 changes: 43 additions & 55 deletions src/com/sun/pdfview/function/FunctionType3.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package com.sun.pdfview.function;

import java.io.IOException;

import com.sun.pdfview.PDFObject;
import com.sun.pdfview.PDFParseException;

Expand Down Expand Up @@ -68,14 +69,11 @@
* </pre>
*/
public class FunctionType3 extends PDFFunction {

/**
* the actual samples, converted to integers. The first index is
* input values (from 0 to size[m - 1] * size[m - 2] * ... * size[0]),
* and the second is the output dimension within the sample (from 0 to n)
*/
private int[][] samples;


private PDFFunction[] functions;
private float[] bounds;
private float[] encode;

/** Creates a new instance of FunctionType3 */
protected FunctionType3() {
super(TYPE_3);
Expand Down Expand Up @@ -114,82 +112,72 @@ protected void parse(PDFObject obj) throws IOException {
throw new PDFParseException("Functions required for function type 3!");
}
PDFObject[] functionsAry = functionsObj.getArray();
int[] size = new int[functionsAry.length];
functions = new PDFFunction[functionsAry.length];
for (int i = 0; i < functionsAry.length; i++) {
size[i] = functionsAry[i].getIntValue();
functions[i] = PDFFunction.getFunction(functionsAry[i]);
}

// read the Bounds array (required)
PDFObject boundsObj = obj.getDictRef("Bounds");
if (boundsObj == null) {
throw new PDFParseException("Bounds required for function type 3!");
}
PDFObject[] boundsAry = boundsObj.getArray();
int[] size1 = new int[boundsAry.length];
bounds = new float[boundsAry.length + 2];
if (bounds.length - 2 != functions.length - 1) {
throw new PDFParseException("Bounds array must be of length " + (functions.length - 1));
}

for (int i = 0; i < boundsAry.length; i++) {
size1[i] = boundsAry[i].getIntValue();
bounds[i+1] = boundsAry[i].getFloatValue();
}
bounds[0] = getDomain(0);
bounds[bounds.length-1] = getDomain(1);

// read the encode array (required)
PDFObject encodeObj = obj.getDictRef("Encode");
if (encodeObj == null) {
throw new PDFParseException("Encode required for function type 3!");
}
PDFObject[] encodeAry = encodeObj.getArray();
float[] encode = new float[encodeAry.length];
encode = new float[encodeAry.length];
if (encode.length != 2*functions.length) {
throw new PDFParseException("Encode array must be of length " + 2*functions.length);
}
for (int i = 0; i < encodeAry.length; i++) {
encode[i] = encodeAry[i].getFloatValue();
}
throw new PDFParseException("Unsupported function type 3.");
}

/**
* Map from <i>m</i> input values to <i>n</i> output values.
* The number of inputs <i>m</i> must be exactly one half the size of the
* domain. The number of outputs should match one half the size of the
* range.
*
* @param inputs an array of <i>m</i> input values
* @param inputs an array of <i>1</i> input values
* @param outputs an array of size <i>n</i> which will be filled
* with the output values, or null to return a new array
*/
@Override
protected void doFunction(float[] inputs, int inputOffset,
float[] outputs, int outputOffset) {
// calculate the encoded values for each input
float[] encoded = new float[getNumInputs()];
// for (int i = 0; i < getNumInputs(); i++) {
// // encode -- interpolate(x<i>, domain<2i>, domain<2i + 1>,
// // encode<2i>, encode<2i + 1>)
// encoded[i] = interpolate(inputs[i + inputOffset],
// getDomain(2 * i),
// getDomain((2 * i) + 1),
// getEncode(2 * i),
// getEncode((2 * i) + 1));
//
// // clip to size of sample table -- min(max(e<i>, 0), size<i> - 1)
// encoded[i] = Math.max(encoded[i], 0);
// encoded[i] = Math.min(encoded[i], size[i] - 1);
// }
float[] outputs, int outputOffset) {

float x = inputs[inputOffset];

// do some magic
for (int i = 0; i < getNumOutputs(); i++) {
// if (getOrder() == 1) {
// outputs[i + outputOffset] = multilinearInterpolate(encoded, i);
// } else {
// outputs[i + outputOffset] = multicubicInterpolate(encoded, i);
// }
}

// now adjust the output to be within range
// for (int i = 0; i < outputs.length; i++) {
// // decode -- interpolate(r<i>, 0, 2^bps - 1,
// // decode<2i>, decode<2i + 1>)
// outputs[i + outputOffset] = interpolate(outputs[i + outputOffset],
// 0,
// (float) Math.pow(2, getBitsPerSample()) - 1,
// getDecode(2 * i),
// getDecode((2 * i) + 1));
// }
// calculate the output values
int p = bounds.length - 2;
while (x < bounds[p]) p--;
x = interpolate(x, bounds[p], bounds[p+1], encode[2*p], encode[2*p + 1]);
float[] out = functions[p].calculate(new float[]{x});
for (int i = 0; i < out.length; i++) {
outputs[i + outputOffset] = out[i];
}
}

@Override
public int getNumInputs() {
return 1;
}

@Override
public int getNumOutputs() {
return functions[0].getNumOutputs();
}
}
21 changes: 21 additions & 0 deletions src/com/sun/pdfview/function/PDFFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,27 @@ public static PDFFunction getFunction (PDFObject obj)
}

/**
* Perform a linear interpolation. Given a value x, and two points,
* (xmin, ymin), (xmax, ymax), where xmin <= x <= xmax, calculate a value
* y on the line from (xmin, ymin) to (xmax, ymax).
*
* @param x the x value of the input
* @param xmin the minimum x value
* @param ymin the minimum y value
* @param xmax the maximum x value
* @param ymax the maximum y value
* @return the y value interpolated from the given x
*/
public static float interpolate(float x, float xmin, float xmax,
float ymin, float ymax) {
float value = (ymax - ymin) / (xmax - xmin);
value *= x - xmin;
value += ymin;

return value;
}

/**
* Get the type of this function
*
* @return one of the types of function (0-4)
Expand Down

0 comments on commit 3a04163

Please sign in to comment.