Why doesn't my code flip image horizontally? - java

public void flipImageHorizontally(){
this.redisplayImage();
for(int x = 0; x < this.image.length; x++)
for(int y = 0; y < this.image[0].length; y++){
this.image[x][y] = this.image[x][this.image[0].length - 1 - y];
}
}
The code runs but it doesn't perform the action intended. It is supposed to flip the image horizontally, but instead it only flips half of the image.

Let's say you have an image two pixels wide and one pixel high:
1 2
After the first iteration of your loop, the end pixel will be swapped to the beginning (image[0][0] = image[0][2 - 1 - 0];):
2 2
But now you lost the original value of image[0][0]! So when you do the swap image[0][1] = image[0][2 - 1 - 1];, you are copying the second half of the image back to itself.
The right answer is to use a buffer so you don't overwrite the swap:
for(int y = 0; y < this.image[0].length / 2; y++) {
int buffer = this.image[x][y];
this.image[x][y] = this.image[x][this.image[0].length - 1 - y];
this.image[x][this.image[0].length - 1 - y] = buffer;
}
Integer truncation ensures that this.image[0].length / 2 is an efficient bound. For even numbers, you iterate exactly the first half. For odd numbers, you iterate the first half, not including the middle pixel. That's a good thing, because the middle does not need to be swapped.

You need to iterate up to the middle, and swap pixels that are on the left with pixels that are on the right. Otherwise you end up overwriting your changes.
public void flipImageHorizontally() {
this.redisplayImage();
for(int x = 0; x < this.image.length; x++) {
for(int y = 0; y < this.image[x].length / 2; y++) {
int pixel = this.image[x][y]; // assuming int
this.image[x][y] = this.image[x][this.image[x].length - 1 - y];
this.image[x][this.image[x].length - 1 - y] = pixel;
}
}
}
In this code
the pixel variable temporarily holds the value on the left;
the value on the left gets assigned the value on the right;
the value on the right gets the value that was originally on the left (i.e. whatever is in pixel).
Notes:
I maintained your naming of x and y, even though it's counter-intuitive because it makes it look like you're performing a vertical flip instead of a horizontal one.
I don't know the data type of the array; I assumed int, but it might be a float array, Pixel objects, or something else.
I don't know what this.redisplayImage(); is supposed to do, and whether it's in the right location.

Related

I don't understand what the multiplication in q.offer(x*m + y) does and what the while loop is doing and everything in the code

