I'm trying to make a function that shuffles an image as shown below:
Its argument takes three 600x400 RGB arrays to create the pixel colors. I have been trying to brainstorm this for so many hours but I'm so confused about methods to do it. Here's an idea I've tried working out, but I got overwhelmed and stumped with:
Copy each RGB array (R[][], G[][], and B[][] separately which combined makes a colored image) into their respective temporary arrays. Split the temporary arrays into a 4x4. Each element would contain its own 2D array with a block of the original image. Then using the random library I can assign the elements to new locations within the 4x4. I have no idea how to do this without making 42 arrays (16 arrays per color in the 4x4, but 42 arrays for R, G, and B). I would appreciate any advice or Here is the code I currently have, but I paused (or possibly abandoned) working on:
void Shuffle(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]){
// Initialize 150x100 inner shuffle arrays. These arrays are chunks of the original image
int shuffArrR[150][100] = {0};
int shuffArrG[150][100] = {0};
int shuffArrB[150][100] = {0};
int row = 0, col = 0;
/*
BOUNDARY INFO FOR 4x4 ARRAY:
C1: C2: C3: C4: hBound# (row):
--------------------> 1
R1: | | | | |
--------------------> 2
R2: | | | | |
--------------------> 3
R3: | | | | |
--------------------> 4
R4: | | | | |
--------------------> 5
| | | | |
v v v v v
vBound# (col): 1 2 3 4 5
vBound: hBound:
#: col: #: row:
1 0 1 0
2 150 2 100
3 300 3 200
4 450 4 300
5 600 5 400
*/
// Define boundaries
int const vBound1 = 0, vBound2 = 150, vBound3 = 300, vBound4 = 450;
int const hBound1 = 0, hBound2 = 100, hBound3 = 200, hBound4 = 300;
for(row; row < HEIGHT; row++){
for(col; col < WIDTH; col++){
// Copy RGB arrays to shuffle arrays
shuffArrR[col][row] = R[col][row];
shuffArrG[col][row] = G[col][row];
shuffArrB[col][row] = B[col][row];
// Define 16 blocks in 4x4 array ------------------
// If in R1
if(row >= hBound1 && row <= hBound2){
// And in C1
if(col >= vBound1 && col <= vBound2){
// ** I stopped here after I realized how many arrays I'd have to make to account for every element in the 4x4 **
}
}
}
}
}
Label each block with an ID, 0, 1, 2, ...15 .
-----------------
| 12| 13| 14| 15|
-----------------
| 8 | 9 | 10| 11|
-----------------
| 4 | 5 | 6 | 7 |
-----------------
| 0 | 1 | 2 | 3 |
-----------------
Put all ID in an array, then shuffle the array. shuffle like this. Then traversal the array and swap content of each block.
int arr[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
arr_shuffle(arr, 16);
int i;
for (i = 0; i < 16; i++) {
swap_block(i, arr[i]);
}
Now the problem will be how to swap two block. Let's say we have block A and block B. Both size should be 100(height) * 150(width). Then think A is an array like A[100][150], and B is B[100][150]. swap this array will be like below.
for (i = 0; i < 100; i++) {
for (j = 0; j < 150; j++) {
swap(A[i][j], B[i][j];
}
}
The final step should be convert A[i][j] and B[i][j] to the real element in array R/G/B. This can be done simply by math.
void get_real_id(int block_id, int x, int y, int *real_x, int *real_y)
{
int row, col;
row = block_id / 4; // convert block id to row number
col = block_id % 4; // convert block id to col number
// find BLOCK[y][x] in array R, which should be R[real_y][real_x]
*real_x = (col * (WIDTH/4)) + x;
*real_y = (row * (HEIGHT/4)) + y;
}
The sample code in below will work for array R. The define of R is R[HEIGHT][WEIGHT], not R[WEIGHT][HEIGHT] (This define should work too but I can't think with it).
int R[HEIGHT][WIDTH];
int arr_shuffle(int *arr, int len)
{
size_t i;
for (i = 0; i < len - 1; i++)
{
size_t j = i + rand() / (RAND_MAX / (len - i) + 1);
int t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
void get_real_id(int block_id, int x, int y, int *real_x, int *real_y)
{
int row, col;
row = block_id / 4;
col = block_id % 4;
*real_x = (col * (WIDTH/4)) + x;
*real_y = (row * (HEIGHT/4)) + y;
}
void swap_block(int src, int dst)
{
int w_len = WIDTH / 4; // should be 150
int h_len = HEIGHT / 4; // should be 100
int i, j;
for (i = 0; i < h_len; i++) {
for (j = 0; j < w_len; j++) {
int real_src_x;
int real_src_y;
int real_dst_x;
int real_dst_y;
get_real_id(src, j, i, &real_src_x, &real_src_y);
get_real_id(dst, j, i, &real_dst_x, &real_dst_y);
// swap two point.
int r = R[real_src_y][real_src_x];
R[real_src_y][real_src_x] = R[real_dst_y][real_dst_x];
R[real_dst_y][real_dst_x] = r;
}
}
}
int Shuffle()
{
int i;
int arr[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
arr_shuffle(arr, 16);
for (i = 0; i < 16; i++) {
int src_block_id = i;
int dst_block_id = arr[i];
swap_block(src_block_id, dst_block_id);
}
}
I should mention there is chance that after the Shuffle nothing changes.