• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1022
  • Last Modified:

Image, washout, how

Have a JComponent with an Image.  I want to
'washout' this image and use it as a light background for
a technical graphics overlay.  The image is jpeg.
I have an idea that this is an 'alpha' adjustment but
I'm new to image processing.
My attempts with ImageFilter/ImageProducer fail.
Anyone have an example?

0
hank1
Asked:
hank1
  • 3
  • 2
  • 2
1 Solution
 
sameerjoshiCommented:
Check this site out. This is an excellant example of putting the image as a background to a JComponent with JTable on top of it. Just replace table with your component.

Have fun

http://www.codeguru.com/java/articles/177.shtml


or (Sometimes this site is down so.........)



import java.awt.*;
                         import java.awt.event.*;
                         import javax.swing.*;
                         import javax.swing.table.*;

                         public class Table
                         {
                                 public static void main(String[] args)
                                 {
                                         JFrame frame = new JFrame("Table");
                                         frame.addWindowListener( new WindowAdapter() {
                                                 public void windowClosing(WindowEvent e)
                                                 {
                                                         Window win = e.getWindow();
                                                         win.setVisible(false);
                                                         win.dispose();
                                                         System.exit(0);
                                                 }
                                         } );
                                         
                                         
                                         // Create your own sub-class of JTable rather than using anonymous class
                                         JTable table = new JTable( 15, 3 )
                                                 {
                                                         public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
                                                         {
                                                                 Component c = super.prepareRenderer( renderer, row, column);
                                                                 // We want renderer component to be transparent so background image is visible
                                                                 if( c instanceof JComponent )
                                                                         ((JComponent)c).setOpaque(false);
                                                                 return c;
                                                         }
                                         
                                                         // Hard coded value. In your sub-class add a function for this.
                                                         ImageIcon image = new ImageIcon( "codeguruwm.gif" );

                                                         public void paint( Graphics g )
                                                         {
                                                                 // First draw the background image - tiled
                                                                 Dimension d = getSize();
                                                                 for( int x = 0; x < d.width; x += image.getIconWidth() )
                                                                         for( int y = 0; y < d.height; y += image.getIconHeight() )
                                                                                 g.drawImage( image.getImage(), x, y, null, null );
                                                                 // Now let the regular paint code do it's work
                                                                 super.paint(g);
                                                         }
                                                         
                                                 };
                                         // Set the table transparent
                                         table.setOpaque(false);
                                         
                                         JScrollPane sp = new JScrollPane( table );
                                         frame.getContentPane().add( sp );
                                         
                                         frame.pack();
                                         frame.show();
                                 }
                         }
0
 
hank1Author Commented:
Thanks for the example, but the question is how to
'wash out' the image so I can use it as a background.
Fade it would be another way of putting it.
Thanks again.  Plugging the site in my links list.
0
 
JodCommented:
Another short answer...

This is some background on how it works, from "Java Expert Solutions":

Java's producer-consumer model makes it simple to create filters that provide many interesting image effects. Just to refresh your memory, an image producer provides the data for an image. An image consumer takes the image data and displays it. When you create an image from an URL, the data read from that URL serves as the image producer. When you create an image from an in-memory array, the MemoryImageSource is the image producer. To display an image, you connect an image producer to an image consumer and the image consumer displays the image. An image filter works like both a producer and a consumer. It acts like a consumer when it receives pixel data from the producer; then it acts like a producer when it sends the pixel data on to the consumer.

[In other words, a filter sits between a producer and a consumer and does something to the image when the producer passes it the data before the consumer gets the data to display it]

Have you tried using an RGBImageFilter? The following example is giving in the JDK docs:


FilteredImageSource is an implementation of the ImageProducer interface which takes an existing image and a filter object and uses them to produce image data for a new filtered version of the original image. Here is an example which filters an image by swapping the red and blue compents:

 
      Image src = getImage("doc:///demo/images/duke/T1.gif");
      ImageFilter colorfilter = new RedBlueSwapFilter();
      Image img = createImage(new FilteredImageSource(src.getSource(),
                                          colorfilter));

where RedBlueSwapFilter is:

      class RedBlueSwapFilter extends RGBImageFilter {
          public RedBlueSwapFilter() {
            // The filter's operation does not depend on the
            // pixel's location, so IndexColorModels can be
            // filtered directly.
            canFilterIndexColorModel = true;
          }

          public int filterRGB(int x, int y, int rgb) {
            return ((rgb & 0xff00ff00)
                  | ((rgb & 0xff0000) >> 16)
                  | ((rgb & 0xff) << 16));
          }
      }

