Creating 3x3 checkerboard over a picture using Graphics2D - java

I want to create an overlay of a 3x3 checkerboard, where the non-solid squares should be transparent.
I don't want to iterate the pixels, but rather just draw squares using Graphics2D to create a checkerboard. (Do I need a for loop, an if statement, or both?)
Here's my code so far:
Picture myPict = new Picture(myPathName);
myPict.show();
Graphics2D graphicsObj = myPict.getGraphics2D();
final int WIDTH = myPict.getWidth() / 3;
final int HEIGHT = myPict.getHeight() / 3;
for (int i = 0; i > WIDTH; i = WIDTH * 2) {
Rectangle2D.Double shape1 = new Rectangle2D.Double(WIDTH, HEIGHT, 0, 0);
graphicsObj.draw(shape1);
}

I'd use a combined (double) for loop/if statement for drawing the solid parts of the checkerboard. In pseudo-code it might be expressed as:
draw image
for each row {
for each column {
if 'odd' square number {
graphics fill rectangle
}
}
}

Related

How can I add a border to an image in Java?

The border needs to be made out of the closest pixel of the given image, I saw some code online and came up with the following. What am I doing wrong? I'm new to java, and I am not allowed to use any methods.
/**
* TODO Method to be done. It contains some code that has to be changed
*
* #param enlargeFactorPercentage the border in percentage
* #param dimAvg the radius in pixels to get the average colour
* of each pixel for the border
*
* #return a new image extended with borders
*/
public static BufferedImage addBorders(BufferedImage image, int enlargeFactorPercentage, int dimAvg) {
// TODO method to be done
int height = image.getHeight();
int width = image.getWidth();
System.out.println("Image height = " + height);
System.out.println("Image width = " + width);
// create new image
BufferedImage bi = new BufferedImage(width, height, image.getType());
// copy image
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixelRGB = image.getRGB(x, y);
bi.setRGB(x, y, pixelRGB);
}
}
// draw top and bottom borders
// draw left and right borders
// draw corners
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixelRGB = image.getRGB(x, y);
for (enlargeFactorPercentage = 0; enlargeFactorPercentage < 10; enlargeFactorPercentage++){
bi.setRGB(width, enlargeFactorPercentage, pixelRGB * dimAvg);
bi.setRGB(enlargeFactorPercentage, height, pixelRGB * dimAvg);
}
}
}
return bi;
I am not allowed to use any methods.
What does that mean? How can you write code if you can't use methods from the API?
int enlargeFactorPercentage
What is that for? To me, enlarge means to make bigger. So if you have a factor of 10 and your image is (100, 100), then the new image would be (110, 110), which means the border would be 5 pixels?
Your code is creating the BufferedImage the same size as the original image. So does that mean you make the border 5 pixels and chop off 5 pixels from the original image?
Without proper requirements we can't help.
#return a new image extended with borders
Since you also have a comment that says "extended", I'm going to assume your requirement is to return the larger image.
So the solution I would use is to:
create the BufferedImage at the increased size
get the Graphics2D object from the BufferImage
fill the entire BufferedImage with the color you want for the border using the Graphics2D.fillRect(….) method
paint the original image onto the enlarged BufferedImage using the Graphics2D.drawImage(…) method.
Hello and welcome to stackoverflow!
Not sure what you mean with "not allowed using methods". Without methods you can not even run a program because the "thing" with public static void main(String[] args) is a method (the main method) and you need it, because it is the program starting point...
But to answer your question:
You have to load your image. A possibility would be to use ImageIO. Then you create a 2D graphics object and then you can to drawRectangle() to create a border rectangle:
BufferedImage bi = //load image
Graphics2D g = bi.getGraphics();
g.drawRectangle(0, 0, bi.getHeight(), bi.getWidth());
This short code is just a hint. Try it out and read the documentation from Bufferedimage see here and from Graphics2D
Edit: Please notice that this is not quite correct. With the code above you overdraw the outer pixel-line from the image. If you don't want to cut any pixel of, then you have to scale it up and draw with bi.getHeight()+2 and bi.getWidth()+2. +2 because you need one pixel more at each side of the image.

creating tiles using bufferedImage in java

