Skip to main content

Contrast Example

11 replies [Last post]
Joined: 2006-03-07

I am a semi-newbie to JAI. I have been pouring over all of the examples and searching the internet like a madman. Does anyone have a clear example of how to do contrast? I have heard a lot of different methods (lookup table multiplying bands by constant, the rescale operation, etc). I am basically looking for something simple that runs very fast. I need to provide a slidebar control that will allow a user to adjust the contrast easily.

If someone could help me out here I would be eternally grateful.

Thank you.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Joined: 2010-03-08

how can i see your code? there are some strange characters, like "]]]]]]]" etc.
i really need your help :) thanks

Rafael Santos

It's not what you're looking for, but here is part of a code to change


> how can i see your code? there is some strange characters, like "]]]]]]]" etc.
> i really need your help :) thanks

* Part of the Java Image Processing Cookbook, please see
* for information on usage and distribution.
* Rafael Santos (
package howto.contrast;

import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

import display.multiple.DisplayTwoSynchronizedImages;

public class SimpleContrast
* Application starting point, open an image and apply to it a it in
JPEG with a
* compression factor.
public static void main(String[] args) throws IOException
// Open the image.
BufferedImage input = File(args[0]));
// Create a compatible output image.
BufferedImage output = new
// Get the scale factor and offset.
float scaleFactor = Float.parseFloat(args[1]);
float offset = Float.parseFloat(args[2]);
// Create an instance of the RescaleOp operator and applyt it.
RescaleOp rescale = new RescaleOp(scaleFactor, offset, null);
// Create a JFrame to display the results.
JFrame frame = new JFrame();
frame.setTitle("Contrast and brightness adjust of the image "+args[0]);
// Add to the JFrame's ContentPane an instance of
DisplayTwoSynchronizedImages, which will
// show the original and processed images, side by side.
// Set the closing operation so the application is finished.
frame.pack(); // adjust the frame size using preferred dimensions.
frame.setVisible(true); // show the frame.

To unsubscribe, e-mail:
For additional commands, e-mail:

Joined: 2004-07-12


Thanks for your code.
What's the clamp method you're referring to ?


Joined: 2006-03-07

The clamp method just makes sure the value is an integer between 0 and 255 and then converts it to a byte. Thats all... Glad the code helped. I appreciated the help that I received and that is why I return the favor my posting my code.


Joined: 2004-07-12

Ok, now I understand : all occurrences of arrays : [ i] was interpreted as "Italic" by the forum and disappeared from the source.

thanks again

Joined: 2006-04-19

the following example works also very fine and returns results incl. brightness-adjustment, very similar to photoshop "Brightness/Kontrast"...

