-2

Building a lottery scratch-card app in Java. Have allot of it done, just need help with the scratching functionality.

Basically the program works like this:

  1. create image for the background (right now its just a white background, but later would obviously be an scratchcard image with lotto symbols)
  2. create the card_surface which is just a green layer than should reveal the image behind when scratched.
  3. onMouseDragged() I used a stroke to draw a line from current mouse co-ordinates to newer mouse-cordinates. I have tried setting the Alphacomposite on this stroke thinking it would reveal the image underneath. Unfortunately not though.

Appreciate any help...

 import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.ImageIcon;

import java.awt.Stroke;
import java.awt.BasicStroke;
import java.awt.AlphaComposite;


public class Main {
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    final DrawPad drawPad = new DrawPad();
    frame.add(drawPad, BorderLayout.CENTER);
    JButton clearButton = new JButton("New Scratch-Card");
    clearButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        drawPad.clear();
      }
    });
    frame.add(clearButton, BorderLayout.SOUTH);
    frame.setSize(500, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }

}
class DrawPad extends JComponent {
  Image image;
  Image card_surface;

  Graphics2D graphics2D;
  int currentX, currentY, oldX, oldY;



  public DrawPad() {
    final Stroke stroke = new BasicStroke (17.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL);
    //image = new ImageIcon("iPhone-4-Pattern-Wallpaper-07.jpg").getImage();
    setDoubleBuffered(false);
    addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        oldX = e.getX();
        oldY = e.getY();
      }
    });
    addMouseMotionListener(new MouseMotionAdapter() {
      public void mouseDragged(MouseEvent e) {
        currentX = e.getX();
        currentY = e.getY();
        if (graphics2D != null){
      graphics2D.setStroke(stroke);
          graphics2D.setPaint(Color.GRAY);
          graphics2D.setComposite(makeComposite(0.5F));
          graphics2D.drawLine(oldX, oldY, currentX, currentY);
        repaint();
        oldX = currentX;
        oldY = currentY;
      }
}
    });
  }
private AlphaComposite makeComposite(float alpha) {
    int type = AlphaComposite.SRC_OVER;
    return(AlphaComposite.getInstance(type, alpha));
  }
 public void clear() {
    image=null;
    card_surface=null;

    repaint();
  }
  public void paintComponent(Graphics g) {
    if (image == null) {

      image = createImage(getSize().width, getSize().height);
      graphics2D = (Graphics2D) image.getGraphics();
      graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
          RenderingHints.VALUE_ANTIALIAS_ON);



    graphics2D.setPaint(Color.white);
        graphics2D.fillRect(0, 0, getSize().width, getSize().height);
        graphics2D.setPaint(Color.black);

    repaint();

    }

     if (card_surface == null) {
    card_surface = createImage(getSize().width, getSize().height);
        graphics2D = (Graphics2D) card_surface.getGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
      RenderingHints.VALUE_ANTIALIAS_ON);   

    graphics2D.setPaint(Color.green);
        graphics2D.fillRect(0, 0, getSize().width, getSize().height);

    repaint();
}


    g.drawImage(image, 0, 0, null);
    g.drawImage(card_surface, 0, 0, null);

  }


}
aubreybourke
  • 439
  • 1
  • 5
  • 17
  • You need to tell us what your problem is. Just telling what you want to do isn't too much help actually. Tell us what doesn't work, which (if any) exceptions you get etc. – Magnus Winter Dec 29 '11 at 08:19
  • I don't know where to go from here. I tried using an Alphacomposite stroke to unmask the image underneath. I also looked into clipping the image underneath. The code compile and runs, so no exceptions. I guess I dont really know the best way to do it, so maybe someone could suggest something? – aubreybourke Dec 29 '11 at 08:31

2 Answers2

4

What you are trying to do is to reveal the underlying image when the user 'scratches' the top image, correct?

You actually need two images here : First, the original image and secondly, a blank image with a gray background that goes over the first image, hiding it. When the user 'scratches' the top image, you need to draw with a transparent colour OVER the gray image, revealing the underlying image.

So the steps are:

Draw original image with blank over it When user 'scratches' draw with a transparent colour on the top image Repaint the images, with the top image now having transparent sections Repeat

It sounds complicated, but I don't think it will be too hard, you just need to keep the two images apart and paint one over the other using a buffer. See this post How to make a color transparent in a BufferedImage and save as PNG for information on working with transparent buffered images.

I hope this helps.

Community
  • 1
  • 1
Ewald
  • 5,691
  • 2
  • 27
  • 31
  • Ok thanks - I'll take a look and get back to you later. I badly need sleep right now! – aubreybourke Dec 29 '11 at 09:08
  • Great, I think it will work, I did something like this years ago in a game, so the theory is solid. Implementation would be trickier, but it's definitely doable. – Ewald Dec 29 '11 at 09:17
  • Ahhh, Got it.- I read the code and can see this working! Nice one for the help mate. – aubreybourke Dec 29 '11 at 10:19
  • Excellent, there's still a bit of work for you, but once you have the idea, it's easier to implement. Best of luck! – Ewald Dec 29 '11 at 12:01
0

OK managed to get the basics working,

I used the link from Ewald, thanks mate!