public static BufferedImage split(BufferedImage img) {
BufferedImage pic = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = pic.getGraphics();
int width = 2000/2;
int height = 2000/2;
int imageW = pic.getWidth();
int imageH = pic.getHeight();
// Tile the image to fill our area.
for (int x = 0; x < width; x += imageW) {
for (int y = 0; y < height; y += imageH) {
g.drawImage(pic, x, y, null);
}
}
return pic ;
}
the point of the code is to create a tile of 2x2 of the image (same image reproduce at a smaller size in a 2x2 grid). i want to updated pic so i can print it onto a jpanel. all i get is black image. can someone tell me whats wrong with the code. or tell me how to create a better piece of code.
I want to make four smaller images of the original and place it in a grid of 2x2 that is the same size as the original image
Something like...
public static BufferedImage split(BufferedImage img) {
BufferedImage pic = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = pic.getGraphics();
int width = pic.getWidth() / 4;
int height = pic.getHeight() / 4;
Image scaled = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
// Tile the image to fill our area.
for (int x = 0; x < pic.getWidth(); x += width) {
for (int y = 0; y < pic.getHeight(); y += height) {
g.drawImage(scaled, x, y, null);
}
}
g.dispose();
return pic;
}
You may also like to have a look at Java: maintaining aspect ratio of JPanel background image and Quality of Image after resize very low -- Java for more details about how you can improve the scaling algorithm

Draw image using rectangles

I wrote a program that reads an image from command line and want to read each pixel to draw a rectangle of the respective colour to "recreate" the image from rectangles.
However, although the rectangles have the correct size, every pixel seems to be black. At least, what I see in the output panel is a black picture that has the same size as the input picture.
class AppDrawPanel extends JPanel {
private BufferedImage bi;
/* ... */
public void loadAPPImage( String s ) throws IOException{
bi = ImageIO.read(new File(s));
}
#Override
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D) g;
int w = bi.getWidth();
int h = bi.getHeight();
for( int x = 0; x < w; x++){
for ( int z = 0; z < h; z++ ){
Color c = new Color(bi.getRGB(x, z));
super.setForeground(c);
g2.fillRect(x, z, 3, 3);
}
}
}
}
And the main function:
public static void main( String[] args ) throws IOException{
/* ... */
AppDrawPanel draw = new AppDrawPanel();
draw.loadAPPImage(args[0]);
frame.add(draw);
/* ... */
}
where /* ... */ represents code that has nothing to do with drawing the rectangles or reading the image.
In this related example, the width and height of each pixel is scaled by an arbitrary factor of 10. The method drawImage() then scales the image to the component's preferred size. As an exercise, override getPreferredSize() to return an appropriate dimension:
new Dimension(imgW * 10, imgH * 10);
Also consider making the arbitrary factor a class-level property.

Java: basic plotting, drawing a point/dot/pixel

