| /** |
| * 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; |
| } |
| } |