Slow map in java - java

I'm making a game in java, is a rpg, however, only with the map the game is slow.
The map is made ​​in TiledMap Editor, therefore, an XML that is read and loaded into an ArrayList. My PC is a dual-core 3.0, 4GB RAM, 1GB Video.
The do the rendering is done as follows:
//method of tileset class
public void loadTileset(){
positions = new int[1 + tilesX * tilesY][2];
int yy = 0;
int xx = 0;
int index = 0;
// save the initial x and y point of each tile in an array named positions
// positions[tileNumber] [0] - X position
// positions[tileNumber] [1] - Y position
for(int i = 1 ; i < positions.length; i++){
if(index == tilesX ){
yy += tileHeight;
xx = 0;
index = 0;
}
positions[i][0] = xx;
positions[i][1] = yy;
xx += tileWidth;
index++;
}
}
//method of map class
public void draw(Graphics2D screen){
//x and y position of each tile on the screen
int x = 0; int y = 0;
for(int j = 0; j < 20 ; j++){
for(int i = initialTile ; i < initialTile + quantTiles ; i++){
int tile = map[j][i];
if(tile != 0){
screen.drawImage(tileSet.getTileImage().getSubimage(tileSet.getTileX(tile), tileSet.getTileY(tile),tileSet.getTileWidth(), tileSet.getTileHeight()),x,y,null);
}
x += tileSet.getTileWidth();
}
x = 0;
y += tileSet.getTileHeight();
}
}
Am I doing something wrong?
Note: I'm new to the forum and to make matters worse I do not understand very much English, so excuse any mistake.

First of all, you should not create the subimages for the tiles during each call. Strictly speaking, you should not call getSubimage at all for images that you want to paint: It will make the image "unmanaged", and this can degrade rendering performance by an order of magnitude. You should only call getSubimage for images that you do not want to render - for example, when you are initially creating individual images for the tiles.
You obviously already have a TileSet class. You could add a bit of functionality to this class so that you can directly access images for the tiles.
Your current code looks like this:
screen.drawImage(
tileSet.getTileImage().getSubimage(
tileSet.getTileX(tile),
tileSet.getTileY(tile),
tileSet.getTileWidth(),
tileSet.getTileHeight()),
x,y,null);
You could change it to look like this:
screen.drawImage(tileSet.getTileImage(tile), x,y,null);
The getTileImage(int tile) method suggested here could then obtain tiles that have been stored internally.
I'll sketch a few lines of code from the tip of my head, you'll probably be able to transfer this into your TileSet class:
class TileSet
{
private Map<Integer, BufferedImage> tileImages;
TileSet()
{
....
prepareTileImages();
}
private void prepareTileImages()
{
tileImages = new HashMap<Integer, BufferedImage>();
for (int tile : allPossibleTileValuesThatMayBeInTheMap)
{
// These are the tiles that you originally rendered
// in your "draw"-Method
BufferedImage image =
getTileImage().getSubimage(
getTileX(tile),
getTileY(tile),
getTileWidth(),
getTileHeight());
// Create a new, managed copy of the image,
// and store it in the map
BufferedImage managedImage = convertToARGB(image);
tileImages.put(tile, managedImage);
}
}
private static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
// This is the new method: For a given "tile" value
// that you found at map[x][y], this returns the
// appropriate tile:
public BufferedImage getTileImage(int tile)
{
return tileImages.get(tile);
}
}

Related

How do I create an Area object using a PathIterator?