I need to just have a panel inside of which i'd be able to draw. I want to be able to draw pixel by pixel.
ps: I don't need lines/circles other primitives.
pps: the graphics library does not really matter, it can be awt, swing, qt.. anything. I just want to have something that is usually represented by Bufferedimage or somethign like that where you set colors of single pixels and then render it to the screen.
An example of one way to do it:
// Create the new image needed
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB );
for ( int rc = 0; rc < height; rc++ ) {
for ( int cc = 0; cc < width; cc++ ) {
// Set the pixel colour of the image n.b. x = cc, y = rc
img.setRGB(cc, rc, Color.BLACK.getRGB() );
}//for cols
}//for rows
and then from within overridden paintComponent(Graphics g)
((Graphics2D)g).drawImage(img, <args>)
represented by Bufferedimage ..
I suggest a BufferedImage for that, displayed..
..or something like that where you set colors of single pixels and then render it to the screen.
..in a JLabel - as seen in this answer.
Of course, once we have an instance of BufferedImage, we can setRGB(..).
If you honestly need to render pixel-by-pixel, I have done this at-length for hotspot visualization piece of software I wrote for a research lab.
What you want is BufferedImage.setRGB(..) -- if you are drawing pixel-by-pixel, I assume you have implemented an algorithm that will render the RGB values for each pixel (much like we did with the heat-maps). This is what we used in an old IE-compatible Applet back in the day. Worked like a charm and was relatively fast given what it was doing.
Unfortunately any time you manipulate the RGB values directly in a BufferedImage, it will become uncached by the backing video memory.
Since Java 7 though, I heard that the underlying J2D implementation will make an attempt at re-caching the image into video memory once the manipulations stop and rendering is done over-and-over again -- for example, while you are rendering the heat map it is not accelerated, but once it is rendered, as you drag the window around and work with the app, the backing image data can become re-accelerated.
If you want to do something quickly, you can just use the Graphics methods setColor and drawLine. For example:
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Set the colour of pixel (x=1, y=2) to black
g.setColor(Color.BLACK);
g.drawLine(1, 2, 1, 2);
}
I have used this technique and it wasn't terribly slow. I haven't compared it to using BufferedImage objects.
A little late here, but you could always do it the way Java game programmers do, with a Screen class:
public class Screen {
private int width, height;
public int[] pixels;
public Screen(int width, int height) {
this.width = width;
this.height = height;
pixels = new int[width * height];
}
public void render() {
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
pixels[x + y * width] = 0xFFFFFF; //make every pixel white
}
}
}
public void clear() {
for(int i = 0; i < pixels.length; i++) {
pixels[i] = 0; //make every pixel black
}
}
}
And then in your main class:
private Screen screen;
private BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
screen.clear();
screen.render();
for(int i = 0; i < pixels.length; i++) {
pixels[i] = screen.pixels[i];
}
Graphics g = bs.getDrawGraphics();
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
g.dispose();
bs.show();
}
That should work, I think.
I'm coming with a solution which is fast and yet compatible with Graphics2D, in the sense that it doesn't draw from a detached pixel array.
fun drawLand(area: Rectangle): BufferedImage {
val height = area.height
val image = BufferedImage(area.width, height, BufferedImage.TYPE_INT_ARGB)
val g2 = image.createGraphics()
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)
g2.background = Color.PINK
g2.clearRect(area.x, area.y, area.width, area.height)
val squares: Sequence<Square> = repo.getSquares(area)
val pixels: IntArray = (image.raster.dataBuffer as DataBufferInt).data
for (square in squares) {
val color = square.color or OPAQUE // 0xFF000000.toInt()
val base = square.location.y * height + square.location.x
pixels[base] = color
}
g2.dispose()
return image
}
Legend:
In the background, the image is backed by an Array of some Java primitives, depending on BufferedImage.TYPE_.
Here I opted for TYPE_INT_ARGB, so each pixel is conveniently an Int. Then you can go row by row and tamper with the underlying pixels.

Rotate Buffered Image (diagonal Text)

(Sorry for the links, I'm new and I cannot post images)
I want to accomplish the following : create a table with the legends on the top, and in a diagonal way.
but I'm having some problems, I have the following image, and I'm trying to rotate it 45º (the result it's at the right),
Here is my code:
//just some labels
ArrayList<String> labels = new ArrayList<String>();
labels.add("Juan");
labels.add("QWERTYYY");
labels.add("ANA");
// margin
int margin=3;
//diagonal = 45º
// value to shift each label
int diagonalShift = (int)(cellSizeWidth / Math.sqrt(2d));
// height, width represent the size of the final image
// heightSub, widthSub represent the size of the image to be rotated taking into account the shift for each label
int widthSub = height + (diagonalShift * labels.size());
int heightSub = width;
// image to Display
BufferedImage image = new BufferedImage(height, width, BufferedImage.TYPE_INT_RGB);
Graphics2D imageGraphics = (Graphics2D) image.getGraphics();
// tempImage: subImage to rotate and place in image
BufferedImage tempImage = new BufferedImage(widthSub, heightSub, BufferedImage.TYPE_INT_RGB);
Graphics2D tempImageGraphics = (Graphics2D) tempImage.getGraphics();
tempImageGraphics.setColor(Color.BLUE);
tempImageGraphics.drawRect(0, 0, widthSub-1, heightSub-1);
// I'd like to use antialias, but it's giving bad results
// tempImageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
// drawing labels
// as we're designing a table cellSizeWidth and CellSizeHeight represent the dimensions for each cell
tempImageGraphics.setColor(Color.WHITE);
for (int i = 0; i < labels.size(); i++) {
String label = labels.get(i);
tempImageGraphics.drawString(label,
margin + (i * diagonalShift),
(int) (i * cellSizeWidth) + fontSize + centerDistance);
}
I tried the following:
//rotating
AffineTransform fontAfineTransform = new AffineTransform();
// fontAfineTransform.rotate(verticalTextDirection.rotationAngle());
which gives as result the image at the right in the second Image 2
so I need to apply a translation to get it to the right position
// Math.sqrt(2d) because I'm working with 45º and the height becomes the hypotenuse
// fontAfineTransform.translate(-height/Math.sqrt(2d),height/Math.sqrt(2d));
//drawing into image
imageGraphics.drawImage(tempImage, fontAfineTransform, null);
can someone please explain how the affineTransform works, or how can I get the text to be in a diagonal way.
Thanks

Categories