blob: ebc05283c594cb5720d5209a5318080553a59640 [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.
*/
/**
* Copied and pasted from Tess4j (https://sourceforge.net/projects/tess4j/)
*/
package org.apache.tika.parser.ocr.tess4j;
import java.awt.image.BufferedImage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ImageDeskew {
private static final Logger LOG = LoggerFactory.getLogger(ImageDeskew.class);
private final BufferedImage cImage;
private final int cSteps = 200;
private double[] cSinA;
private double[] cCosA;
private double cDMin;
private int[] cHMatrix;
public ImageDeskew(BufferedImage var1) {
this.cImage = var1;
}
public double getSkewAngle() {
double var2 = 0.0D;
int var4 = 0;
this.calc();
HoughLine[] var1 = this.getTop(20);
if (var1.length < 20) {
return 0.0D;
} else {
for (int var5 = 0; var5 < 19; ++var5) {
var2 += var1[var5].alpha;
++var4;
}
return var2 / (double) var4;
}
}
private HoughLine[] getTop(int var1) {
HoughLine[] var2 = new HoughLine[var1];
for (int var3 = 0; var3 < var1; ++var3) {
var2[var3] = new HoughLine();
}
int var4;
int var5;
for (var4 = 0; var4 < this.cHMatrix.length - 1; ++var4) {
if (this.cHMatrix[var4] > var2[var1 - 1].count) {
var2[var1 - 1].count = this.cHMatrix[var4];
var2[var1 - 1].index = var4;
for (var5 = var1 - 1; var5 > 0 && var2[var5].count > var2[var5 - 1].count; --var5) {
HoughLine var7 = var2[var5];
var2[var5] = var2[var5 - 1];
var2[var5 - 1] = var7;
}
}
}
for (int var6 = 0; var6 < var1; ++var6) {
var5 = var2[var6].index / this.cSteps;
var4 = var2[var6].index - var5 * this.cSteps;
var2[var6].alpha = this.getAlpha(var4);
var2[var6].d = (double) var5 + this.cDMin;
}
return var2;
}
private void calc() {
int var1 = (int) ((double) this.cImage.getHeight() / 4.0D);
int var2 = (int) ((double) this.cImage.getHeight() * 3.0D / 4.0D);
this.init();
for (int var3 = var1; var3 < var2; ++var3) {
for (int var4 = 1; var4 < this.cImage.getWidth() - 2; ++var4) {
if (ImageUtil.isBlack(this.cImage, var4, var3) &&
!ImageUtil.isBlack(this.cImage, var4, var3 + 1)) {
this.calc(var4, var3);
}
}
}
}
private void calc(int var1, int var2) {
for (int var7 = 0; var7 < this.cSteps - 1; ++var7) {
double var3 = (double) var2 * this.cCosA[var7] - (double) var1 * this.cSinA[var7];
int var5 = (int) (var3 - this.cDMin);
int var6 = var5 * this.cSteps + var7;
try {
this.cHMatrix[var6]++;
} catch (Exception var9) {
LOG.warn("", var9);
}
}
}
private void init() {
this.cSinA = new double[this.cSteps - 1];
this.cCosA = new double[this.cSteps - 1];
for (int var3 = 0; var3 < this.cSteps - 1; ++var3) {
double var1 = this.getAlpha(var3) * 3.141592653589793D / 180.0D;
this.cSinA[var3] = Math.sin(var1);
this.cCosA[var3] = Math.cos(var1);
}
this.cDMin = -this.cImage.getWidth();
final double cDStep = 1.0D;
final int cDCount =
(int) (2.0D * (double) (this.cImage.getWidth() + this.cImage.getHeight()) / cDStep);
this.cHMatrix = new int[cDCount * this.cSteps];
}
public double getAlpha(int var1) {
final double cAlphaStart = -20.0D;
final double cAlphaStep = 0.2D;
return cAlphaStart + (double) var1 * cAlphaStep;
}
public static class HoughLine {
public int count = 0;
public int index = 0;
public double alpha;
public double d;
public HoughLine() {
}
}
}