Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / First Aid / February 2008

Tip: Looking for answers? Try searching our database.

Has working with raster graphics always been this complicated?

Thread view: 
jsalzman@gmail.com - 25 Feb 2008 16:21 GMT
Hello,

I'm not new to programming, but I'm new to Java, at least as far as
programming an entire applet. I'm familiar with looking through a
language's API to learn more about developing an application using
available methods. I've done it plenty of times.

When I learn a new programming language, I do it by having a goal in
mind. Something that I want to program to achieve a task. in doing so,
I develop an understanding of the language.

I just can't, for the life of me, figure out how to manipulate raster
images the way I want. I find references to Image objects, Graphics
objects, BufferedImage objects and such. You can do things with Image
objects that you can't do with Graphics objects. There's plenty of
online help for Java, but help through API docs and tutorials don't
seem to spell out many details. There seems to be more useful
tutorials, describing the theory behind an API call, for Visual Basic
than Java out there.

I'm trying to figure out the true differences between an Image and
Graphics object. From what I can find, You can draw primitives on
Graphics, but not Image. If you can draw primitives on Images, I can't
figure out the details.

Here's what I'm trying to do. This is the "demo" project I'm making to
help me learn graphics handling concepts in Java. I wanted to make a
mouse driven application that reveals a hidden picture. I have the
picture graphics to be revealed, in the form of GIF files. I have a
series of "covering" images that I want to use to cover the pictures
in the form of GIF files (in the shape of doors, curtains, etc.).

Here's my concept. I have code working that can get the door image to
draw over the picture image. I'm having trouble with the code that
will do the "reveal". I want to animate a box that widens from the
middle of the cover picture to the edges (simulating a barn door
wipe). My first thought would be to paint 1px wide box in a
transparent color and redraw the box to as wide as the graphic. Sounds
easy enough in a drawing program like Photoshop. I can't figure out
how to paint in a transparent color on a raster image object and then
superimpose that image on the picture making the picture visible under
those transparent pixels.

I'm not asking anyone to write the entire program for me. The way I'm
trying to accomplish the task may be overkill, but I'm doing it this
way to become familiar with certain concepts. I'm looking for working
examples of code that'll show me how to draw transparent pixels on a
raster image, overlay the raster on another image with the image
showing through the transparent spot, and draw primitives on a raster
image (if different from other drawing methods using rasters). Double
buffering the drawing process would be a plus, is that what I would
use a BufferedImage for?

Thanks,
Jeff
Nigel Wade - 25 Feb 2008 16:44 GMT
> Hello,
>
[quoted text clipped - 15 lines]
> tutorials, describing the theory behind an API call, for Visual Basic
> than Java out there.

This isn't anything I'm really familiar with myself. I've done some basic
programming with the Graphics2D object, images and transforms etc. but not a
lot. I don't know if these links are of any use to you, they are some I filed
away for myself, if you haven't looked through them yet they could provide some
insight:

http://java.sun.com/docs/books/tutorial/2d/index.html
http://www.apl.jhu.edu/~hall/java/Java2D-Tutorial.html

Signature

Nigel Wade, System Administrator, Space Plasma Physics Group,
           University of Leicester, Leicester, LE1 7RH, UK
E-mail :    nmw@ion.le.ac.uk
Phone :     +44 (0)116 2523548, Fax : +44 (0)116 2523555

Knute Johnson - 25 Feb 2008 17:20 GMT
> Hello,
>
[quoted text clipped - 51 lines]
> Thanks,
> Jeff

Graphics and Graphics2D should be thought of as the paint brush with
which you draw on Images, BufferedImages, Printers, etc.  If an object
is something to draw on, you will be able to get a Graphics/2D object
for it.

If you load an image that has transparent pixels, when you draw that
image on top of another image, the first image will show through the
transparent pixels.  There are numerous other ways to make drawings or
images transparent (see AlphaComposite).  Color objects can be created
with transparency too.  Below I create a BufferedImage, draw translucent
yellow pixels on the entire image.  In the paintComponent(), where all
drawing on the component must take place, I draw a red and blue X on the
component and then draw the BufferedImage with its transparent pixels
over the top.  The is just one simple way to do this sort of drawing.

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

