blob: 2b8195727ef182b32728fbcbdf72dd099191af09 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.pdfbox.jbig2.image;
abstract class Filter {
/**
* Find a filter name by its type.
*
* @param type the filter type
* @return filter name
*/
public static String nameByType(final FilterType type) {
if (type == null)
throw new IllegalArgumentException("type must not be null");
return type.name();
}
/**
* Find a filter type by its name.
*
* @param name the filter name
* @return filter type
*/
public static FilterType typeByName(final String name) {
if (name == null)
throw new IllegalArgumentException("name must not be null");
return FilterType.valueOf(name);
}
/**
* Find a filter by its type.
*
* @param type the filter type
* @return the Filter
*/
public static Filter byType(final FilterType type) {
switch (type){
case Bessel :
return new Bessel();
case Blackman :
return new Blackman();
case Box :
return new Box();
case Catrom :
return new Catrom();
case Cubic :
return new Cubic();
case Gaussian :
return new Gaussian();
case Hamming :
return new Hamming();
case Hanning :
return new Hanning();
case Hermite :
return new Hermite();
case Lanczos :
return new Lanczos();
case Mitchell :
return new Mitchell();
case Point :
return new Point();
case Quadratic :
return new Quadratic();
case Sinc :
return new Sinc();
case Triangle :
return new Triangle();
}
throw new IllegalArgumentException("No filter for given type.");
}
public static final class Bessel extends Filter {
public Bessel() {
super(false, 3.2383, 1.0);
}
private double J1(final double x) {
double p, q;
int i;
final double Pone[] = {
0.581199354001606143928050809e+21, -0.6672106568924916298020941484e+20, 0.2316433580634002297931815435e+19,
-0.3588817569910106050743641413e+17, 0.2908795263834775409737601689e+15, -0.1322983480332126453125473247e+13,
0.3413234182301700539091292655e+10, -0.4695753530642995859767162166e+7, 0.270112271089232341485679099e+4
}, Qone[] = {
0.11623987080032122878585294e+22, 0.1185770712190320999837113348e+20, 0.6092061398917521746105196863e+17,
0.2081661221307607351240184229e+15, 0.5243710262167649715406728642e+12, 0.1013863514358673989967045588e+10,
0.1501793594998585505921097578e+7, 0.1606931573481487801970916749e+4, 0.1e+1
};
p = Pone[8];
q = Qone[8];
for (i = 7; i >= 0; i--) {
p = p * x * x + Pone[i];
q = q * x * x + Qone[i];
}
return p / q;
}
private double P1(final double x) {
double p, q;
int i;
final double Pone[] = {
0.352246649133679798341724373e+5, 0.62758845247161281269005675e+5, 0.313539631109159574238669888e+5,
0.49854832060594338434500455e+4, 0.2111529182853962382105718e+3, 0.12571716929145341558495e+1
}, Qone[] = {
0.352246649133679798068390431e+5, 0.626943469593560511888833731e+5, 0.312404063819041039923015703e+5,
0.4930396490181088979386097e+4, 0.2030775189134759322293574e+3, 0.1e+1
};
p = Pone[5];
q = Qone[5];
for (i = 4; i >= 0; i--) {
p = p * (8.0 / x) * (8.0 / x) + Pone[i];
q = q * (8.0 / x) * (8.0 / x) + Qone[i];
}
return p / q;
}
private double Q1(final double x) {
double p, q;
int i;
final double Pone[] = {
0.3511751914303552822533318e+3, 0.7210391804904475039280863e+3, 0.4259873011654442389886993e+3,
0.831898957673850827325226e+2, 0.45681716295512267064405e+1, 0.3532840052740123642735e-1
}, Qone[] = {
0.74917374171809127714519505e+4, 0.154141773392650970499848051e+5, 0.91522317015169922705904727e+4,
0.18111867005523513506724158e+4, 0.1038187585462133728776636e+3, 0.1e+1
};
p = Pone[5];
q = Qone[5];
for (i = 4; i >= 0; i--) {
p = p * (8.0 / x) * (8.0 / x) + Pone[i];
q = q * (8.0 / x) * (8.0 / x) + Qone[i];
}
return p / q;
}
private double BesselOrderOne(double x) {
double p, q;
if (x == 0.0)
return 0.0;
p = x;
if (x < 0.0)
x = -x;
if (x < 8.0)
return p * J1(x);
q = Math.sqrt(2.0 / (Math.PI * x))
* (P1(x) * (1.0 / Math.sqrt(2.0) * (Math.sin(x) - Math.cos(x))) - 8.0 / x * Q1(x)
* (-1.0 / Math.sqrt(2.0) * (Math.sin(x) + Math.cos(x))));
if (p < 0.0)
q = -q;
return q;
}
@Override
public double f(final double x) {
if (x == 0.0)
return Math.PI / 4.0;
return BesselOrderOne(Math.PI * x) / (2.0 * x);
}
}
public static final class Blackman extends Filter {
@Override
public double f(final double x) {
return 0.42 + 0.50 * Math.cos(Math.PI * x) + 0.08 * Math.cos(2.0 * Math.PI * x);
}
}
public static class Box extends Filter {
public Box() {
super(true, .5, 1.0);
}
public Box(final double supp) {
super(true, supp, 1.0);
}
@Override
public double f(final double x) {
if (x >= -0.5 && x < 0.5)
return 1.0;
return 0.0;
}
}
public static final class Point extends Box {
public Point() {
super(0);
}
@Override
public double fWindowed(double x) {
// don't apply windowing as we have a radius of zero.
return super.f(x);
}
}
public static final class Catrom extends Filter {
public Catrom() {
super(true, 2.0, 1.0);
}
@Override
public double f(double x) {
if (x < 0)
x = -x;
if (x < 1.0)
return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0));
if (x < 2.0)
return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x)));
return 0.0;
}
}
public static final class Cubic extends Filter {
public Cubic() {
super(false, 2.0, 1.0);
}
@Override
public double f(double x) {
if (x < 0)
x = -x;
if (x < 1.0)
return 0.5 * x * x * x - x * x + 2.0 / 3.0;
if (x < 2.0) {
x = 2.0 - x;
return 1.0 / 6.0 * x * x * x;
}
return 0.0;
}
}
public static final class Gaussian extends Filter {
public Gaussian() {
super(false, 1.25, 1.0);
}
@Override
public double f(final double x) {
return Math.exp(-2.0 * x * x) * Math.sqrt(2.0 / Math.PI);
}
}
public static final class Hamming extends Filter {
@Override
public double f(final double x) {
return 0.54 + 0.46 * Math.cos(Math.PI * x);
}
}
public static final class Hanning extends Filter {
@Override
public double f(final double x) {
return 0.5 + 0.5 * Math.cos(Math.PI * x);
}
}
public static final class Hermite extends Filter {
@Override
public double f(double x) {
if (x < 0) {
x = -x;
}
if (x < 1.0) {
return (2.0 * x - 3.0) * x * x + 1.0;
}
return 0.0;
}
}
public static final class Lanczos extends Filter {
public Lanczos() {
super(true, 3.0, 1.0);
}
@Override
public double f(double x) {
if (x < 0)
x = -x;
if (x < 3.0)
return (float) (sinc(x) * sinc(x / 3.0));
return 0.0;
}
private double sinc(double value) {
if (value != 0.0f) {
value = value * Math.PI;
return Math.sin(value) / value;
} else {
return 1.0;
}
}
}
public static final class Mitchell extends Filter {
public Mitchell() {
super(false, 2.0, 1.0);
}
@Override
public double f(double x) {
double b, c;
b = 1.0 / 3.0;
c = 1.0 / 3.0;
if (x < 0)
x = -x;
if (x < 1.0) {
x = (12.0 - 9.0 * b - 6.0 * c) * (x * x * x) + (-18.0 + 12.0 * b + 6.0 * c) * x * x + (6.0 - 2.0 * b);
return x / 6.0;
}
if (x < 2.0) {
x = (-1.0 * b - 6.0 * c) * (x * x * x) + (6.0 * b + 30.0 * c) * x * x + (-12.0 * b - 48.0 * c) * x
+ (8.0 * b + 24.0 * c);
return x / 6.0;
}
return 0.0;
}
}
public static final class Quadratic extends Filter {
public Quadratic() {
super(false, 1.5, 1.0);
}
@Override
public double f(double x) {
if (x < 0)
x = -x;
if (x < 0.5)
return 0.75 - x * x;
if (x < 1.5) {
x -= 1.5;
return 0.5 * x * x;
}
return 0.0;
}
}
public static final class Sinc extends Filter {
public Sinc() {
super(true, 4.0, 1.0);
}
@Override
public double f(double x) {
x *= Math.PI;
if (x != 0.0)
return Math.sin(x) / x;
return 1.0;
}
}
public static final class Triangle extends Filter {
@Override
public double f(double x) {
if (x < 0.0)
x = -x;
if (x < 1.0)
return 1.0 - x;
return 0.0;
}
}
/**
* is this filter cardinal? ie, does func(x) = (x==0) for integer x?
*/
final boolean cardinal;
/** radius of nonzero portion */
double support;
/** blur factor (1=normal) */
double blur;
protected Filter() {
this(true, 1.0, 1.0);
}
protected Filter(final boolean cardinal, final double support, final double blur) {
this.cardinal = cardinal;
this.support = support;
this.blur = blur;
}
public double fWindowed(double x) {
return x < -support || x > support ? 0 : f(x);
}
public abstract double f(double x);
/**
* Return the filter name.
*
* @return the filter's name
*/
public String getName() {
return getClass().getSimpleName();
}
/**
* @return the support
*/
public double getSupport() {
return support;
}
/**
* @param support the support to set
*/
public void setSupport(final double support) {
this.support = support;
}
/**
* @return the blur
*/
public double getBlur() {
return blur;
}
/**
* @param blur the blur to set
*/
public void setBlur(final double blur) {
this.blur = blur;
}
}