/*
* Gray8DeblurHorizHalftone.java
*
* Created on November 3, 2007, 3:07 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*
* Copyright 2008 by Jon A. Webb
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package jjil.algorithm;
import jjil.core.Error;
import jjil.core.Gray8Image;
import jjil.core.Image;
import jjil.core.PipelineStage;
/**
* Uses halftoning to remove horizontal blur from a Gray8Image. The idea is to
* threshold the image at 0 at each pixel and add the error this introduces to
* adjacent pixels, weighting by parameters specified in the constructor.
* Depending on the weights, various kinds of blur can be removed.
* @author webb
*/
public class Gray8DeblurHorizHalftone extends PipelineStage {
int n0, n1, n2, n3, n4;
/**
* Creates a new instance of Gray8DeblurHorizHalftone. The weights specified
* are scaled so that the image average brightness should not change after
* the halftoning.
* @param n0 the weight for pixel (r,c+1)
* @param n1 the weight for pixel (r,c+2)
* @param n2 the weight for pixel (r,c+3)
* @param n3 the weight for pixel (r,c+4)
* @param n4 the weight for pixel (r,c+5)
*/
public Gray8DeblurHorizHalftone(int n0, int n1, int n2, int n3, int n4) {
// scale the weights so the sum is 8
int sum = n0 + n1 + n2 + n3 + n4;
this.n0 = 8*n0/sum;
this.n1 = 8*n1/sum;
this.n2 = 8*n2/sum;
this.n3 = 8*n3/sum;
this.n4 = 8*n4/sum;
// integer division may make the sum not quite 8. correct this
// in the weight for pixel (r,c+1)
this.n0 = 8 - (this.n0 + this.n1 + this.n2 + this.n3 + this.n4);
}
/**
* Deblurs an input Gray8Image by halftoning, spreading the error introduced
* horizontally.
* @param im Input Gray8Image.
* @throws jjil.core.Error if the input is not of type Gray8Image.
*/
public void push(Image im) throws jjil.core.Error {
if (!(im instanceof Gray8Image)) {
throw new Error(
Error.PACKAGE.ALGORITHM,
ErrorCodes.IMAGE_NOT_GRAY8IMAGE,
im.toString(),
null,
null);
}
byte[] bData = ((Gray8Image) im).getData();
for (int i=0; i<im.getHeight(); i++) {
int nRow = i * im.getWidth();
for (int j=0; j<im.getWidth(); j++) {
byte bVal = bData[nRow + j];
byte bNewVal;
if (bVal >= 0) {
bNewVal = Byte.MAX_VALUE;
} else {
bNewVal = Byte.MIN_VALUE;
}
int nDiff = bVal - bNewVal;
if (j < im.getWidth()-1) {
bData[nRow + j + 1] = (byte) Math.max(Byte.MIN_VALUE,
Math.min(Byte.MAX_VALUE, bData[nRow + j + 1] +
this.n0 * nDiff / 8));
}
if (j < im.getWidth()-2) {
bData[nRow + j + 2] = (byte) Math.max(Byte.MIN_VALUE,
Math.min(Byte.MAX_VALUE, bData[nRow + j + 2] +
this.n1 * nDiff / 8));
}
if (j < im.getWidth()-3) {
bData[nRow + j + 3] = (byte) Math.max(Byte.MIN_VALUE,
Math.min(Byte.MAX_VALUE, bData[nRow + j + 3] +
this.n2 * nDiff / 8));
}
if (j < im.getWidth()-4) {
bData[nRow + j + 4] = (byte) Math.max(Byte.MIN_VALUE,
Math.min(Byte.MAX_VALUE, bData[nRow + j + 4] +
this.n3 * nDiff / 8));
}
if (j < im.getWidth()-5) {
bData[nRow + j + 5] = (byte) Math.max(Byte.MIN_VALUE,
Math.min(Byte.MAX_VALUE, bData[nRow + j + 5] +
this.n4 * nDiff / 8));
}
}
}
super.setOutput(im);
}
}