public class test extends JPanel {
    BufferedImage bi = new
BufferedImage(400,300,BufferedImage.TYPE_INT_ARGB);

    public test() {
        setPreferredSize(new Dimension(400,300));

        // draw translucent yellow on the buffered image
        Graphics2D g = bi.createGraphics();
        g.setColor(new Color(255,255,0,180));
        g.fillRect(0,0,bi.getWidth(),bi.getHeight());
    }

    public void paintComponent(Graphics g2D) {
        Graphics2D g = (Graphics2D)g2D;
        // draw blue and red X first
        g.setColor(Color.BLUE);
        BasicStroke bs = new BasicStroke(20.0f);
        g.setStroke(bs);
        g.drawLine(0,0,getWidth(),getHeight());
        g.setColor(Color.RED);
        g.drawLine(getWidth(),0,0,getHeight());

        // draw translucent image
        g.drawImage(bi,0,0,null);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                test t = new test();
                f.add(t);
                f.pack();
                f.setVisible(true);
            }
        });
    }
}

Signature

Knute Johnson
email s/nospam/knute/

jsalzman@gmail.com - 25 Feb 2008 17:59 GMT
Thanks for the help Knute (and Nigel) for some of the direction.

I see by your sample code Knute that Java is highly "granular" when it
comes to manipulating objects, mostly the requirement of getting a new
instance of something you want to use to manipulate another object.
Just something I need to keep in mind to better understand Java.
Mark Space - 25 Feb 2008 18:19 GMT
> Thanks for the help Knute (and Nigel) for some of the direction.
>
> I see by your sample code Knute that Java is highly "granular" when it
> comes to manipulating objects, mostly the requirement of getting a new
> instance of something you want to use to manipulate another object.
> Just something I need to keep in mind to better understand Java.

You might also consider getting some introductory reading material on
Java graphics.  I don't have a lot of experience with it either, but
_Learning Java_ by O'Reilly does have an introduction to Graphics2D.  I
remember specifically a demo program that loaded an image, then allowed
you to grab it with the mouse and drag it around the window.  It was
pretty cool and with a little bit of study revealed some good hints how
to think about the Graphics2D operations.

_Learning Java_ is also a very complete introduction to the language,
and many important APIs.  If you are feeling new and overwhelmed, I'd
recommend it as a good start.  With _Learning Java_ and Sun's on-line
tutorial, you have 90% of what you need to get started.  Make sure to
get the latest edition (third I think).

There are also books specifically on 2D graphics in Java.  I don't know
how much they really add to _Learning Java_.
jsalzman@gmail.com - 26 Feb 2008 13:12 GMT
OK, I'm getting close, but I seem to be missing something. I've
included my code so far. I know it's a bit messy, but I'm still
learning to tighten up java code. This is a proof of concept for me.
It achieves something similar to what I wanted to do originally. I
currently have the program draw an oval (circle) where the mouse
clicks. That's enough to let me see what happens real-time.
Eventually, I'll have the reveal "expand" from the point where the
user clicks.

Anyway, drawing an expanding oval or box isn't the problem. This
example takes one image file (revealArea) and is supposed to overlay
it on another image file (baseImage). I expected to be able to click
in the window and wherever my mouse is, an oval will "paint a hole"
into the revealArea image, exposing part of the baseImage below.

I currently have the code of the revealArea image commented out. In
lieu of that image, I simply draw a white filled rectangle to
substitute. The rectangle overlays the base image fine (as witnessed
from the flicker). Drawing the oval does something unexpected. I set
the paint color to blue with an alpha of 30. I tried an alpha of zero,
expecting the hole to appear. When I click in the window, I get a
translucent blue circle blended with the white rectangle and not the
"hole" I expected to be formed. Is there a way to "paint" the hole?
Also, what techniques can I use to avoid the flicker of the images
drawing over one another?