PlanarImage contrast(PlanarImage myImage, int level, float boost) {

long beginTime = (new java.util.Date()).getTime();

// pre-adjust Brightness to set a centre for continuative contrast-modifications
if (level != 0) {
try {
if (level < -255) level = -255;
if (level > 255) level = 255;
double[] constants = {(float)level, (float)level, (float)level};
ParameterBlock pb = new ParameterBlock();
myImage = JAI.create("addconst", pb, null);
} catch (Exception e) {
return myImage;

// start contrast
try {

int numBands = myImage.getNumBands();

// bp is used to compress or pull colorrange
// bp = BoostPixel ;)
float[][][] bp = new float[numBands][2][];

// decrease contrast
if (boost < 0) {
if (boost < -127.5F) boost = -127.5F;
boost = 127.5F + boost;

float innerMax = (255.0F / 2.0F) + boost;
float innerMin = (255.0F / 2.0F) - boost;

for (int i = 0; i < numBands; i++) {
bp[!! i !!][0] = new float[] { -0.1F, 0.0F, 255.0F, 255.1F };
bp[!! i !!][1] = new float[] { 0.0F, innerMin, innerMax, 255.0F };

// increase contrast
else {
if (boost == 0.0F) boost = 0.00001F;
if (boost > 127.5F) boost = 127.5F;
boost = 127.5F - boost;

float innerMax = (255.0F / 2.0F) + boost;
float innerMin = (255.0F / 2.0F) - boost;

for (int i = 0; i < numBands; i++) {
bp[!! i !!][0] = new float[] { 0.0F, innerMin, innerMax, 255.0F };
bp[!! i !!][1] = new float[] { 0.0F, 0.0F, 255.0F, 255.0F };

long endTime = (new java.util.Date()).getTime();
System.out.println("Time to adjust contrast was " + (endTime - beginTime) + " ms");

return JAI.create("piecewise", myImage, bp);

} catch (Exception e) {
return myImage;

Joined: 2010-02-03

Can anyone please post this code somewhere else?
It is broken when seeing it from the web inside the forum, I guess it is correct in the emails.

Tks in advance

Joined: 2006-03-07

Thank you very much, that was exactly what I was looking for. Here is the final code that I came up with. It is a very simple way of implementing contrast that runs very quickly. I hope others can use it:

public static PlanarImage setColor(PlanarImage source,
int red, int green, int blue,
float contrast,
float brightness)
// Time the process for performance
long beginTime = (new java.util.Date()).getTime();

// Setup the parameter block for the source image and
// the three parameters for the mean operation
ParameterBlock mpb = new ParameterBlock();
mpb.addSource(source); // The source image
mpb.add(null); // null ROI means whole image
mpb.add(1); // check every pixel horizontally
mpb.add(1); // check every pixel vertically
// Perform the mean operation on the source image
PlanarImage meanImage = JAI.create("mean", mpb, null);
// Retrieve the mean pixel value
double[] mean = (double[])meanImage.getProperty("mean");
// Average the mean of all bands
double sum = 0.0D;
for (int i=0; i < mean.length; i++)
sum += mean[i];
int average = (int) sum / mean.length;

// Create the lookup table based on the average mean
byte[][] lut = new byte[3][256];
for (int i = 0; i < 256; i++ )
lut[0][i] = clamp((average + (int)((i - average) * contrast)) + red + (int)brightness);
lut[1][i] = clamp((average + (int)((i - average) * contrast)) + green + (int)brightness);
lut[2][i] = clamp((average + (int)((i - average) * contrast)) + blue + (int)brightness);
LookupTableJAI lookup = new LookupTableJAI(lut);
// Setup the parameter block for the lookup operation
ParameterBlock pb = new ParameterBlock();

// Calculate processing time and report
long endTime = (new java.util.Date()).getTime();
System.out.println("Time to set colors was " + (endTime - beginTime) + " ms");

// Return the resulting image
return JAI.create("lookup", pb, null);

For a 10 MP jpg image the function ran in just under 80ms on my laptop (Pentium 4 w/HT, 1.5GB Ram, 128MB Video card). That is A LOT faster than the AWT/Java 2D implementation I had before.

Again, thanks...

Todd Krebs

Joined: 2005-01-07

Often people add the brightness first and then caculate the contrast. Try it. You'll notice that when you increase the brightness by 20% and the contrast by 40% that it will get really more depth, while if you do the contrast first and then the brightness it'll just get foggy. Anyway, I'm glad I helped.

Joined: 2003-06-21

i think you can use the "rescale" method. it directly affects the contrast value.

Joined: 2005-01-07

A very, but not extremly valid option for enhancing the contrast is by simply taking the average of the RGB values and doing the following

a = (r + g + b) / 3
c = floating point value between 0 and finite, though I'd set 2 or 3 as top, where 1 = no change

r = a + (r - a) * c;
g = a + (g - a) * c;
b = a + (b - a) * c;

thats all. By specifying c > 1 you'll get more color, and < 1 it'll turn more grayish.

hope it helps.

Two variations:
- setting 'a' as the middle of your color range, so if your color ranges between 0 and 1, you'd set 'a' to 0.5. While if it was between 0 and 255, it'd be 127.
- setting a to the average of several neigbouring pixels. This would be more like a local contrast increase.

Both these options also work for grayscale, while the first mentioned does not.

edit: Added the 2 variations.