Can someone explain this code in detail, I don't understand what the multiplication in q.offer(x*m + y) does and what the while loop is doing. This is the requirements for the program:
Starting from a given location on the grid, experiment explores the grid, expanding and labeling all of the cells in a single colony originating from the starting location. Taking as input a grid, the coordinates of a starting location, and a label, experiment will either label that location and all its neighbors or do nothing, depending on the presence or absence of a cell at the given location, respectively; either way, experiment is required to return the size of the labeled colony.
(c) The program is responsible for ensuring that experiment is called start- ing at every location on the grid storing a 1. The reason is that experiment locates only a single colony.
For example, using the first grid above and calling experiment for the first time on the location at the top row and forth column will modify the grid only at the locations labeled A, leaving all the other locations intact.
Once every grid location storing a 1 has been colonized, the program freezes the grid by replacing the 0s on the grid with s (dashes) .
(d) The program is responsible for creating an initial grid of random number of rows and columns in the range [5-20], and for filling the grid randomly with 0s and 1s.
(e) The program is responsible for generating the labels for experiment to use during exploration. Use the alphabet letters A · · · Z and a · · · z as labels (in that order).
public static Map<Character, Integer> experiment(int n, int m, int x, int y, char[][] matrix, int[][] mark, char colony) {
Queue<Integer> q = new LinkedList<Integer>();
q.offer(x*m + y);
mark[x][y] = 1;
matrix[x][y] = colony;
while(!q.isEmpty()) {
int front = q.peek(); q.remove();
int x1 = front / m, y1 = front % m;
if(x1 != 0)
if(mark[x1-1][y1] == 0 && matrix[x1-1][y1] == '1') {
matrix[x1-1][y1] = colony;
mark[x1-1][y1] = 1;
q.offer((x1-1) * m + y1);
}
I just don't understand this part of code. Can someone please explain it.
one possible explanation could be that
x and y are coordinates of grid,
if you loop over x and y as below
for( int x = 0 ; x < width; x++ ){
for( int y = 0 ; y < height; y++ ){
index_of_one_dimensional_array = x*m+y;//where m = width(i.e number if columns in each row)
}
}
seems like the q.offer() functions somehow uses this concept to set a value depending on value of index_of_one_dimensional_array given by x*m+y;
and loop is used to make sure every cell in the grid is processed which happens when the queue is empty

Elementary Java Algorithm Assistance

I need help writing a program that is given a specified number of coordinate points in the form (X,Y). The number of points that will be given is the first line in the program; it can be read in through a scanner.
I need to calculate the least amount of area to cover all of the points with the lines x = a, and y = b. So, the area would be a * b (Area of a rectangle).
However, one coordinate point (X, Y) must be removed to optimize the area. The point that is removed should minimize the area as much as possible. I need help writing algorithm to do so.
This is a sample input, and output that I was given ::
SAMPLE INPUT
4
2 4
1 1
5 2
17 25
SAMPLE OUTPUT
12
In this example, the first line of input (4) indicates that four points will be input. The next four lines are the coordinates in form (x, y). The last point which is (17, 25) is removed as the outlier which leaves us with the first three points.
If the three remaining points are graphed, they can all be inside a box (3 by 4) hence the output is 12; (3 * 4). It is OK for the line to be on the point like in this example. However, the outlier is not always the last point, or very big. The outlier could be very small, the area just needs to be minimized.
--
This is what I have so far (I know it's not very much..) - please help me!
It's mostly just the algorithm that I need help with..
import java.io.*;
import java.util.*;
public class Area {
public static void main(String args[]) {
Scanner scan = new Scanner(System.in);
int numOfPoints = scan.nextInt();
int Xcoordinates[] = new int[numOfPoints];
int Ycoordinates[] = new int[numOfPoints];
for (int i = 0; i <= numOfCows - 1; i++) {
Xcoordinates[i] = scan.nextInt();
Ycoordinates[i] = scan.nextInt();
}
}
}
Possible Pseudocode (continuing from above; this may be wrong..):
for (int i = 0; i <= Xcoordinates.length; i++) { //loop through array
compare values, and determine outlier
int lowestXValue = [find lowest x value]
int highestXValue = [find highest x value; not outlier] }
remove xcoordinates[outlier]
remove ycoordinates[outlier]
int xLength = highestXValue - lowestXValue - 1 // -1 because can be on line
for (int i = 0; i <= Ycoordinates.length; i++) { //loop through y array
int lowestYValue = [find lowest y value]
int highestYValue = [find highesy Y value] }
int yLength = highestYValue - lowestYValue - 1;
int boxArea = yLength * xLength
System.out.println(boxArea);
However, this would only search through the possible X outlier, and if there's a Y value that would minimize area by removal, it would not catch that
I would create two sorted lists of integers, one for the x co-ords and one for the y co-ords. Then you can check the area saved by removing the max x co-ordinate (area saved should be max y co-ordinate times (max x co-ordinate - second highest x co-ordinate)). You can do the same thing to check the area saved by removing the max y co-ordinate, and whichever is greater will be your final answer.

Searching a grid recursively by triangular numbers

I have a 36x25 grid of nodes that I wish to search through all triangular numbers from the corner opposite of the hypotenuse. Here's psuedocode for what I was considering, but this method only works until it hits the next corner of the grid, and I'm sure there is a much simpler way to do this recursively, I just am having difficulty figuring it out.
for(int iteration; iteration < maxDistance(49); iteration++)
{
int xAdd = iteration;
int yAdd = 0;
while(xAdd != 0)
{
checkStuff(nodeGrid[x+xAdd][y+yAdd]);
xAdd--;
yAdd++;
}
}
What I want program to do:
[0][1][2][3][4][5]
[1][2][3][4][5][6]
[2][3][4][5][6][7]
[3][4][5][6][7][8]
[4][5][6][7][8][9]
check in this order. So first check all tiles with value 0, then 1 and so on.
Note: in this case my function will only work up until the 4th set up tiles. Any further and it will reach out of bounds.
/**
* Only works for rectangular arrays
*/
public void iterateOver(Node[][] a){
int x_dim = a[0].length;
int y_dim = a.length;
for (int i = 0; i < x_dim + y_dim - 1; i++){
int x, y;
if (i < x_dim){
x = i;
y = 0;
}
else{
x = x_dim - 1;
y = i - x_dim + 1;
}
for (;x >=0 && y < y_dim; y++, x--){
doStuff(a[y][x]);
}
}
}
How it works
Picture your rectangular array:
[0][1][2][3][4][5]
[1][2][3][4][5][6]
[2][3][4][5][6][7]
[3][4][5][6][7][8]
[4][5][6][7][8][9]
There are clearly 6 columns and 5 rows (or 6 x values and 5 y values). That means that we need to do 6 + 5 - 1 iterations, or 10. Thus, the for (int i = 0; i < x_dim + y_dim - 1; i++). (i is the current iteration, measured from 0).
We start by columns. When i is less than the x dimension, x = i and y = 0 to start with. x is decremented and y is incremented until x is less than zero or y is equal to the y dimension. Then, we do a similar thing down the right hand side.

Counting with booleans

I was wondering if I could add booleans up like numbers. I am making something that uses a grid, and I want it to find the surrounding squares and return a number.
EDIT:
This is how I count with booleans.
int count = 0;
for (int x = -1; x<=1;x++){
for (int y = -1; y <=1;y++){
if (grid[xPos+x][yPos+y]){
count++;
}
}
}
boolean[] bools = ...
int sum = 0;
for(boolean b : bools) {
sum += b ? 1 : 0;
}
This assumes that you want true to be 1 and false to be 0.
To add to Jeffrey's answer, don't forget:
If your at the center cell of your nested for loops, don't check the grid, and don't add to count. Else you're counting the cell itself in its neighbor count. In your situation, it's were (x == 0 && y == 0)
You will need to check if the cell is on the edge, and if so make sure you're not trying to count cells that are off the grid. I've done this using something like this: int xMin = Math.max(cellX - 1, 0); where xMin is the lower bound of one of the for loops. I do similar for y, and similar for the maximum side of the grid. In your code this will happen when xPos + x < 0 or xPos + x >= MAX_X (MAX_X is a constant for the max x value allowed for the grid), and similar for the y side of things.
What is your goal? Speed? Readability? Code terseness?
If you're seeking speed, think about minimizing the number of memory accesses. If you can force your booleans to be stored as bits, you could use >> and & to compare only the bits you care about in each row. Maybe something like this:
byte grid[m][n / 8];
int neighbor_count = 0;
for (int row = yPos - 1; row < yPos + 1; row++) {
// calculate how much to shift the bits over.
int shift = 5 - (xPos - 1 % 8);
if (shift > 0) {
// exercise for the reader - span bytes.
} else {
// map value of on-bits to count of on bits
static byte count[8] = [0, 1, 1, 2, 1, 2, 2, 3];
// ensure that only the lowest 3 bits are on.
low3 = (grid[row][xPos / 8] >> shift) & 7;
// look up value in map
neighbor_count += count[low3];
}
caveat coder: this is untested and meant for illustration only. It also contains no bounds-checking: a way around that is to iterate from 1 to max - 2 and have a border of unset cells. Also you should subtract 1 if the cell being evaluated is on.
This might end up being slower than what you have. You can further optimize it by storing the bitmap in int32s (or whatever's native). You could also use multithreading, or just implement Hashlife :)
Obviously this optimizes away from terseness and readability. I think you've got maximum readability in your code.
As Jeffrey alludes to, storing a sparse array of 'on' booleans might be preferable to an array of values, depending on what you're doing.

Simple issue regarding iterating through each pixel in an image

Okay this is going to seem really dumb but bear with me please. A year ago I made a little program to perform various operations on images, and now I'm a bit rusty and having to do something vaguely similar. I'm looking at the old application in order to help me get started but there is one very simple thing my head doesn't want to understand the logic of just now. Basically where I loop through each pixel in an image in order to do something with that location, what exactly doesn't matter right now. Here is the basic idea:
for (int x = 0; x < inputImage.getWidth(); x++) {
for(int y = 0; y < inputImage.getHeight(); y++) {
*code in here*
}
}
Now what I don't get is this. Surely the logic of the nested for loops means that after every loop, both x AND y are incremented. So on the first pass, x = 0, y = 0. Second pass, x = 1, y = 1 and so on. This would mean that you only ever choose diagonal pixels going from the top left of the image to the bottom right, missing out a ton of pixels such as one located at x = 0, y = 1. I KNOW this is simple and surely makes sense but I'm just not getting the logic right now! Many thanks.
No, that's not what nested loops do at all. The y loop is wholly inside the body of the x loop (that's what it means to be nested), so the entire y loop runs at each iteration of the x loop.
x = 0
y = 0, y = 1, y = 2, ...
x = 1
y = 0, y = 1, y = 2, ...
The behavior you're thinking of, with only iterating over diagonal elements, could be achieved like this if you wanted it:
for (int x = 0, int y = 0;
x < inputImage.getWidth && y < inputImage.getHeight;
x++, y++) {
// stuff
}
Notice how both x and y are incremented in the same loop; there is no nested "subloop". (Disclaimer: I haven't done Java in a while, I might have messed up the syntax a bit)
No. Both x and y are not actually incremented simultaneously.
y goes from 0 to inputImage.height-1 for every x from 0 to inputImage.width-1. That means, you traverse the first column completely before moving to another column on the image and so on.

Categories

Resources