This filter swaps the red and blue values - you need one that reduces the itensity of all colours in the image. You can do this by individually manipulating each Red, Green or Blue colour value or use the Aplpha channel.

There is a class GrayFilter (which extends RGBImageFilter) which can be used to greyscale an image to produce the image used on a disabled button (may work for you).

Otherwise, if you changed RedBlueSwapFilter to AlphaReducefilter you get:

      class AlphaReducefilter extends RGBImageFilter {
          public AlphaReducefilter() {
            // The filter's operation does not depend on the
            // pixel's location, so IndexColorModels can be
            // filtered directly.
            canFilterIndexColorModel = true;
          }

          public int filterRGB(int x, int y, int rgb) {
            return ( (rgb & 0x00ffffff)
                   | ( (rgb & 0xff000000) - ( (rgb & 0xff000000) / 2) ));
          }
      }

which roughly reduces the Alpha value to half what it was before, or something like that anyway. (NOTE: I have only just written this example and not actually tried this code out yet...)

As you can see, the int RGB variable consists of 4 parts:

0x means hex then the next two digits are the Alpha (giving 256 possible intensities for the Alpha channel)
Then the next two are the Red value of the pixel (giving 256 possible intensities) and the next two are the Green and the final two are the Blue
So you extract from the int rgb variable the parts of the colour you are interested in and process them separately. This is how the RedBlueSwapFilter works...


HOWEVER - there is an even easier route, once again illustrating how there always seems to be a dozen ways to skin a cat in Java.

You can use the ready made BufferedImageOp classes provided. The following example shows how:

[note the example does not actually use the ColorConvertOp - which is the one you need - but it shows you how to do it...]


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
import java.awt.geom.AffineTransform;
import java.awt.font.TextLayout;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.event.WindowAdapter;


public class ImageOps extends JApplet {

    private BufferedImage bi[];
    public static final float[] SHARPEN3x3_3 = {
        0.f, -1.f,  0.f,
        -1.f,  5.f, -1.f,
        0.f, -1.f,  0.f};

    public void init() {
        setBackground(Color.white);

        bi = new BufferedImage[4];
        String s[] = { "bld.jpg", "bld.jpg", "boat.gif", "boat.gif"};
        for ( int i = 0; i < bi.length; i++ ) {
            Image img = getToolkit().getImage("images/" + s[i]);
            try {
                MediaTracker tracker = new MediaTracker(this);
                tracker.addImage(img, 0);
                tracker.waitForID(0);
            }
            catch ( Exception e ) {}
            int iw = img.getWidth(this);
            int ih = img.getHeight(this);
            bi[i] = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_RGB);
            Graphics2D big = bi[i].createGraphics();
            big.drawImage(img,0,0,this);
        }
    }


    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_RENDERING,
                            RenderingHints.VALUE_RENDER_QUALITY);
        int w = getSize().width;
        int h = getSize().height;

        g2.setColor(Color.black);
        float[][] data = {{0.1f, 0.1f, 0.1f,    // low-pass filter
                0.1f, 0.2f, 0.1f,
                0.1f, 0.1f, 0.1f},
            SHARPEN3x3_3};

        String theDesc[] = { "Convolve LowPass", "Convolve Sharpen",
            "LookupOp", "RescaleOp"};
        for ( int i = 0; i < bi.length; i++ ) {
            int iw = bi[i].getWidth(this);
            int ih = bi[i].getHeight(this);
            int x = 0, y = 0;

            AffineTransform at = new AffineTransform();
            at.scale((w-14)/2.0/iw, (h-34)/2.0/ih);

            BufferedImageOp biop = null;
            BufferedImage bimg = new BufferedImage(iw,ih,BufferedImage.TYPE_INT_RGB);

            switch ( i ) {
            case 0 :
            case 1 : x = i==0?5:w/2+3; y = 15;
                Kernel kernel = new Kernel(3,3,data[i]);
                ConvolveOp cop = new ConvolveOp(kernel,
                                                ConvolveOp.EDGE_NO_OP,
                                                null);
                cop.filter(bi[i],bimg);
                biop = new AffineTransformOp(at,
                                             AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
                break;
            case 2 : x = 5; y = h/2+15;
                byte chlut[] = new byte[256];
                for ( int j=0;j<200 ;j++ )
                    chlut[j]=(byte)(256-j);
                ByteLookupTable blut=new ByteLookupTable(0,chlut);
                LookupOp lop = new LookupOp(blut, null);
                lop.filter(bi[i],bimg);  
                biop = new AffineTransformOp(at,
                                             AffineTransformOp.TYPE_BILINEAR);
                break;
            case 3 : x = w/2+3; y = h/2+15;
                RescaleOp rop = new RescaleOp(1.1f,20.0f, null);
                rop.filter(bi[i],bimg);
                biop = new AffineTransformOp(at,
                                             AffineTransformOp.TYPE_BILINEAR);
            }
            g2.drawImage(bimg,biop,x,y);
            TextLayout tl = new TextLayout(theDesc[i], g2.getFont(),g2.getFontRenderContext());
            tl.draw(g2, (float) x, (float) y-4);
        }
    }

    public static void main(String s[]) {
        JFrame f = new JFrame("ImageOps");
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
        });
        JApplet applet = new ImageOps();
        f.getContentPane().add("Center", applet);
        applet.init();
        f.pack();
        f.setSize(new Dimension(550,550));
        f.show();
    }


}


