Jump to content
  • Advertisement
Sign in to follow this  
soumya_iiitc

Dividing a image into 4 blocks

This topic is 3666 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I want to divide an image into for blocks and each block will be height/2 and width/2. I can do this using for loop but it's taking two much time to process for large images. Please suggest me any best and efficient way to do this. Thanks, Soumyadipta De

Share this post


Link to post
Share on other sites
Advertisement
You have the image in main memory, right?

Then use 4 for-loops, one for each block. Iterate through the lines and copy one line at a time into the new buffer.

Share this post


Link to post
Share on other sites

////////////////////////////////// PREPARE IMAGE BLOCKS //////////////////////////////

int srcIndex1 = 0;
int srcIndex2 = 0;
int srcIndex3 = 0;
int srcIndex4 = 0;

int dstIndex = 0;

for(int i=0; i<POT_height; i++)
{
if( i < POT_height/2)
{
for(int j=0; j<POT_width; j++)
{
if( j < POT_width/2)
{
dib_POT_block1[srcIndex1 + 0] = POT_data[dstIndex + 0];
dib_POT_block1[srcIndex1 + 1] = POT_data[dstIndex + 1];
dib_POT_block1[srcIndex1 + 2] = POT_data[dstIndex + 2];
dib_POT_block1[srcIndex1 + 3] = POT_data[dstIndex + 3];

srcIndex1 += 4;
}
else
{
dib_POT_block2[srcIndex2 + 0] = POT_data[dstIndex + 0];
dib_POT_block2[srcIndex2 + 1] = POT_data[dstIndex + 1];
dib_POT_block2[srcIndex2 + 2] = POT_data[dstIndex + 2];
dib_POT_block2[srcIndex2 + 3] = POT_data[dstIndex + 3];

srcIndex2 += 4;
}

dstIndex += 4;
}
}
else
{
for(int j=0; j<POT_width; j++)
{
if( j < POT_width/2)
{
dib_POT_block3[srcIndex3 + 0] = POT_data[dstIndex + 0];
dib_POT_block3[srcIndex3 + 1] = POT_data[dstIndex + 1];
dib_POT_block3[srcIndex3 + 2] = POT_data[dstIndex + 2];
dib_POT_block3[srcIndex3 + 3] = POT_data[dstIndex + 3];

srcIndex3 += 4;
}
else
{
dib_POT_block4[srcIndex4 + 0] = POT_data[dstIndex + 0];
dib_POT_block4[srcIndex4 + 1] = POT_data[dstIndex + 1];
dib_POT_block4[srcIndex4 + 2] = POT_data[dstIndex + 2];
dib_POT_block4[srcIndex4 + 3] = POT_data[dstIndex + 3];

srcIndex4 += 4;
}

dstIndex += 4;
}
}
}

Share this post


Link to post
Share on other sites
You could use the following approach:

for(int i = 0; i < height/2; i++)
{
memcpy(destimage0 + width/2 * sizeof(pixel) * i, srcimage + i * width, width/2 * sizeof(pixel));
memcpy(destimage1 + width/2 * sizeof(pixel) * i, srcimage + i * width + width/2, width/2 * sizeof(pixel));
memcpy(destimage2 + width/2 * sizeof(pixel) * i, srcimage + (i + height/2) * width, width/2 * sizeof(pixel));
memcpy(destimage3 + width/2 * sizeof(pixel) * i, srcimage + (i + height/2) * width + width/2, width/2 * sizeof(pixel));
}

You could precompute width/2 and height/2 as well as width/2 * sizeof(pixel) in order to reduce calculations.

Share this post


Link to post
Share on other sites
Thanks for your help but the above loop is very confusing. It will be really helpful if you please explain the logic?

Can you please explain the loop? i not getting the point why you are incrementing the source and destination buffer pointer while doing memcpy.

destimage0 + width/2 * sizeof(pixel) * i

and

srcimage + i * width, width/2 * sizeof(pixel)

