Link to home
Start Free TrialLog in
Avatar of m_adil
m_adil

asked on

Accessing pixels

How can i access pixels of an image and manipulate them (change their RGB). I think pixelGrabber does this but how? any simple working ex.

Thanks in advance.
ASKER CERTIFIED SOLUTION
Avatar of samers
samers

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of heyhey_
heyhey_

sampel code from
https://www.experts-exchange.com/questions/10242582/Making-an-image-transparent.html

this exampel changes the alpha value of all pixels that have some fixed color (makes them transparent)

/*
sample code
all you need is one image (I use duke.gif from Swing examples)
inside the current directory.
compile this example and run it - that's all.
*/
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
public class demo1 extends Container
{
  private Image bgImage;
  private Image i, i1, i2, i3;
 
  public demo1()
  {
    loadImages();
    doSomeConversion();
    buildUI();
  }
  // load one background image
  // and one sample foreground that we will manipulate
  public void loadImages()
  {  
    setBackground(Color.lightGray);
    i = Toolkit.getDefaultToolkit().getImage("duke.gif");
    bgImage = Toolkit.getDefaultToolkit().getImage("aa.jpg");
    MediaTracker tracker = new MediaTracker(this);
    tracker.addImage(i, 11);
    tracker.addImage(bgImage, 11);
    try
    {
      tracker.waitForID(11);
    } catch (Exception x)
    {
      x.printStackTrace();
    }
    System.out.println("w = " + i.getWidth(null));
    System.out.println("w = " + bgImage.getWidth(null));
  }
  // create three copies of the sampel Image with different aplha values
  public void doSomeConversion()
  {
    i1 = convertToTransparentImage(i, 0, 0);
    i2 = convertToTransparentImage(i, 0, 128);
    i3 = convertToTransparentImage(i, 0, 255);
  }  
 
  // create one background Image container
  // and add 4 Image componets on it
  public void buildUI()
  {
    setLayout(new GridLayout(1, 1));
    // try with Image background
//    ImageContainer c = new ImageContainer(bgImage);
    // or try with Panel with fixed background color
    Panel c = new Panel();
    c.setBackground(Color.cyan);
    c.setLayout(new FlowLayout());
    add(c);
    ImageContainer cc = new ImageContainer(i);
    c.add(cc);
    cc = new ImageContainer(i1);
    c.add(cc);
    cc = new ImageContainer(i2);
    c.add(cc);
    cc = new ImageContainer(i3);
    c.add(cc);
  }
 
  // your method
  public Image convertToTransparentImage(Image image, int r, int g, int b, int alpha)
  {
    return convertToTransparentImage(image, (r << 16 | r << 8 | b), alpha);
  }
  // your method with less parameters
  public Image convertToTransparentImage(Image image, int rgb, int alpha)
  {
    int w = image.getWidth(null);
    int h = image.getHeight(null);
    int[] pixels = new int[w * h];
   
    // grab all pixels with PixelGrabber
    PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);
    try
    {
      pg.grabPixels();
    } catch (Exception x)
    {
      x.printStackTrace();
    }
    // change the alpha values if needed    
    for (int i = 0; i < w * h; i++)
    {
      int col = pixels[i] & 0xffffff;
      if (col== rgb)
      {
        System.out.print(".");
        pixels[i] = col | (alpha << 24);
      }
    }
    // create new Image object
    return createImage(new MemoryImageSource(w, h, pixels, 0, w));
  }
// some double buffering code  
  private Image offImage;
  private Graphics offGraphics;
 
  public void update (Graphics g)
  {
    paint(g);
  }
  public void paint (Graphics g)
  {
    Dimension d = getSize();
    if (offImage == null || offImage.getWidth(null) != d.width || offImage.getHeight(null) != d.height)
    {
      offImage = createImage(d.width, d.height);
      offGraphics = offImage.getGraphics();
    }
   
    offGraphics.setColor(getBackground());
    offGraphics.fillRect(0, 0, d.width, d.height);
    super.paint(offGraphics);
    g.drawImage(offImage, 0, 0, null);
  }
 
  // main method
  public static void main(String args[])
  {
    Frame f = new Frame("demo");
    f.add(new demo1());
    f.setSize(500, 500);
    f.setVisible(true);
    f.addWindowListener(new WindowAdapter()
    {
      public void windowClosing(WindowEvent e)
      {
        System.exit(0);
      }
    });
  }
 
  // helper class ImageContainer class :)
  class ImageContainer extends Container
  {
    private Image image;
    public ImageContainer(Image i)
    {
      image = i;
    }
    public Dimension preferredSize()
    {
      return new Dimension(image.getWidth(null), image.getHeight(null));
    }
    public Dimension minimumSize()
    {
      return super.minimumSize();
    }
    public Dimension getMaximumSize()
    {
      return preferredSize();
    }
    public void update(Graphics g)
    {
      paint(g);
    }
    public void paint(Graphics g)
    {
      g.drawImage(image, 0, 0, null);
      super.paint(g);
    }
  }
}
Avatar of m_adil