and full details of how to obtain the images and run the applet are at:

http://ariel.collegebdeb.qc.ca/~docs/java/Java_Tutorial/2d/images/filtering.html

Hallelujah.

Any further questions, let me know...
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
sameerjoshiCommented:
If this image is going to be same for ever, use an image editor or download one and make it fade.This is the easiest way ..i did the same and am having fun now
0
 
hank1Author Commented:
http://java.sun.com/docs/books/tutorial/2d/images/filtering.html

I'm already there.  Nice answer.  I guess I am going to
have to live this for awhile.   I can use the filters but
I don't know how to set them.  Seems those who do
are artists of some kind.  I guess I'll  hook up some sliders
and see what various things do.  There must be a tool
like that out there somewhere.

I wish I could just render the photo once but that's not the
application.  I am capturing production images for
quality control and must allow the operator to tweak.
0
 
JodCommented:
I haven't tried this out, but it should allow you to fiddle with the alpha value of images created like this, so you can see the difference.

You could do a similar thing to fiddle with the colour values of an image. For example, reduce the intensity of RGB values by a set amount to turn down an images "brightness".

[one of my previously asked questions explains filters in more detail if you want to know more about them...the link is http://www.experts-exchange.com/jsp/qShow.jsp?ta=java&qid=10211311 ]

Image src = getImage("doc:///demo/images/duke/T1.gif");
ImageFilter colorfilter = new fiddlefilter();

// completely transparent image
colorfilter.setAlphaCorrection(0);
Image img1 =
  createImage(new FilteredImageSource(src.getSource(), colorfilter));

// translucent image
colorfilter.setAlphaCorrection(130);
Image img1 =
  createImage(new FilteredImageSource(src.getSource(), colorfilter));

// completely opaque image
colorfilter.setAlphaCorrection(255);
Image img1 =
  createImage(new FilteredImageSource(src.getSource(), colorfilter));



where fiddlefilter is:

class fiddlefilter extends RGBImageFilter {
    int alphaCorrection = 0;

    public fiddlefilter() {
      // The filter's operation does not depend on the
      // pixel's location, so IndexColorModels can be
      // filtered directly.
      canFilterIndexColorModel = true;
    }

    // pass in a value between 0 and 255 for the alpha channel
    //  alpha channel controls transparency
    public setAlphaCorrection (int a) {
      if (a > 255) a = 255;
      if (a < 0) a = 0;
      // shift value over into alpha channel part of integer
      alphaCorrection = a << 24;
    }

  // removes current Alpha value and sets it to one passed in
  //  through setAlphaCorrection
    public int filterRGB(int x, int y, int rgb) {
      return ( (rgb & 0x00ffffff) | alphaCorrection);
    }
}

The key part is:

return ( (rgb & 0x00ffffff) | alphaCorrection)

This first removes the existing alpha channel values and replaces them for allpixels in the image with the one you specify in setAlphaCorrection.

Remember the rgb pixel color value is stored as 32 bits:

00000000 00000000  00000000 00000000  00000000 00000000  00000000 00000000
  Alpha Channel           Red               Green               Blue

(paste this bit somewhere else to see clearly...)
0
 
hank1Author Commented:
Thanks - especially the alpha channel mask.
Going to bed.  Thanks everyone.
0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

  • 3
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now