views:

487

answers:

2
+1  Q: 

BufferedImage Help

I posted a question in sun java forums sometime ago and i am finding it hard to understand the first response i received from the replier though it seems he gave me the correct approach to my problem. The link to the question is:

http://forums.sun.com/thread.jspa?threadID=5436562&tstart=0

Someone replied that i should use BufferedImage and make tiles. I don't really understand what the tiles mean in connection with the BufferedImage.

I would like someone to explain to me what the tiles are and how they are created in the BufferedImage.

I have searched the web for a while but couldn't find any link that can help me understanding the basics of the tiles and creating the tiles. Any pointer to a site is also appreciated.

I need help in understanding the tiles in connection with the BufferedImage and also how they are created.

+5  A: 

A "tile" in a 2D game simply means an "image smaller than whole screen that you can reuse several times to create the background".

Here's a a working example where four tiles are created (adding some random noise to every pixel). Each tile is 50x50 pixels.

Then there's a "map" (that you call a "grid" in your case) representing which tiles you want to put where.

From that map, a bigger BufferedImage is created (note that it's just an example, in a real program you'll want to use a BufferedImage copy, not a pixel-by-pixel copy).

The map is 9x7, each tile is 50x50 pixels, hence the resulting image is 9*50 x 7*50 (ie 450 by 350).

Note that the following is really just a simple example, as short as possible, showing how to create a bigger BufferedImage using several tiles: the goal is not to give a tutorial on best Swing usage nor on how to squeeze every bit of performances out of BufferedImages, etc.

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

public class ToyTiled extends JFrame {

    private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;

    private BufferedImage img;

    public static void main( String[] args ) {
        new ToyTiled();
    }

    public ToyTiled() {
        super();
        this.add(new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                g.drawImage(img, 0, 0, null);
            }

        });
        img = new BufferedImage( 450, 350, IMAGE_TYPE );   // here you should create a compatible BufferedImage
        this.setSize(img.getWidth(), img.getHeight());
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);


        final int NB_TILES = 4;
        BufferedImage[] tiles = new BufferedImage[NB_TILES];
        tiles[0] = createOneTile( new Color( 255, 255, 255 ) );
        tiles[1] = createOneTile( new Color( 255,   0, 255 ) );
        tiles[2] = createOneTile( new Color(   0,   0, 255 ) );
        tiles[3] = createOneTile( new Color(   0, 255, 255 ) );  

        final int[][] map = new int[][] {
                { 1, 0, 2, 3, 0, 1, 2, 2, 2 },
                { 0, 2, 3, 0, 1, 2, 2, 2, 3 },
                { 1, 0, 2, 3, 0, 1, 2, 2, 2 },
                { 2, 1, 0, 1, 2, 3, 2, 0, 0 },
                { 1, 0, 2, 3, 0, 1, 2, 2, 3 },
                { 1, 0, 2, 2, 1, 1, 2, 2, 3 },
                { 1, 0, 2, 3, 0, 1, 2, 2, 3 },
        };

        for (int i = 0; i < map[0].length; i++) {
            for (int j = 0; j < map.length; j++) {
                final BufferedImage tile = tiles[map[j][i]];
                for (int x = 0; x < tile.getWidth(); x++) {
                    for (int y = 0; y < tile.getHeight(); y++) {
                        img.setRGB( x + i * 50, y + j * 50, tile.getRGB(x,y) );
                    }
                }
            }
        }

        this.setVisible( true );
    }

    private BufferedImage createOneTile( final Color c ) {
        final Random r = new Random();
        final BufferedImage res = new BufferedImage( 50, 50, IMAGE_TYPE );
        for (int x = 0; x < res.getWidth(); x++) {
            for (int y = 0; y < res.getHeight(); y++) {
                res.setRGB( x, y, c.getRGB() - r.nextInt(150) );
            }
        }
        return res;
    }

}
Webinator
Thank you sooo much for your reply. I am still studying the code. Thanks.
Eddy Freeman
@Eddy Freeman: if this was an answer that solved the problem for you, or got you on the right track, it is considered courteous to select it as the "answer" to your problem.
aperkins
A: 

If you want to rotate a portion of a BufferedImage you might find these classes/methods useful:

Example:

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;

public class TileTest extends JFrame {

    public static void main(String[] args) throws IOException {
        URL logo = new URL("http://sstatic.net/so/img/logo.png");
        TileTest tileTest = new TileTest(ImageIO.read(logo));
        tileTest.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        tileTest.setVisible(true);
    }

    private TileTest(BufferedImage image) throws IOException {
        this.image = image; 
        setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
        JLabel label = new JLabel(new ImageIcon(image));
        add(label);
        BufferedImage tile = image.getSubimage(0, 0, 61, 61);
        add(new JButton(new RotateAction(tile, label)));
        pack();
    }

    private BufferedImage image;

}

class RotateAction extends AbstractAction {

    public void actionPerformed(ActionEvent e) {
        BufferedImage tmpImage = op.filter(image, null);
        image.setData(tmpImage.getRaster());
        component.repaint();
    }

    RotateAction(BufferedImage image, Component component) {
        super("Rotate");
        this.component = component;
        this.image = image;
        double x = 0.5 * image.getWidth();
        double y = 0.5 * image.getHeight();
        AffineTransform xfrm =
            AffineTransform.getQuadrantRotateInstance(1, x, y);
        op = new AffineTransformOp(
            xfrm, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
    }

    private final Component component;

    private final BufferedImage image;

    private final BufferedImageOp op;

}
finnw