Here's the working code (just change the 'iphone4' image path to an image of your choice):

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.ImageIcon;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.awt.Toolkit;
import java.io.File;
import javax.imageio.ImageIO;

import java.awt.Stroke;
import java.awt.BasicStroke;
import java.awt.AlphaComposite;


public class Main {
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    final DrawPad drawPad = new DrawPad();
    frame.add(drawPad, BorderLayout.CENTER);
    JButton clearButton = new JButton("New Scratch-Card");
    clearButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        drawPad.clear();
      }
    });
    frame.add(clearButton, BorderLayout.SOUTH);
    frame.setSize(500, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }

}
class DrawPad extends JComponent {
  BufferedImage image;
  BufferedImage card_surface;

  Graphics2D graphics2D;
  int currentX, currentY, oldX, oldY;



  public DrawPad() {
    final Stroke stroke = new BasicStroke (17.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL);

    setDoubleBuffered(false);
    addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent e) {
        oldX = e.getX();
        oldY = e.getY();
      }
    });
    addMouseMotionListener(new MouseMotionAdapter() {
      public void mouseDragged(MouseEvent e) {
        currentX = e.getX();
        currentY = e.getY();
        if (graphics2D != null){
      graphics2D.setStroke(stroke);
          graphics2D.setPaint(Color.GRAY);
          //graphics2D.setComposite(makeComposite(0.5F));
          graphics2D.drawLine(oldX, oldY, currentX, currentY);
        repaint();
        oldX = currentX;
        oldY = currentY;
      }
}
    });
  }
private AlphaComposite makeComposite(float alpha) {
    int type = AlphaComposite.SRC_OVER;
    return(AlphaComposite.getInstance(type, alpha));
  }
 private Image TransformColorToTransparency(BufferedImage image, Color c1, Color c2)
  {
    // Primitive test, just an example
    final int r1 = c1.getRed();
    final int g1 = c1.getGreen();
    final int b1 = c1.getBlue();
    final int r2 = c2.getRed();
    final int g2 = c2.getGreen();
    final int b2 = c2.getBlue();
    ImageFilter filter = new RGBImageFilter()
    {
      public final int filterRGB(int x, int y, int rgb)
      {
        int r = (rgb & 0xFF0000) >> 16;
        int g = (rgb & 0xFF00) >> 8;
        int b = rgb & 0xFF;
        if (r >= r1 && r <= r2 &&
            g >= g1 && g <= g2 &&
            b >= b1 && b <= b2)
        {
          // Set fully transparent but keep color
          return rgb & 0xFFFFFF;
        }
        return rgb;
      }
    };

    ImageProducer ip = new FilteredImageSource(image.getSource(), filter);
      return Toolkit.getDefaultToolkit().createImage(ip);
  }
private BufferedImage ImageToBufferedImage(Image image2, int width, int height)
  {
    BufferedImage dest = new BufferedImage(
        width, height, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = dest.createGraphics();
    //g2.drawImage(image, 0, 0, null);
    g2.drawImage(image2, 0, 0, null);
    //g2.dispose();
    return dest;
  }
 public void clear() {
    image=null;
    card_surface=null;

    repaint();
  }
  public void paintComponent(Graphics g) {



 if (image == null) {

    image = new BufferedImage(500, 300, BufferedImage.TYPE_INT_ARGB);
    String imagePath = "iPhone-4-Pattern-Wallpaper-07.jpg";
    File inFile = new File(imagePath);
    try{
    image = ImageIO.read(inFile);
}catch(java.io.IOException e){System.out.println(e);}


    graphics2D = image.createGraphics();

      //image = new ImageIcon().getImage("");
      //image = createImage(getSize().width, getSize().height);
      //graphics2D = (Graphics2D) image.getGraphics();
      graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
          RenderingHints.VALUE_ANTIALIAS_ON);



    //graphics2D.setPaint(Color.white);
       // graphics2D.fillRect(0, 0, getSize().width, getSize().height);
       // graphics2D.setPaint(Color.black);

    repaint();

    }

     if (card_surface == null) {
    card_surface = new BufferedImage(500, 300, BufferedImage.TYPE_INT_ARGB);
        graphics2D = (Graphics2D) card_surface.getGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
      RenderingHints.VALUE_ANTIALIAS_ON);   

    graphics2D.setPaint(Color.green);
        graphics2D.fillRect(0, 0, getSize().width, getSize().height);

    repaint();
}


    g.drawImage(image, 0, 0, null);
    g.drawImage(card_surface, 0, 0, null);
    Image transpImg2 = TransformColorToTransparency(card_surface, new Color(0, 50, 77), new Color(200, 200, 255));
    BufferedImage resultImage2 = ImageToBufferedImage(transpImg2, image.getWidth(), image.getHeight());
    g.drawImage(image, 0, 0, null);
    g.drawImage(resultImage2, 0, 0, null); 

   /* File outFile2 = new File("map_with_transparency2.png");
    try{
    ImageIO.write(resultImage2, "PNG", outFile2);
    }catch(Exception e){System.out.println(e);}
    //card_surface = (BufferedImage)transpImg2;
    */
  }


}
aubreybourke
  • 439
  • 1
  • 5
  • 17
  • Here's a look at a well polished app I made which uses this code as its basis: http://www.splashportal.net/scratchCard/ :)))))))) – aubreybourke Dec 30 '11 at 11:23