I have a matrix from an image 1600x1600. I need to assign this matrix into 4x4 blocks. As an example:
00 01 02 03
IMAGE = 04 05 06 07 BLOCK(i) = 00 01 BLOCK(i+1) = 02 03
08 09 0A 0B 04 05 06 07
0C 0D 0E 0F
BLOCK(i+2) = 08 09 BLOCK(i+3) = 0A 0B
0C 0D = 0E 0F
Firstly I don't know the image dimensions, the user opens it. I get it later. My test image is 1600x1600. But blocks dimensions are fixed at 4x4. And image dimensions are, let's agree it can be divided by 4 for now...
I don't know how many blocks there will be.
I need to access the row and columns of the blocks later because I will be performing mathematical operations with the blocks later... For example , XOR operation with block(n)[x,y] with block(n+1) [x,y]. So this declaration part, this part of the program is very very important.
I have been stuck at this part of the program for 2 weeks and I can't continue. Please help me. It looks like very simple code but.......
My structure is like this, beginning part
private void Form1_Load(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap("c:\\yavanna.jpg");
pictureBox1.Image = Image.FromFile("c:\\yavanna.jpg");
int width = bmp.Width;
int height = bmp.Height;
Color p;
int[,] alpha_map_int = new int[width, height];
int[,] red_map_int = new int[width, height];
int[,] green_map_int = new int[width, height];
int[,] blue_map_int = new int[width, height];
int[,] grayscale_map_int = new int[width, height];
string[,] gray_scale_map = new string[width, height];
string temp_hexValue;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
//get pixel value
p = bmp.GetPixel(x, y);
//extract pixel component ARGB
int a = p.A;
alpha_map_int[x, y] = a;
int r = p.R;
red_map_int[x, y] = r;
int g = p.G;
green_map_int[x, y] = g;
int b = p.B;
blue_map_int[x, y] = b;
// convert to grayscale
double grayscale = 0.2126 * red_map_int[x,y] + 0.7152 * green_map_int[x, y] + 0.0722 * blue_map_int[x, y];
grayscale_map_int[x, y] = Convert.ToInt32(grayscale);
temp_hexValue = Convert.ToString(grayscale_map_int[x, y]);
gray_scale_map[x, y] = temp_hexValue;
}
}
Here's a version of jdweng's answer, that generates 4x4 arrays and handles source arrays that don't divide by 4. You can see why he posted a simplified sample. Any bigger and it would be worth using two more loops to populate the 4x4 array.
'image' is the input, 'bytes4x4' is the output.
List<List<List<byte>>> bytes4x4 = new List<List<List<byte>>>();
for (int row = 0; row<length-3 ; row += 4)
{
for (int col = 0; col<width-3; col += 4)
{
bytes4x4.Add(new List<List<byte>>() {
new List<byte>() { image[row, col], image[row, col + 1], image[row, col + 2], image[row, col + 3]},
new List<byte>() { image[row + 1, col], image[row + 1, col + 1], image[row + 1, col + 2], image[row + 1, col + 3] },
new List<byte>() { image[row + 2, col], image[row + 2, col + 1], image[row + 2, col + 2], image[row + 2, col + 3] },
new List<byte>() { image[row + 3, col], image[row + 3, col + 1], image[row + 3, col + 2], image[row + 3, col + 3] }
});
}
This declares and populates 'bytes4x4', which is a long list of two dimensional blocks. Access a block like this:
var block100 = bytes4x4[100];
And use that to get a pixel:
var block100pixelrow1col3 = block100[1][3];
or
var block100pixelrow1col3 = bytes4x4[100][1][3];
Note that these indexs are all zero based, so there's no element [4] in the blocks.
Now I think about it, you might be after a 2-dimensional array of 2-dimensional blocks. If so the code would look like this:
var bytes4x4 = new List<List<List<List<byte>>>>();
for (int row = 0; row<length-3 ; row += 4)
{
var row = new List<List<List<byte>>>();
bytes4x4.Add(row);
for (int col = 0; col<width-3; col += 4)
{
row.Add(new List<List<byte>>() {
new List<byte>() { image[row, col], image[row, col + 1], image[row, col + 2], image[row, col + 3]},
new List<byte>() { image[row + 1, col], image[row + 1, col + 1], image[row + 1, col + 2], image[row + 1, col + 3] },
new List<byte>() { image[row + 2, col], image[row + 2, col + 1], image[row + 2, col + 2], image[row + 2, col + 3] },
new List<byte>() { image[row + 3, col], image[row + 3, col + 1], image[row + 3, col + 2], image[row + 3, col + 3] }
});
}
Then you could access a block that is 14 rows down and 23 columns across like this:
var block14by23 = bytes4x4[14][23];