I am clearly missing an important concept here. I have written code using mouse events to draw a boundary (a polygon) on an existing BufferedImage. Here is the relevant section:
public void paintComponent(Graphics g)
{
super.paintComponent(g); //Paint parent's background
//G3 displays the BufferedImage "Drawing" with each paint
Graphics2D G3 = (Graphics2D)g;
G3.drawImage(this.Drawing, 0, 0, null);
G3.dispose();
}
public void updateDrawing()
{
int x0, y0, x1, y1; // Vertex coordinates
Line2D.Float seg;
// grafix is painting the mouse drawing to the BufferedImage "Drawing"
if(this.pts.size() > 0)
{
for(int ip = 0; ip < pts.size(); ip++)
{
x0 = (int)this.pts.get(ip).x;
y0 = (int)this.pts.get(ip).y;
this.grafix.drawRect(x0 - this.sqw/2, y0 - this.sqh/2, + this.sqw, this.sqh);
if (ip > 0)
{
x1 = (int)this.pts.get(ip-1).x;
y1 = (int)this.pts.get(ip-1).y;
this.grafix.drawLine(x1, y1, x0, y0);
seg = new Line2D.Float(x1, y1, x0, y0);
this.segments.add(seg);
}
}
}
repaint();
}
The next two routines are called by the mouse events: Left click gets the next point and right click closes the region.
public void getNextPoint(Point2D p)
{
this.isDrawing = true;
Point2D.Float next = new Point2D.Float();
next.x = (float) p.getX();
next.y = (float) p.getY();
this.pts.add(next);
updateDrawing();
}
public void closeBoundary()
{
//Connects the last point to the first point to close the loop
Point2D.Float next = new Point2D.Float(this.pts.get(0).x, this.pts.get(0).y);
this.pts.add(next);
this.isDrawing = false;
updateDrawing();
}
It all works fine and I can save the image with my drawing on it:
image with drawing
The list of vertices (pts) and the line segments (segments) are all that describe the region/shape/polygon.
I wish to extract from the original image only that region enclosed within the boundary. That is, I plan to create a new BufferedImage by moving through all of the pixels, testing to see if they fall within the figure and keep them if they do.
So I want to create an AREA from the points and segments I've collected in drawing the shape. Everything says: create an AREA variable and "getPathIterator". But on what shape? My AREA variable will be empty. How does the path iterator access the points in my list?
I've been all over the literature and this website as well.
I'm missing something.
Thank you haraldK for your suggestion. Before I saw your post, I came to a similar conclusion:
Using the Arraylist of vertices from the paint operation, I populated a "Path2D.Float" object called "contour" by looping through the points list that was created during the "painting" operation. Using this "contour" object, I instantiated an Area called "interferogram". Just to check my work, I created another PathIterator, "PI", from the Area and decomposed the Area, "interferogram" into "segments" sending the results to the console. I show the code below:
private void mnuitmKeepInsideActionPerformed(java.awt.event.ActionEvent evt)
{
// Keeps the inner area of interest
// Vertices is the "pts" list from Class MouseDrawing (mask)
// It is already a closed path
ArrayList<Point2D.Float> vertices =
new ArrayList<>(this.mask.getVertices());
this.contour = new Path2D.Float(Path2D.WIND_NON_ZERO);
// Read the vertices into the Path2D variable "contour"
this.contour.moveTo((float)vertices.get(0).getX(),
(float)vertices.get(0).getY()); //Starting location
for(int ivertex = 1; ivertex < vertices.size(); ivertex++)
{
this.contour.lineTo((float)vertices.get(ivertex).getX(),
(float)vertices.get(ivertex).getY());
}
this.interferogram = new Area(this.contour);
PathIterator PI = this.interferogram.getPathIterator(null);
//Test print out the segment types and vertices for debug
float[] p = new float[6];
int icount = 0;
while( !PI.isDone())
{
int type = PI.currentSegment(p);
System.out.print(icount);
System.out.print(" Type " + type);
System.out.print(" X " + p[0]);
System.out.println(" Y " + p[1]);
icount++;
PI.next();
}
BufferedImage masked = Mask(this.image_out, this.interferogram);
// Write image to file for debug
String dir;
dir = System.getProperty("user.dir");
dir = dir + "\\00masked.png";
writeImage(masked, dir, "PNG");
}
Next, I applied the mask to the image testing each pixel for inclusion in the area using the code below:
public BufferedImage Mask(BufferedImage BIM, Area area)
{
/** Loop through the pixels in the image and test each one for inclusion
* within the area.
* Change the colors of those outside
**/
Point2D p = new Point2D.Double(0,0);
// rgb should be white
int rgb = (255 << 24);
for (int row = 0; row < BIM.getWidth(); row++)
{
for (int col = 0; col < BIM.getHeight(); col++)
{
p.setLocation(col, row);
if(!area.contains(p))
{
BIM.setRGB(col, row, rgb);
}
}
}
return BIM;
}
public static BufferedImage deepCopy(BufferedImage B2M)
{
ColorModel cm = B2M.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = B2M.copyData(B2M.getRaster()
.createCompatibleWritableRaster());
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
This worked beautifully (I was surprised!) except for one slight detail: the lines of the area appeared around the outside of the masked image.
In order to remedy this, I copied the original (resized) image before the painting operation. Many thanks to user1050755 (Nov 2014) for the routine deepCopy that I found on this website. Applying my mask to the copied image resulted in the portion of the original image I wanted without the mask lines. The result is shown in the attached picture. I am stoked!
masked image

Java Convolution

Hi I am in need of some help. I need to write a convolution method from scratch that takes in the following inputs: int[][] and BufferedImage inputImage. I can assume that the kernel has size 3x3.
My approach is to do the follow:
convolve inner pixels
convolve corner pixels
convolve outer pixels
In the program that I will post below I believe I convolve the inner pixels but I am a bit lost at how to convolve the corner and outer pixels. I am aware that corner pixels are at (0,0), (width-1,0), (0, height-1) and (width-1,height-1). I think I know to how approach the problem but not sure how to execute that in writing though. Please to aware that I am very new to programming :/ Any assistance will be very helpful to me.
import java.awt.*;
import java.awt.image.BufferedImage;
import com.programwithjava.basic.DrawingKit;
import java.util.Scanner;
public class Problem28 {
// maximum value of a sample
private static final int MAX_VALUE = 255;
//minimum value of a sample
private static final int MIN_VALUE = 0;
public BufferedImage convolve(int[][] kernel, BufferedImage inputImage) {
}
public BufferedImage convolveInner(double center, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage1 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//inner pixels
for (int x = 1; x < width - 1; x++) {
for (int y = 1; y < height - 1; y ++) {
//get pixels at x, y
int colorValue = inputImage.getRGB(x, y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed() ;
int green = pixelColor.getGreen() ;
int blue = pixelColor.getBlue();
int innerred = (int) center*red;
int innergreen = (int) center*green;
int innerblue = (int) center*blue;
Color newPixelColor = new Color(innerred, innergreen, innerblue);
int newRgbvalue = newPixelColor.getRGB();
inputImage1.setRGB(x, y, newRgbvalue);
}
}
return inputImage1;
}
public BufferedImage convolveEdge(double edge, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//inner pixels
for (int x = 0; x < width - 1; x++) {
for (int y = 0; y < height - 1; y ++) {
//get pixels at x, y
int colorValue = inputImage.getRGB(x, y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed() ;
int green = pixelColor.getGreen() ;
int blue = pixelColor.getBlue();
int innerred = (int) edge*red;
int innergreen = (int) edge*green;
int innerblue = (int) edge*blue;
Color newPixelColor = new Color(innerred, innergreen, innerblue);
int newRgbvalue = newPixelColor.getRGB();
inputImage2.setRGB(x, y, newRgbvalue);
}
}
return inputImage2;
}
public BufferedImage convolveCorner(double corner, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage3 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//inner pixels
for (int x = 0; x < width - 1; x++) {
for (int y = 0; y < height - 1; y ++) {
//get pixels at x, y
int colorValue = inputImage.getRGB(x, y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed() ;
int green = pixelColor.getGreen() ;
int blue = pixelColor.getBlue();
int innerred = (int) corner*red;
int innergreen = (int) corner*green;
int innerblue = (int) corner*blue;
Color newPixelColor = new Color(innerred, innergreen, innerblue);
int newRgbvalue = newPixelColor.getRGB();
inputImage3.setRGB(x, y, newRgbvalue);
}
}
return inputImage3;
}
public static void main(String[] args) {
DrawingKit dk = new DrawingKit("Compositor", 1000, 1000);
BufferedImage p1 = dk.loadPicture("image/pattern1.jpg");
Problem28 c = new Problem28();
BufferedImage p5 = c.convolve();
dk.drawPicture(p5, 0, 100);
}
}
I changed the code a bit but the output comes out as black. What did I do wrong:
import java.awt.*;
import java.awt.image.BufferedImage;
import com.programwithjava.basic.DrawingKit;
import java.util.Scanner;
public class Problem28 {
// maximum value of a sample
private static final int MAX_VALUE = 255;
//minimum value of a sample
private static final int MIN_VALUE = 0;
public BufferedImage convolve(int[][] kernel, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage1 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//for every pixel
for (int x = 0; x < width; x ++) {
for (int y = 0; y < height; y ++) {
int colorValue = inputImage.getRGB(x,y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed();
int green = pixelColor.getGreen();
int blue = pixelColor.getBlue();
double gray = 0;
//multiply every value of kernel with corresponding image pixel
for (int i = 0; i < 3; i ++) {
for (int j = 0; j < 3; j ++) {
int imageX = (x - 3/2 + i + width) % width;
int imageY = (x -3/2 + j + height) % height;
int RGB = inputImage.getRGB(imageX, imageY);
int GRAY = (RGB) & 0xff;
gray += (GRAY*kernel[i][j]);
}
}
int out;
out = (int) Math.min(Math.max(gray * 1, 0), 255);
inputImage1.setRGB(x, y, new Color(out,out,out).getRGB());
}
}
return inputImage1;
}
public static void main(String[] args) {
int[][] newArray = {{1/9, 1/9, 1/9}, {1/9, 1/9, 1/9}, {1/9, 1/9, 1/9}};
DrawingKit dk = new DrawingKit("Problem28", 1000, 1000);
BufferedImage p1 = dk.loadPicture("image/pattern1.jpg");
Problem28 c = new Problem28();
BufferedImage p2 = c.convolve(newArray, p1);
dk.drawPicture(p2, 0, 100);
}
}
Welcome ewuzz! I wrote a convolution using CUDA about a week ago, and the majority of my experience is with Java, so I feel qualified to provide advice for this problem.
Rather than writing all of the code for you, the best way to solve this large program is to discuss individual elements. You mentioned you are very new to programming. As the programs you write become more complex, it's essential to write small working snippets before combining them into a large successful program (or iteratively add snippets). With this being said, it's already apparent you're trying to debug a ~100 line program, and this approach will cost you time in most cases.
The first point to discuss is the general approach you mentioned. If you think about the program, what is the simplest and most repeated step? Obviously this is the kernel/mask step, so we can start from here. When you convolute each pixel, you are performing a similar option, regardless of the position (corner, edge, inside). While there are special steps necessary for these edge cases, they share similar underlying steps. If you try to write code for each of these cases separately, you will have to update the code in multiple (three) places with each adjustment and it will make the whole program more difficult to grasp.
To support my point above, here's what happened when I pasted your code into IntelliJ. This illustrates the (yellow) red flag of using the same code in multiple places:
The concrete way to fix this problem is to combine the three convolve methods into a single one and use if statements for edge-cases as necessary.
Our pseudocode with this change:
convolve(kernel, inputImage)
for each pixel in the image
convolve the single pixel and check edge cases
endfor
end
That seems pretty basic right? If we are able to successfully check edge cases, then this extremely simple logic will work. The reason I left it so general above to show how convolve the single pixel and check edge cases is logically grouped. This means it's a good candidate for extracting a method, which could look like:
private void convolvePixel(int x, int y, int[][] kernel, BufferedImage input, BufferedImage output)
Now to implement our method above, we will need to break it into a few steps, which we may then break into more steps if necessary. We'll need to look at the input image, if possible for each pixel accumulate the values using the kernel, and then set this in the output image. For brevity I will only write pseudocode from here.
convolvePixel(x, y, kernel, input, output)
accumulation = 0
for each row of kernel applicable pixels
for each column of kernel applicable pixels
if this neighboring pixel location is within the image boundaries then
input color = get the color at this neighboring pixel
adjusted value = input color * relative kernel mask value
accumulation += adjusted value
else
//handle this somehow, mentioned below
endif
endfor
endfor
set output pixel as accumulation, assuming this convolution method does not require normalization
end
The pseudocode above is already relatively long. When implementing you could write methods for the if and the else cases, but it you should be fine with this structure.
There are a few ways to handle the edge case of the else above. Your assignment probably specifies a requirement, but the fancy way is to tile around, and pretend like there's another instance of the same image next to this input image. Wikipedia explains three possibilities:
Extend - The nearest border pixels are conceptually extended as far as necessary to provide values for the convolution. Corner pixels are extended in 90° wedges. Other edge pixels are extended in lines.
Wrap - (The method I mentioned) The image is conceptually wrapped (or tiled) and values are taken from the opposite edge or corner.
Crop - Any pixel in the output image which would require values from beyond the edge is skipped. This method can result in the output image being slightly smaller, with the edges having been cropped.
A huge part of becoming a successful programmer is researching on your own. If you read about these methods, work through them on paper, run your convolvePixel method on single pixels, and compare the output to your results by hand, you will find success.
Summary:
Start by cleaning-up your code before anything.
Group the same code into one place.
Hammer out a small chunk (convolving a single pixel). Print out the result and the input values and verify they are correct.
Draw out edge/corner cases.
Read about ways to solve edge cases and decide what fits your needs.
Try implementing the else case through the same form of testing.
Call your convolveImage method with the loop, using the convolvePixel method you know works. Done!
You can look up pseudocode and even specific code to solve the exact problem, so I focused on providing general insight and strategies I have developed through my degree and personal experience. Good luck and please let me know if you want to discuss anything else in the comments below.
Java code for multiple blurs via convolution.

How do I flip an image upside-down?

I was wondering if I could find some help on this problem. I was asked to use an image ("corn.jpg"), and flip it entirely upside down. I know I need to write a program which will switch pixels from the top left corner with the bottom left, and so on, but I wasn't able to get my program to work properly before time ran out. Could anyone provide a few tips or suggestions to solve this problem? I'd like to be able to write my code out myself, so suggestions only please. Please note that my knowledge of APImage and Pixel is very limited. I am programming in Java.
Here is what I managed to get done.
import images.APImage;
import images.Pixel;
public class Test2
{
public static void main(String [] args)
{
APImage image = new APImage("corn.jpg");
int width = image.getImageWidth();
int height = image.getImageHeight();
int middle = height / 2;
//need to switch pixels in bottom half with the pixels in the top half
//top half of image
for(int y = 0; y < middle; y++)
{
for (int x = 0; x < width; x++)
{
//bottom half of image
for (int h = height; h > middle; h++)
{
for(int w = 0; w < width; w++)
{
Pixel bottomHalf = image.getPixel(h, w);
Pixel topHalf = image.getPixel(x, y);
//set bottom half pixels to corresponding top ones?
bottomHalf.setRed(topHalf.getRed());
bottomHalf.setGreen(topHalf.getGreen());
bottomHalf.setBlue(topHalf.getBlue());
//set top half pixels to corresponding bottom ones?
topHalf.setRed(bottomHalf.getRed());
topHalf.setGreen(bottomHalf.getGreen());
topHalf.setBlue(bottomHalf.getBlue());
}
}
}
}
image.draw();
}
}
Thank you for your help!
See Transforming Shapes, Text, and Images.
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class FlipVertical {
public static BufferedImage getFlippedImage(BufferedImage bi) {
BufferedImage flipped = new BufferedImage(
bi.getWidth(),
bi.getHeight(),
bi.getType());
AffineTransform tran = AffineTransform.getTranslateInstance(0, bi.getHeight());
AffineTransform flip = AffineTransform.getScaleInstance(1d, -1d);
tran.concatenate(flip);
Graphics2D g = flipped.createGraphics();
g.setTransform(tran);
g.drawImage(bi, 0, 0, null);
g.dispose();
return flipped;
}
FlipVertical(BufferedImage bi) {
JPanel gui = new JPanel(new GridLayout(1,2,2,2));
gui.add(new JLabel(new ImageIcon(bi)));
gui.add(new JLabel(new ImageIcon(getFlippedImage(bi))));
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) throws AWTException {
final Robot robot = new Robot();
Runnable r = new Runnable() {
#Override
public void run() {
final BufferedImage bi = robot.createScreenCapture(
new Rectangle(0, 660, 200, 100));
new FlipVertical(bi);
}
};
SwingUtilities.invokeLater(r);
}
}
Whenever you're swapping variables, if your language doesn't allow for simultaneous assignment (and Java doesn't), you need to use a temporary variable.
Consider this:
a = 1;
b = 2;
a = b; // a is now 2, just like b
b = a; // b now uselessly becomes 2 again
Rather than that, do this:
t = a; // t is now 1
a = b; // a is now 2
b = t; // b is now 1
EDIT: And also what #vandale says in comments :P
If you are able to use the Graphics class, the following may be of use:
http://www.javaworld.com/javatips/jw-javatip32.html
And the Graphics class documentation:
http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html
Instead of using
Pixel bottomHalf = image.getPixel(h, w);
Pixel topHalf = image.getPixel(x, y);
//set bottom half pixels to corresponding top ones?
bottomHalf.setRed(topHalf.getRed());
bottomHalf.setGreen(topHalf.getGreen());
bottomHalf.setBlue(topHalf.getBlue());
//set top half pixels to corresponding bottom ones?
topHalf.setRed(bottomHalf.getRed());
topHalf.setGreen(bottomHalf.getGreen());
topHalf.setBlue(bottomHalf.getBlue());
You should have stored the bottomHalf's RGB into a temporary Pixel and used that to set topHalf after replacing bottomHalf's values (if you follow). You could have also really used something like this.... assuming your pixel operates on integer rgb values (which would have improved your main method).
private static final Pixel updateRGB(Pixel in, int red, int green, int blue) {
in.setRed(red); in.setGreen(green); in.setBlue(blue);
}
You want to flip the image upside down, not swap the top and bottom half.
The loop could look like this.
int topRow = 0;
int bottomRow = height-1;
while(topRow < bottomRow) {
for(int x = 0; x < width; x++) {
Pixel t = image.getPixel(x, topRow);
image.setPixel(x, topRow, image.getPixel(x, bottomRow));
image.setPixel(x, bottomRow, t);
}
topRow++;
bottomRow--;
}

Why is the first sprite from the next row invisible?

What I'm trying to do
Convert my sprite sheet into separate buffered images, of which, each will be stored in a an array. The way I'm doing is from the top, down and from left to right.
The issue:
When I go through all the elements and get to the 1st element of the next row. The image is blank, however, all elements following show as intended.
Illustration:
Note: The location is the same for each element.
Sprite sheet:
Link: http://imageshack.us/photo/my-images/153/ljsh.png/
As it appears:
Link: "http://imageshack.us/photo/my-images/194/t3be.png/"
Anyone can use the sprite sheet if they want to.
Need more reputation for the images. :/
Code:
Note: I'm still very new to Java, so please, be gentle ;)
I think the problem is within the for loop that's in the loadSpriteSheet method.
Although what the cause is exactly, I have no idea.
How it works, from my understanding is that:
Loads sprite sheet image.
Array of buffered images is created based on the amount of rows and columns input by user.
The size is calculated SizeX = image.width / columns, SizeY = image.height / rows.
Graphics object draws to the current element in the array.
The sprite sheet is moved -SizeX.
The next element is drawn.
Repeats until x = columns.
Starts next row, sprite sheet is moved -SizeY.
Continues the same as before.
The "System.out" part shows the location of tX and tY exactly where I would expect them to be.
public class SpriteSheet extends ImageObject {
// Variables
protected BufferedImage[] spriteSheet;
protected AffineTransform sprSheetAt;
// Getters
public int getLength() {return spriteSheet.length;}
// Setters
// Constructor
public SpriteSheet(JFrame a) {
super(a);
}
public void loadSpriteSheet(String filename, int rows, int columns) {
try {
image = ImageIO.read(new FileInputStream(filename));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
sprSheetAt = AffineTransform.getTranslateInstance(0, 0);
// Size of sprite image.
int spriteSX = image.getWidth() / columns;
int spriteSY = image.getHeight() / rows;
int tX = 0;
int tY = 0;
spriteSheet = new BufferedImage[rows * columns];
int spriteInd = 0;
for(int y = 0; y < rows; y++) {
for(int x = 0; x < columns; x++) {
Graphics2D g;
if(spriteInd >= spriteSheet.length) {
break;
}
spriteSheet[spriteInd] = new BufferedImage(spriteSX, spriteSY, BufferedImage.TYPE_INT_ARGB);
g = spriteSheet[spriteInd].createGraphics();
g.drawImage(image, sprSheetAt, null);
g.dispose();
System.out.println(spriteInd + ", tX: " + tX + ", tY: " + tY);
tX -= spriteSX;
spriteInd++;
sprSheetAt.setToTranslation(tX, tY);
}
tX = 0;
tY -= spriteSY;
}
}
public void drawSprite(Graphics2D g, int spriteInd) {
g2d = g;
if(alive) {
g2d.drawImage(spriteSheet[spriteInd], 0, 0, frame);
}
}
}
I hope I explained this clearly, my apologies if I have not.
Thank you in advanced for the help.
Upon looking again, at other sprite/sprite sheet related questions, I came across BufferedImage.getSubimage. (I noticed just before I posted this that it was suggested)
And thus I immediately implemented it.
I changed the inner most for loop that's within the loadSpriteSheet method to.
for(int y = 0; y < rows; y++) {
for(int x = 0; x < columns; x++) {
spriteSheet[spriteInd] = new BufferedImage(spriteSX, spriteSY, BufferedImage.TYPE_INT_ARGB);
System.out.println(spriteInd + ", tX: " + tX + ", tY: " + tY);
spriteSheet[spriteInd] = image.getSubimage(tX, tY, spriteSX, spriteSX);
tX += spriteSX;
spriteInd++;
}
tX = 0;
tY += spriteSY;
}
It's much shorter and actually works now :D
So from this I have learned a few things.
1. Do more googling and general searching.
2. Check the api more.
3. And wait until I've spent a long time searching to ask :)
Despite this, I would like to know what the cause of the issue was.

Taking a picture as input, Make grey scale and & then outputting

I'm attempting to take a picture as input, then manipulate said picture (I specifically want to make it greyscale) and then output the new image. This is a snippet of the code that I'm editing in order to do so but I'm getting stuck. Any ideas of what I can change/do next. Greatly appreciated!
public boolean recieveFrame (Image frame) {
int width = frame.width();
int height = frame.height();
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
Color c1 = frame.get(i, j);
double greyScale = (double) ((Color.red *.3) + (Color.green *.59) + (Color.blue * .11));
Color newGrey = Color.greyScale(greyScale);
frame.set(i, j, newGrey);
}
}
boolean shouldStop = displayImage(frame);
return shouldStop;
}
I'm going to try to stick as close as possible to what you already have. So, I'll assume that you are looking for how to do pixel-level processing on an Image, rather than just looking for a technique that happens to work for converting to greyscale.
The first step is that you need the image to be a BufferedImage. This is what you get by default from ImageIO, but if you have some other type of image, you can create a BufferedImage and paint the other image into it first:
BufferedImage buffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffer.createGraphics();
g.drawImage(image, 0, 0);
g.dispose()
Then, you can operate on the pixels like this:
public void makeGrey(BufferedImage image) {
for(int x = 0; x < image.getWidth(); ++x) {
for(int y = 0; y < image.getHeight(); ++y) {
Color c1 = new Color(image.getRGB(x, y));
int grey = (int)(c1.getRed() * 0.3
+ c1.getGreen() * 0.59
+ c1.getBlue() * .11
+ .5);
Color newGrey = new Color(grey, grey, grey);
image.setRGB(x, y, newGrey.getRGB());
}
}
}
Note that this code is horribly slow. A much faster option is to extract all the pixels from the BufferedImage into an int[], operate on that, and then set it back into the image. This uses the other versions of the setRGB()/getRGB() methods that you'll find in the javadoc.

Categories