mfmz
mfmz

Reputation: 227

Break large 2D array into multiple smaller 2D array using JAVA

I have a 2D array which consist of image pixels which its size depends on the size of the input image. I need to break it into smaller 9x9 arrays. To give a clearer picture, I try to illustrate the situation:

//The number of rows and columns of the smallerArray will look something like this: It should copy them from the imagePixels array iterating through each 8 columns, then move on to the next 8 rows.

    1st small   2nd small            3rd small            and so on..
    array:      array:               array: 
     012345678  91011121314151617   181920212223242526    ....
    0          0                   0
    1          1                   1
    2          2                   2
    3          3                   3
    4          4                   4
    5          5                   5
    6          6                   6
    7          7                   7
    8          8                   8

    Then move on to next 8 rows:

      012345678    91011121314151617   181920212223242526    ....
    9             9                   9
    10           10                  10
    11           11                  11
    12           12                  12
    13           13                  13
    14           14                  14
    15           15                  15
    16           16                  16
    17           17                  17

.
.
.

I have done the following code but could not get my logic right. How can I stop the iteration:

Copy up until the 9th column or row, store it in an array, resume copying on the 10th column/row, stop when it reaches 9 column/row after, store it in another array, and keep on doing that till it finishes copying the imagePixels array.

I tried to store the arrays in an ArrayList so it would be easier for me to manipulate and do calculation stuffs with all the smallerArrays.

ArrayList<double[][]> collectionofSmallArrays = new ArrayList();
double[][] imagePixels = new double[1600][1000]; //Lets say this is the size of the image
double[][] smallerArray = new double[9][9];

for(int a = 0; a<smallerArray.length; a++)
{
  for(int b =0; b<smallerArray[a].length; b++)
  { 
    for(int c=0; c<imagePixels.length; c++)
    {
      for(int d=0; d<imagePixels[c].length; d++)
      {
        smallerArray[a][b] = imagePixels[c][d];
        ...(code to stop the iteration if it reaches 9, store it in array then resume where it stops     with another new array)
        collectionofSmallArrays.add(smallerArray);
      }
    }
  }
}

Can anyone work around the code to achieve the expected result? Appreciate it.

Upvotes: 1

Views: 1906

Answers (3)

jheyd
jheyd

Reputation: 599

  1. You cannot reuse smallerArray. Create the instance inside the for loop and store the size in a constant.
  2. I think a map with some corner coordinates as a key would be far better than a list for storing your results.
  3. What happens if the length or width or your image is not divisible by 9?

Upvotes: 0

Marco13
Marco13

Reputation: 54659

You should probably provide more context information. Saying that an array of double values represents pixels sounds dubios. If you are working with images, then you might find solutions on a completely different level of abstraction (I'm thinking about BufferedImage#createSubImage here).

However, to answer the question: You should break the task up into smaller parts. Particularly, it might be easier to implement two methods:

  • One method that receives an input array, some coordinates, and an output array, and that copies the data from the specified coordinates of the input array to the output array
  • One method that calls the above mentioned method with the appropriate coordinates to split the whole array into the parts of the desired size.

In pseudocode:

for (each coordinates (9*r,9*c)) {
    copy the rectange (9*r,9*c)-(9*r+9,9*c+9) of the input array into an array

A very simple implementation/test is shown in the following example. Note that this could be generalized and improved, but I think it shows the basic idea:

import java.util.ArrayList;
import java.util.List;

public class SubArrayTest
{
    public static void main(String[] args)
    {
        double inputArray[][] = createInputArray(160, 100);
        System.out.println("inputArray: "+toString(inputArray));

        List<double[][]> subArrays = createSubArrays(inputArray, 9, 9);

        for (double subArray[][] : subArrays)
        {
            System.out.println("subArray:\n"+toString(subArray));
        }
    }

    private static List<double[][]> createSubArrays(
        double inputArray[][], int subRows, int subCols)
    {
        List<double[][]> subArrays = new ArrayList<double[][]>();
        for (int r=0; r<inputArray.length; r+=subRows)
        {
            for (int c=0; c<inputArray[r].length; c+=subCols)
            {
                double subArray[][] = new double[subRows][subCols]; 
                fillSubArray(inputArray, r, c, subArray);
                subArrays.add(subArray);
            }
        }
        return subArrays;
    }

    private static void fillSubArray(
        double[][] inputArray, int r0, int c0, double subArray[][])
    {
        for (int r=0; r<subArray.length; r++)
        {
            for (int c=0; c<subArray[r].length; c++)
            {
                int ir = r0 + r;
                int ic = c0 + c;
                if (ir < inputArray.length &&
                    ic < inputArray[ir].length)
                {
                    subArray[r][c] = inputArray[ir][ic];
                }
            }
        }
    }


    //===Test methods=========================================================
    private static double[][] createInputArray(int rows, int cols)
    {
        double array[][] = new double[rows][cols]; 
        for (int r=0; r<array.length; r++)
        {
            for (int c=0; c<array[r].length; c++)
            {
                array[r][c] = r*100+c;
            }
        }
        return array;
    }

    private static String toString(double array[][])
    {
        String format = "%7.1f";
        StringBuilder sb = new StringBuilder();
        for (int r=0; r<array.length; r++)
        {
            for (int c=0; c<array[r].length; c++)
            {
                sb.append(String.format(format, array[r][c])+" ");
            }
            sb.append("\n");
        }
        return sb.toString();
    }


}

Side notes:

  • You should always declare variables with their interface type. This means that you should not write

    ArrayList<String> x = new ArrayList<String>();
    

    but always

    List<String> x = new ArrayList<String>();
    
  • In the posted code, you seemed to always add the same instance of the sub-array to the list. This means that in the end you would have many instances of the same array in the list, all with the same content. Somewhere in between you have to create a new double[9][9] array.

Upvotes: 1

talex
talex

Reputation: 20544

smallerArray[a][b] = imagePixels[c][d] line looks strange. You reuse same array instance. Your output array list will contain multiple reference to same array.

Upvotes: 0

Related Questions