// Catalano Imaging Library
// The Catalano Framework
//
// Copyright © Diego Catalano, 2012-2016
// diego.catalano at live.com
//
// Copyright © Andrew Kirillov, 2007-2008
// andrew.kirillov at gmail.com
//
// This library 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 2.1 of the License, or (at your option) any later version.
//
// This library 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 GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
package Catalano.Imaging.Filters;
import Catalano.Core.IntRange;
import Catalano.Imaging.FastBitmap;
import Catalano.Imaging.IApplyInPlace;
/**
* Linear correction of RGB channels.
* The filter performs linear correction of RGB channels by mapping specified channels' input ranges to output ranges.
*
* Supported types: Grayscale, RGB.
*
Coordinate System: Matrix.
*
* @author Diego Catalano
*/
public class LevelsLinear implements IApplyInPlace{
private IntRange inRed = new IntRange(0, 255);
private IntRange inGreen = new IntRange(0, 255);
private IntRange inBlue = new IntRange(0, 255);
private IntRange inGray = new IntRange(0, 255);
private IntRange outRed = new IntRange(0, 255);
private IntRange outGreen = new IntRange(0, 255);
private IntRange outBlue = new IntRange(0, 255);
private IntRange outGray = new IntRange(0, 255);
private int[] mapRed = new int[256];
private int[] mapGreen = new int[256];
private int[] mapBlue = new int[256];
private int[] mapGray = new int[256];
/**
* Initialize a new instance of the LevelsLinear class.
*/
public LevelsLinear() {}
/**
* Get blue component's input range.
* @return Range.
*/
public IntRange getInBlue() {
return inBlue;
}
/**
* Set blue component's input range.
* @param inBlue Range.
*/
public void setInBlue(IntRange inBlue) {
this.inBlue = inBlue;
CalculateMap(inBlue, outBlue, mapBlue);
}
/**
* Get gray component's input range.
* @return Range.
*/
public IntRange getInGray() {
return inGray;
}
/**
* Set gray component's input range.
* @param inGray Range.
*/
public void setInGray(IntRange inGray) {
this.inGray = inGray;
CalculateMap(inGray, outGray, mapGray);
}
/**
* Get green component's input range.
* @return Range.
*/
public IntRange getInGreen() {
return inGreen;
}
/**
* Set green component's input range.
* @param inGreen Range.
*/
public void setInGreen(IntRange inGreen) {
this.inGreen = inGreen;
CalculateMap(inGreen, outGreen, mapGreen);
}
/**
* Get red component's input range.
* @return Range.
*/
public IntRange getInRed() {
return inRed;
}
/**
* Get red component's input range.
* @param inRed Range.
*/
public void setInRed(IntRange inRed) {
this.inRed = inRed;
CalculateMap(inRed, outRed, mapRed);
}
/**
* Get blue component's output range.
* @return Range.
*/
public IntRange getOutBlue() {
return outBlue;
}
/**
* Set blue component's output range.
* @param outBlue Range.
*/
public void setOutBlue(IntRange outBlue) {
this.outBlue = outBlue;
CalculateMap(inBlue, outBlue, mapBlue);
}
/**
* Get gray component's output range.
* @return Range.
*/
public IntRange getOutGray() {
return outGray;
}
/**
* Set gray component's output range.
* @param outGray Range.
*/
public void setOutGray(IntRange outGray) {
this.outGray = outGray;
CalculateMap(inGray, outGray, mapGray);
}
/**
* Get green component's output range.
* @return Range.
*/
public IntRange getOutGreen() {
return outGreen;
}
/**
* Set blue component's output range.
* @param outGreen Range.
*/
public void setOutGreen(IntRange outGreen) {
this.outGreen = outGreen;
CalculateMap(inGreen, outGreen, mapGreen);
}
/**
* Get red component's output range.
* @return Range.
*/
public IntRange getOutRed() {
return outRed;
}
/**
* Set red component's output range.
* @param outRed Range.
*/
public void setOutRed(IntRange outRed) {
this.outRed = outRed;
CalculateMap(inRed, outRed, mapRed);
}
/**
* Set RGB input range.
* @param inRGB Range.
*/
public void setInRGB(IntRange inRGB){
this.inRed = inRGB;
this.inGreen = inRGB;
this.inBlue = inRGB;
CalculateMap(inRGB, outRed, mapRed);
CalculateMap(inRGB, outGreen, mapGreen);
CalculateMap(inRGB, outBlue, mapBlue);
}
/**
* Set RGB output range.
* @param outRGB Range.
*/
public void setOutRGB(IntRange outRGB){
this.outRed = outRGB;
this.outGreen = outRGB;
this.outBlue = outRGB;
CalculateMap(inRed, outRGB, mapRed);
CalculateMap(inGreen, outRGB, mapGreen);
CalculateMap(inBlue, outRGB, mapBlue);
}
@Override
public void applyInPlace(FastBitmap fastBitmap){
int size = fastBitmap.getSize();
if (fastBitmap.isGrayscale()) {
CalculateMap( inGray, outGray, mapGray );
for (int i = 0; i < size; i++) {
fastBitmap.setGray(i, mapGray[fastBitmap.getGray(i)]);
}
}
else{
CalculateMap( inRed, outRed, mapRed );
CalculateMap( inGreen, outGreen, mapGreen );
CalculateMap( inBlue, outBlue, mapBlue );
for (int i = 0; i < size; i++) {
int r = mapRed[fastBitmap.getRed(i)];
int g = mapGreen[fastBitmap.getGreen(i)];
int b = mapBlue[fastBitmap.getBlue(i)];
fastBitmap.setRGB(i, r, g, b);
}
}
}
/**
* Calculate conversion map.
* @param inRange Input range.
* @param outRange Output range.
* @param map Conversion map.
*/
private void CalculateMap(IntRange inRange, IntRange outRange, int[] map){
double k = 0, b = 0;
if ( inRange.getMax() != inRange.getMin() )
{
k = (double) ( outRange.getMax() - outRange.getMin() ) / (double) ( inRange.getMax() - inRange.getMin() );
b = (double) ( outRange.getMin() ) - k * inRange.getMin();
}
for ( int i = 0; i < 256; i++ )
{
int v = (int) i;
if ( v >= inRange.getMax() )
v = outRange.getMax();
else if ( v <= inRange.getMin() )
v = outRange.getMin();
else
v = (int) ( k * v + b );
map[i] = v;
}
}
}
Ads help maintain this website.