Regards,
Soumyadipta De

Share this post


Link to post
Share on other sites
The code takes the top and middle horizontal lines and, since each line contains the data for two of the subimages, breaks each line into two groups. It copies each of the four groups into their respective subimage. The next iteration of the loop then does the same thing, but for the second-from-the-bottom and second-from-the-middle lines. This continues until the bottom line approaches the middle point of the image (and thus the middle line approaches the top of the image). If the pointers were not incremented, then the same partial image data would be copied into the same locations for height/2 times and you'd be left with four subimages that only contain one line of image data.

It looks like this code will throw away one line of the original image's data if the image's height is odd. You can solve it, but how does one go about doing that? Is throwing the data away perfectly OK? How do you decide which images get to be larger and which get to be smaller? These are implementation details that you will have to decide. Also keep in mind that you can take Lord_Evil's code and break it up into two for loops (one for the top subimages and one for the bottom). Although you'll face some slight additional overhead for managing two loops, you'll cut down on the complexity of the problem (possibly making it easier to read) and also get rid of some arithmetic overhead.

Using memcpy is much faster for copying large blocks of data at once rather than assigning the data one variable at a time.

Share this post


Link to post
Share on other sites
Thank you for your explanation, CrimsonSun. ;)

Just to make it easier to understand, a short and very simple example:


Your source image could look like this:

12 13 14 15
8 9 10 11
4 5 6 7
0 1 2 3

And you want those 4 subimages:

4 5 6 7 12 13 14 15
0 1 , 2 3 , 8 9 , 10 11

Now we have width/2 = 2 and height/2 = 2. sizeof(pixel) will be 1 byte in this case so width/2 * sizeof(pixel) = 1.

Now the first iteration (i = 0) evolves to:

memcpy(destimage0 + 0, srcimage + 0, 2); //copies the pixels 0 and 1 to destimage0
memcpy(destimage1 + 0, srcimage + 2, 2); //copies the pixels 2 and 3 to destimage1
memcpy(destimage2 + 0, srcimage + 8, 2); //copies the pixels 8 and 9 to destimage2
memcpy(destimage3 + 0, srcimage + 10, 2); //copies the pixels 10 and 11 to destimage3

Then the pointers are advanced by 2 bytes in the destination images as well as 4 bytes (one line) in the source image.

The next iteration (i = 1) evolves to:

memcpy(destimage0 + 2, srcimage + 4, 2); //copies the pixels 4 and 5 to destimage0
memcpy(destimage1 + 2, srcimage + 6, 2); //copies the pixels 6 and 7 to destimage1
memcpy(destimage2 + 2, srcimage + 12, 2); //copies the pixels 12 and 13 to destimage2
memcpy(destimage3 + 2, srcimage + 14, 2); //copies the pixels 14 and 15 to destimage3

After that, your destination images are laid out in memory like this:

destimage0 = 0, 1, 4, 5
destimage1 = 2, 3, 6, 7
destimage3 = 8, 9, 12, 13
destimage4 = 10, 11, 14, 15


Hope that makes it a bit clearer.

Share this post


Link to post
Share on other sites
We have not considered the BPP (3 or 4) in the above for loop and so the generated index are wrong and you will not get proper image.

//////////////////// BELOW IS THE CORRECT FOR LOOP ////////////////////////////


for(int i=0; i<POT_height/2; i++)
{
int srcIndex = POT_width/2 * bpp *i;
int size = POT_width/2 * bpp;
int size2 = POT_width * bpp;

//Bottom Left
memcpy(dib_POT_block1 + srcIndex, POT_data + i * size2, size);
//Bottom Right
memcpy(dib_POT_block2 + srcIndex, POT_data + i * size2 + size, size);

//Top Left
memcpy(dib_POT_block3 + srcIndex, POT_data + (i + POT_height/2) * size2, size);
//Top Right
memcpy(dib_POT_block4 + srcIndex, POT_data + (i + POT_height/2) * size2 + size, size);
}



Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!