Thanks!

-----------------------
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.lang.Math;
import javax.swing.*;
import javax.imageio.*;
import java.io.*;

public class Reveal extends Applet
  implements MouseMotionListener {

  int width, height;
  int mx, my;  // the mouse coordinates
  Image baseImage;
  Image revealArea;
  Image backbuffer;
  BufferedImage revealBuffer;
  Graphics revealOverlay;

  public void init() {
     width = getSize().width;
     height = getSize().height;
     setBackground( Color.black );

     mx = width/2;
     my = height/2;

     baseImage = getImage( getDocumentBase(), "baseimage.gif" );
     revealArea = getImage( getDocumentBase(),"overlay.gif");

     revealBuffer = new BufferedImage(100, 100,
BufferedImage.TYPE_INT_ARGB);
     revealOverlay = revealBuffer.getGraphics();
     revealOverlay.fillRect(10, 10, 80, 80);
     //revealOverlay.drawImage(scratchArea, 0, 0, 100, 100, null);

     repaint();

     addMouseMotionListener( this );
  }

  public void mouseMoved( MouseEvent e ) {
     repaint();
     e.consume();
  }

  public void mouseDragged( MouseEvent e ) {
     int x = e.getX();
     int y = e.getY();

     revealOverlay.setColor(new Color(0, 0, 255, 30));
     revealOverlay.fillOval(x-5, y-5, 20, 20);

     repaint();
     e.consume();
  }

  public void paint( Graphics g ) {

     g.drawImage(baseImage, 0, 0, null);
     g.drawImage(revealBuffer, 0, 0, null);
  }
}
Knute Johnson - 26 Feb 2008 22:37 GMT
> OK, I'm getting close, but I seem to be missing something. I've
> included my code so far. I know it's a bit messy, but I'm still
[quoted text clipped - 89 lines]
>    }
> }

This can get really tricky.  The problem usually turns out for me anyway
is that you can't draw on an image and reduce its alpha.  You have to
use an AlphaComposite to set the pixel values to something less than
opaque.  Then you can draw that image over another image and the image
behind will be visible through the alpha hole.  If you draw translucent
pixels over opaque pixels the image is still opaque.  See the example below.

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

public class test extends JPanel {
    BufferedImage bi = new
        BufferedImage(400,300,Transparency.TRANSLUCENT);
    Graphics2D imageG;

    public test() {
        setPreferredSize(new Dimension(400,300));

        imageG = bi.createGraphics();

        // the green overlay image will not be green until the first
        // time you press the mouse button
        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent me) {
                // paint the whole image green
                imageG.setColor(Color.GREEN);
                imageG.fillRect(0,0,bi.getWidth(),bi.getHeight());
                // save the composite
                Composite c = imageG.getComposite();
                // clear a hole in the green image
                // adjust the alpha to keep a percentage of green
                // you could use AlphaComposite.CLEAR will be the same
as using
                // an alpha of 0f
                imageG.setComposite(AlphaComposite.getInstance(
                 AlphaComposite.DST_ATOP,0.4f));
                imageG.fillOval(me.getX()-20,me.getY()-20,40,40);
                // restore the composite
                imageG.setComposite(c);
                repaint();
            }
        });
    }

    public void paintComponent(Graphics g2D) {
        Graphics2D g = (Graphics2D)g2D;

        // erase everything with white
        g.setColor(Color.WHITE);
        g.fillRect(0,0,getWidth(),getHeight());
        // draw blue and red X
        g.setColor(Color.BLUE);
        BasicStroke bs = new BasicStroke(20.0f);
        g.setStroke(bs);
        g.drawLine(0,0,getWidth(),getHeight());
        g.setColor(Color.RED);
        g.drawLine(getWidth(),0,0,getHeight());

        // draw image with translucent hole
        g.drawImage(bi,0,0,null);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                test t = new test();
                f.add(t);
                f.pack();
                f.setVisible(true);
            }
        });
    }
}

Signature

Knute Johnson
email s/nospam/knute/



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.