blob: bdcdad6b647c422176b102a15ecd45200df458fa [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;
}
}