views:

78

answers:

2

I want to write a function that resizes a 2D array to the given parameters. Its a general resize array:

public static int[][] resize(int[][] source, int newWidth, int newHeight) {

        int[][] newImage=new int[newWidth][newHeight];
        double scale=newWidth/source.length;
        for (int j=0;j<newHeight;j++)
            for (int i=0;i<newWidth;i++)
                newImage[i][j]=source[(int)(i/scale)][(int)(j/scale)];
        return newImage;

The code above has no problems, it works great for integer resizing. The problem arises however, when I use the resize function to resize an array by a factor of 0.5.

int[][] newImage=new int[source.length][source.length];
newImage=resize(source,source.length/2,source[0].length/2);
        return newImage;

Then everything goes crazy. I get an outofboundserrorexception of like 2147483647. The problem lies in the double scale variable in the first function and the type casting I used in the first function in the last line. Any ideas for fixes?

Note: source.length is the width (columns) of the array, and source[0].length is the height(rows).

+2  A: 

The scale variable is of type double. You probably expect the following:

int newWidth = 5;
int sourceLength = 10;
double scale = newWidth / sourceLength;
// what is `scale` now?

The surprising thing is that scale is now 0.0. This is because dividing an int by an int always results in an int again.

To get the result you want, you have to write:

double scale = ((double) newWidth) / sourceLength;

or

double scale = 1.0 * newWidth / sourceLength;

Then the division takes place with a double and an int, and the result will be a double, in this case the expected 0.5.

Roland Illig
Ah yes that was it, thanks!
fprime
+1  A: 

Explanation:

  1. The expression 1/2 is an integer division. It yields 0.
  2. Assigning 0 to a double will turn it into 0.0
  3. 1 / 0.0 is a floating point division, and yields Double.POSITIVE_INFINITY.
  4. casting Double.POSITIVE_INFINITY to int yields Integer.MAX_VALUE.

Dirty fix:

double scale = ((double)newWidth) / source.length;

That code is not very efficient, as it constantly converts between doubles and ints. You can stick with ints by doing:

newImage[i][j]=source[i * source.length / newWidth][j * source.length / newWidth];

That solution however will overflow if newWidth * source.length > Integer.MAX_VALUE but I suspect you won't be working with matrices that big.

meriton
Thanks this helps..
fprime