ASKER

wow great!
Plz give me a little time to check
Avatar of m_adil

ASKER

I've tried it. u'm getting a little problem. I've grabbed pixels by getPixels() method. Now i want to get RGB value of each pixel. how to do that?
I've tried
ColorModel cm=pg.getColorModel();
but it gives me an error ** Method getColorModel() not found in java.awt.image.PixelGrabber. **

Here is my code
********************
Image img;
..... //load image from file....

            int w = img.getWidth(null);
            int h = img.getHeight(null);
            int[] pixels = new int[w*h];
            int[] pixs = new int[w*h];
            
            PixelGrabber pg = new PixelGrabber(img, 0,0, w, h, pixels, 0, w);
            ColorModel cm=pg.getColorModel();            
            try {
                pg.grabPixels();
//                cm = pg.getColorModel();
            } catch (Exception x) {
                x.printStackTrace();
            }
            
            for(int i=0; i<w*h; i++) {
              /*  int r=cm.getRed(pixels[i]);
                int g=cm.getGreen(pixels[i]);
                int b=cm.getBlue(pixels[i]); */
          
                pixs[w*h-i-1] = pixels[i];
            }
            
            Image tmpimg = createImage(new MemoryImageSource(w,h,pixs,0,w));
            
            Graphics gg;
            gg = getGraphics();
            gg.drawImage(tmpimg, 0,0,null);

***************************


can't test it at the moment, but you need something like

PixelGrabber pg = new PixelGrabber(img, 0,0, w, h, pixels, 0, w);
try
{
  pg.grabPixels();
} catch (Exception x)
{
  x.printStackTrace();
}

for(int i=0; i<w*h; i++)
{
  int rgb = pixels[i];
  int a = (rgb >> 24) & 0xff;
  int r = (rgb >> 16) & 0xff;
  int g = (rgb >> 8)  & 0xff;
  int h = (rgb)       & 0xff;

}
u should know about images more, and know how pixels are stored there, it depends on the number of colore the image use, for example, the example that used by heyhey, he assume that there's a byte for each single color, so when u need to get the RBG, u need to extract them from the pixel value.
so u had to know how many colors ur image has.
Avatar of m_adil

ASKER

I think i can find the no. of colors through Object pixels = pg.getPixels();
But as I've written above, the problem is that when i use ColorModel cm=pg.getColorModel();
it gives me an error ** Method getColorModel() not found in java.awt.image.PixelGrabber. **

Is there any other way to find the no. of colors?

Another thing is that when an image is using more than a byte for single pixel, then how to get RGB values?
' public synchronized ColorModel getColorModel()


Get the ColorModel for the pixels stored in the array. If the PixelGrabber was constructed with an explicit pixel buffer then this method will always return the default RGB ColorModel ...'

(so usually you don't need to use ColorModel at all)


> Another thing is that when an image
> is using more than a byte for single pixel,

Image usually uses INT (not BYTE) per pixel. red, green, blue and alpha values are packed inside that int.

why don't you just try my example ?
Avatar of m_adil

ASKER

heyhey thank u so much for ur help. Plz tell me one more thing. How to set pixel value from RGB value. i.e the reverse function of
  int rgb = pixels[i];
  int a = (rgb >> 24) & 0xff;  //blue
  int r = (rgb >> 16) & 0xff;  //red
  int g = (rgb >> 8)  & 0xff;  //green
  int h = (rgb)       & 0xff;  // ???
(what is h btw)
after changing rgb values how can i combine them to change pixels[i].

I've done this in c++ through
inline TColor rgb(int red,int green,int blue){return ((TColor)((blue)+(green<<8)+(red<<16)));};

but not sure how to do in java.
it's almost the same

int oldrgb = pixels[i];
int a = (rgb >> 24) & 0xff;  //blue
int r = (rgb >> 16) & 0xff;  //red
int g = (rgb >> 8)  & 0xff;  //green
int h = (rgb)       & 0xff;  // ???

int newrgb = (alpha << 24) | (red << 16) | (green << 8) | (blue);
// now newrgb == oldrgb :)

// or
// int newrgb = (alpha << 24) | (green << 16) | (red << 8) | (blue);
// change green and red

Avatar of m_adil

ASKER

yup its working.
Thanks alot.
so why did you accept samers's answer ?