I have a function named resize, which takes a source array, and resizes to new widths and height. The method I’m using, I think, is inefficient. I heard there’s a better way to do it. Anyway, the code below works when scale is an int. However, there’s a second function called half, where it uses resize to shrink an image in half. So I made scale a double, and used a typecast to convert it back to an int. This method is not working, and I dont know what the error is (the teacher uses his own grading and tests on these functions, and its not passing it). Can you spot the error, or is there a more efficient way to make a resize function?
public static int[][] resize(int[][] source, int newWidth, int newHeight) {
int[][] newImage=new int[newWidth][newHeight];
double scale=newWidth/(source.length);
for(int i=0;i<newWidth/scale;i++)
for(int j=0;j<newHeight/scale;j++)
for (int s1=0;s1<scale;s1++)
for (int s2=0;s2<scale;s2++)
newImage[(int)(i*scale+s1)][(int)(j*scale+s2)] =source[i][j];
return newImage;
}
/**
* Half the size of the image. This method should be just one line! Just
* delegate the work to resize()!
*/
public static int[][] half(int[][] source) {
int[][] newImage=new int[source.length/2][source[0].length/2];
newImage=resize(source,source.length/2,source[0].length/2);
return newImage;
}
So one scheme for changing the size of an image is to resample it (technically this is really the only way, every variation is really just a different kind of resampling function).
Cutting an image in half is super easy, you want to read every other pixel in each direction, and then load that pixel into the new half sized array. The hard part is making sure your bookkeeping is strong.
In the code above I’m indexing into the original image reading every other pixel in every other row starting at the 0th row and 0th column (assuming images are row major, here). Thus,
rtells us which row in the original image we’re looking at, andctells us which column in the original image we’re looking at.orig[r][c]gives us the “current” pixel.Similarly,
newrandnewcindex into the “half-image” matrix designatedhi. For each increment innewrornewcwe incrementrandcby 2, respectively. By doing this, we skip every other pixel as we iterate through the image.Writing a generalized resize routine that doesn’t operate on nice fractional quantities (like 1/2, 1/4, 1/8, etc.) is really pretty hard. You’d need to define a way to determine the value of a sub-pixel — a point between pixels — for more complicated factors, like 0.13243, for example. This is, of course, easy to do, and you can develop a very naive linear interpolation principle, where when you need the value between two pixels you simply take the surrounding pixels, construct a line between their values, then read the sub-pixel point from the line. More complicated versions of interpolation might be a
sincbased interpolation…or one of many others in widely published literature.Blowing up the size of the image involves something a little different than we’ve done here (and if you do in fact have to write a generalized resize function you might consider splitting your function to handle upscaling and downscaling differently). You need to somehow create more values than you have originally — those interpolation functions work for that too. A trivial method might simply be to repeat a value between points until you have enough, and slight variations on this as well, where you might take so many values from the left and so many from the right for a particular position.
What I’d encourage you to think about — and since this is homework I’ll stay away from the implementation — is treating the scaling factor as something that causes you to make observations on one image, and writes on the new image. When the scaling factor is less than 1 you generally sample from the original image to populate the new image and ignore some of the original image’s pixels. When the scaling factor is greater than 1, you generally write more often to the new image and might need to read the same value several times from the old image. (I’m doing a poor job highlighting the difference here, hopefully you see the dualism I’m getting at.)