I have a draw function
public void drawBoard(Graphics g) {
int height = this.getHeight();
int width = this.getWidth();
int dx = width / 7;
int dy = height / 6;
for (int x = 0, row = 0; x <= width && row < gameboard.length; row++, x += dx) {
for (int col = 0, y = 0; y <= height&& col < gameboard[0].length; y += dy, col++) {
if (gameboard[row][col] == 0) {
g.setColor(Color.GRAY);
g.fillOval(y, x, dy, dx);
} else if (gameboard[row][col] == 1) {
g.setColor(Color.RED);
g.fillOval(y, x, dy, dx);
} else if(gameboard[row][col] == 1){
g.setColor(Color.BLACK);
g.fillOval(y, x, dy, dx);
} else if(gameboard[row][col]==3){
}else if(gameboard[row][col]==4){
}else if(gameboard[row][col]==5){
}else if(gameboard[row][col]==6){
}else if(gameboard[row][col]==7){
}else if(gameboard[row][col]==8){
}else if(gameboard[row][col]==9){
}
}
}
}
However for when gameboard[row][col]=3,4,...9 I want it to change that slot into a picture downloaded from the web. How do I do that?
I would prefer to do it without a URL definition and simply a get Document like thing in html where I have the photos saved in a file
First, you need to get your image as a BufferedImage. I suggest using the ImageIO class:
String imageFileName = "myTestFile.jpg"
BufferedImage img = ImageIO.read(((new File(imageFileName)).toURI()).toURL());
Next, you want to draw your image using the Graphics.drawImage() API. Your comment indicates that you think you'll need to scale the image, so use the appropriate drawImage method to do that. Using your Graphics object g from your code above, this might look like::
int oldWidth = img.getWidth();
int oldHeight = img.getHeight();
int newWidth = 10; //You decide this...
int newHeight = 10; //You decide this too...
g.drawImage(img, 0, 0, oldWidth, newWidth, 0, 0, newWidth, newHeight, null);
Oracle themselves have an applet which demonstrates the code for this approach, along with a number of other common operations you might want to do on images in their ImageDrawingApplet.java code
Related
I am currently trying to get my java program to load separate sprites from a sprite sheet. When I try to get The yellow square in this sprite sheet
.
However, what I get is this
.
Prior to this I was able to load and render an entire PNG file without problems, and I am unsure the reason for it not working. I put snippets of code that I use to load images, render images, and getting the subimage. I'm still somewhat new to java, so I'm not sure if there is a better solution to this
//The code I use to load a PNG as a BufferedImage
public BufferedImage loadImage(String path) {
try {
BufferedImage loadedImage = ImageIO.read(new FileInputStream(path));
BufferedImage formattedImage = new BufferedImage(loadedImage.getWidth(), loadedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
formattedImage.getGraphics().drawImage(loadedImage, 0, 0, null);
return formattedImage;
} catch (IOException e) {
e.printStackTrace();
return null;
}
//The code I use to render an image onto the screen
public void renderImage(BufferedImage image, int xpos, int ypos) {
int[] imgpixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
if (!(x + xpos > getScreenWidth() - 1) && !(y + ypos > getScreenHeight() - 1) && !(x + xpos < 0) && !(y + ypos < 0)) {
pixels[(x + xpos) + (y + ypos) * getScreenWidth()] = imgpixels[x + y * image.getWidth()];
}
}
}
}
//the code I used to get the subimage
public BufferedImage getImage(int index) {
int i = index % (row * col);
int x = tileX * (i % col);
int y = tileY * (i % row);
return spriteSheet.getSubimage(x, y, tileX, tileY);
//still does the same thing if I were to put in spriteSheet.getSubimage(0, 0, 16, 16)
}
I am implementing captcha feature in our project. Its basically Tapestry framework application. I am generating random alfa-numeric string and convert it to image and display it in web page.
Now what i need is, i want to add random noise like dots lines etc to make image with text unclear. How to proceed please help.
keeping the code for reference .
-- This method gives text captcha.
`
public String generateCaptcha() {
Random random = new Random();
int min = 4; // Inclusive
int max = 9; // Exclusive
int length = random.nextInt(max-min) + min;
StringBuilder captchaStringBuffer = new StringBuilder();
for (int i = 0; i < length; i++) {
int captchaNumber = Math.abs(random.nextInt()) % 60;
int charNumber = 0;
if (captchaNumber < 26) {
charNumber = 65 + captchaNumber;
}
else if (captchaNumber < 52){
charNumber = 97 + (captchaNumber - 26);
}
else {
charNumber = 48 + (captchaNumber - 52);
}
captchaStringBuffer.append((char)charNumber);
}
return captchaStringBuffer.toString();
}
`
-- This method converts generated captcha to Image with out any noise.
`
public void textToImage(String displayCode){
String text = displayCode;
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
Font font = new Font("Arial", Font.PLAIN, 48);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
int width = fm.stringWidth(text);
int height = fm.getHeight();
g2d.dispose();
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_DISABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_DEFAULT);
g2d.setFont(font);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "png", baos);
byte[] res=baos.toByteArray();
setBinaryImage("data:image/png;base64,"+Base64.encode(res));
} catch (IOException e) {
}
}
`
I am newbie so please tell in clear what ever you say.
Thanks in Advance :-)
When trying to obstruct the text that is being displayed, you can use:
Dots/Circles, spread randomly over the image with varying size and color
Lines, coming from a random point on the edge of the image to another point on the edge of the image. These can also vary in color and thickness.
As far as i know, you can use g2d.drawLine(x1, y1, x2, y2) to draw a line. Since you want it to go from the edge to another point on the edge, you have to limit your random-point-generation. You can use this approach:
public Point pointOnEdge(int width, int height) {
int side = (int) (Math.random() * 3); //0=top, 1=bot, 2=left, 3=right
int x = 0;
int y = 0;
switch(side) {
case 0:
//when on top, y is at the top of the image (0) and x is something in [0, width]
y = 0;
x = (int) (Math.random() * width);
break;
case 1:
//when on bottom, y is at the bottom of the image (image height) and x is something in [0, width]
y = height;
x = (int) (Math.random() * width);
case 2:
//when on left, x is at the left side (0) of the image and y is something in [0, height]
y = (int) (Math.random() * height);
x = 0;
break;
case 3:
//when on left, x is at the left side (0) of the image and y is something in [0, height]
y = (int) (Math.random() * height);
x = width;
break;
}
return new Point(x, y);
}
If you create two Points like that, and connect them with a line, then you have a pretty simple way of obstructing your Image Partially, thus distorting it.
Now to the Circles:
public void drawCircles(Graphics2D g2d, int width, int height) {
//draw 10 of them
for(int i = 0; i < 10; i++) {
//select a random size
int x = 10 + (int) (Math.random() * 10);
//draw circle at random position with the created size
g2d.fillOval((int) (Math.random() * width), (int) (Math.random() * height), x, x);
}
}
And like that you are now able to distort your image to make it hard to read.
I hope you have enough common code understanding to know where to put these function calls. If not, I can add it if nescessary.
EDIT 1
If you want a dotted Background for your Captcha, you can use this code before rendering the String or anything else:
boolean r = false;
boolean g = false;
for(int y = 0; y < height; y++) {
r = !r;
g = r;
for(int x = 0; x < width; x++) {
g = !g;
if(g) {
g2d.setColor(Color.GRAY);
}else {
g2d.setColor(Color.WHITE);
}
g2d.drawLine(x, y, x, y);
}
}
EDIT 2
I would recommend, that you use a different font. Then you dont have to do any streching. Good fonts for that are e.g. Gigi. You could also select a font randomly by using GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames() which returns all Fonts that Java has.
I am trying to properly rotate a sword in my 2D game. I have a sword image file, and I wish to rotate the image at the player's location. I tried using Graphics2D and AffineTransform, but the problem is that the player moves on a different coordinate plane, the Screen class, and the Graphics uses the literal location of the pixels on the JFrame. So, I realized that I need to render the sword by rotating the image itself, and then saving it into a pixel array for my screen class to render. However, I don't know how to do this. Here is the code for my screen rendering method:
public void render(double d, double yOffset2, BufferedImage image, int colour,
int mirrorDir, double scale, SpriteSheet sheet) {
d -= xOffset;
yOffset2 -= yOffset;
boolean mirrorX = (mirrorDir & BIT_MIRROR_X) > 0;
boolean mirrorY = (mirrorDir & BIT_MIRROR_Y) > 0;
double scaleMap = scale - 1;
for (int y = 0; y < image.getHeight(); y++) {
int ySheet = y;
if (mirrorY)
ySheet = image.getHeight() - 1 - y;
int yPixel = (int) (y + yOffset2 + (y * scaleMap) - ((scaleMap * 8) / 2));
for (int x = 0; x < image.getWidth(); x++) {
int xPixel = (int) (x + d + (x * scaleMap) - ((scaleMap * 8) / 2));
int xSheet = x;
if (mirrorX)
xSheet = image.getWidth() - 1 - x;
int col = (colour >> (sheet.pixels[xSheet + ySheet
* sheet.width])) & 255;
if (col < 255) {
for (int yScale = 0; yScale < scale; yScale++) {
if (yPixel + yScale < 0 || yPixel + yScale >= height)
continue;
for (int xScale = 0; xScale < scale; xScale++) {
if (x + d < 0 || x + d >= width)
continue;
pixels[(xPixel + xScale) + (yPixel + yScale)
* width] = col;
}
}
}
}
}
}
Here is one of my poor attempts to call the render method from the Sword Class:
public void render(Screen screen) {
AffineTransform at = new AffineTransform();
at.rotate(1, image.getWidth() / 2, image.getHeight() / 2);
AffineTransformOp op = new AffineTransformOp(at,
AffineTransformOp.TYPE_BILINEAR);
image = op.filter(image, null);
screen.render(this.x, this.y, image, SwordColor, 1, 1.5, sheet);
hitBox.setLocation((int) this.x, (int) this.y);
for (Entity entity : level.getEntities()) {
if (entity instanceof Mob) {
if (hitBox.intersects(((Mob) entity).hitBox)) {
// ((Mob) entity).health--;
}
}
}
}
Thank you for any help you can provide, and please feel free to tell me if theres a better way to do this.
You can rotate() the image around an anchor point, also seen here in a Graphics2D context. The method concatenates translate(), rotate() and translate() operations, also seen here as explicit transformations.
Addendum: It rotates the image, but how do I save the pixels of the image as an array?
Once you filter() the image, use one of the ImageIO.write() methods to save the resulting RenderedImage, for example.
I'm constructing a flood fill algorithm that will hopefully, eventually, find a face in the center of a photograph based on the color at the exact center, and similar colors surrounding that. At the moment, however, my algorithm should take in any color within the bounds of the int array and transfer it over to a holder array, essentially making a copy of the original image. But this isn't working, and is resulting in a black image when I run it. Can anyone see the problem I'm missing?
public class TemplateMaker {
public static void main(String[] args) throws IOException {
importPhoto();
}
public static void importPhoto() throws IOException {
File imgPath = new File("/Pictures/BaseImage.JPG");
BufferedImage bufferedImage = ImageIO.read(imgPath);
establishArray(bufferedImage);
}
public static void establishArray(BufferedImage bufferedImage) throws IOException {
//byte[] pixels = hugeImage.getData();
int width = bufferedImage.getWidth();
System.out.println(width);
int height = bufferedImage.getHeight();
System.out.println(height);
int[][] result = new int[height][width];
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++) {
result[i][j] = bufferedImage.getRGB(j, i);
}
findFace(result);
}
public static void findFace(int[][] image) throws IOException {
int height = image.length;
int width = image[0].length;
Color centerStart = new Color(image[height / 2][width / 2], true);
System.out.println(centerStart.getRGB());
System.out.println(Color.blue.getRGB());
int[][] filled = new int[height][width];
floodFill(height / 2, width / 2, centerStart, image, filled, height, width);
//construct the filled array as image.
BufferedImage bufferImage2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < height; x++) {
for (int y = 0; y < width; y++) {
bufferImage2.setRGB(y, x, filled[x][y]);
}
}
//save filled array as image file
File outputfile = new File("/Pictures/saved.jpg");
ImageIO.write(bufferImage2, "jpg", outputfile);
}
public static int[][] floodFill(int x, int y, Color targetColor, int[][] image, int[][] filled, int height, int width) {
//execute something similar once algorithm works.
// if (image[x][y] < targetColor.getRGB()/2 || image[x][y] > targetColor.getRGB()*2) return filled;
if (image[x][y] == Color.blue.getRGB()) {
return filled;
}
if (image.length < 0 || image[0].length < 0 || image.length >= height || image[0].length >= width) {
return filled;
}
filled[x][y] = image[x][y];
image[x][y] = Color.blue.getRGB();
floodFill(x - 1, y, targetColor, image, filled, height, width);
floodFill(x + 1, y, targetColor, image, filled, height, width);
floodFill(x, y - 1, targetColor, image, filled, height, width);
floodFill(x, y + 1, targetColor, image, filled, height, width);
return filled;
}
}
You create int[][] called filled and then call floodFill(...) which returns without doing anything to the array. image.length is always equal to height and image[0].length is always equal to width, so it always returns from the second if statement.
You then build a BufferedImage from that blank array and write it to a file. All of the values in the array are initialized to 0, which gives you black.
Changing the for loop in findFace(..) to the below will save out the original image from your holder array.
for (int x = 0; x < height; x++) {
for (int y = 0; y < width; y++) {
bufferImage2.setRGB(y, x, image[x][y]);
}
}
But I'm not sure if this is what you're asking or not.
Edit: Try this out and see if it sends you in the right direction:
public static int[][] floodFill(int x, int y, Color targetColor, int[][] image, int[][] filled, int height, int width) {
//execute something similar once algorithm works.
// if (image[x][y] < targetColor.getRGB()/2 || image[x][y] > targetColor.getRGB()*2) return filled;
if (image[x][y] == Color.blue.getRGB()) {
System.out.println("returned if 1");
return filled;
}
/*if (image.length < 0 || image[0].length < 0 || image.length >= height || image[0].length >= width) {
return filled;
}*/
filled[x][y] = image[x][y];
image[x][y] = Color.blue.getRGB();
if (x - 1 <= 0 && y < width) {
floodFill(x - 1, y, targetColor, image, filled, height, width);
}
if(x + 1 < height && y >= 0 && y < width) {
floodFill(x + 1, y, targetColor, image, filled, height, width);
}
if(x >= 0 && x < height && y - 1 <= 0) {
floodFill(x, y - 1, targetColor, image, filled, height, width);
}
if(x >= 0 && x < height && y + 1 < width) {
floodFill(x, y + 1, targetColor, image, filled, height, width);
}
return filled;
}
Alright, so I am having a problem writing this program. I have the first part done but I don't know how to finish it. I've tried different solutions and everything, but yet I still have no clue. Here is what I have so far. What I need to do is make this where it will start in all four corners.
public void paintComponent( Graphics g )
{
super.paintComponent( g );
int width = getWidth();
int height = getHeight();
int number, x, y, dx, dy;
x = 0;
y = height;
number = 15;
dx = width / number;
dy = height / number;
for ( int i = 1; i < number; i++ )
{
x += dx;
y -= dy;
g.drawLine( 0, 0, x, y );
}
}
I gather that you want to draw a fan-out of 15 lines from each corner to the facing diagonal. I'd suggest writing a routine to draw a fan from a point to an arbitrary line segment and then use that:
drawFan(Graphics g,
int number, // number of fan lines
int x0, int y0, // coordinates of the point
int sx, int sy, // coordinates of the line segment start
int ex, int ey) // coordinates of the line segment end
{
int x = sx,
y = sy,
dx = (ex - sx) / number,
dy = (ey - sy) / number;
for (int i = 1; i < number; ++i) {
x += dx;
y += dy;
g.drawLine(x0, y0, x, y);
}
}
You can then call this with the appropriate values for each corner and diagonal.
public void paintComponent( Graphics g )
{
super.paintComponent( g );
int width = getWidth();
int height = getHeight();
drawFan(g, 15, 0, 0, 0, height, width, 0); // top left corner
drawFan(g, 15, 0, height, 0, 0, width, height); // bottom left corner
drawFan(g, 15, width, height, 0, height, width, 0); // bottom right corner
drawFan(g, 15, width, 0, 0, 0, width, height); // top right corner
}
Here is the solution, my suggestion is to understand how the coordinate system works in Java then It'll be easy.
public void paintComponent( Graphics g ){
super.paintComponent(g);
int widthX = getWidth();
int heightY = getHeight();
int num, i, j;
num = 15;
i = 0;
j = 15;
while( i != 16 && j != -1 ){
g.drawLine( 0, 0, widthX*i/num, heightY*j/num );
g.drawLine( widthX*i/num, heightY*j/num, widthX, heightY );
g.drawLine( widthX*i/num, heightY*i/num, widthX, 0);
g.drawLine( widthX*j/num, heightY*j/num, 0, heightY);
i++;
j--;
}//end while
}//end method paintComponent