1

I have a jpeg image. I save this bitmapdata to a byte array.

This jpeg has a width of 100 and a height of 100.

I want to extract an image of Rectanlge(10,10,20,20);

Obviously, I can interact through this byte array but I am unsure how to relate the x,y pixels of what I want to this byte array. I know that I have to use the stride and pixel size which is 4 as it is rgba.

I have this which was from this link cropping an area from BitmapData with C#.

Bitmap bmp = new Bitmap(_file);
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
 BitmapData rawOriginal = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);

int origByteCount = rawOriginal.Stride * rawOriginal.Height;
byte[] origBytes = new Byte[origByteCount];
System.Runtime.InteropServices.Marshal.Copy(rawOriginal.Scan0, origBytes, 0, origByteCount);

int BPP = 4;  
int width = 20;
int height = 20;
int startX = 10;
int startY = 10;

for (int i = 0; i < height; i++)
{
for (int j = 0; j < width * BPP; j += BPP)
{
int origIndex = (startX * rawOriginal.Stride) + (i * rawOriginal.Stride) + (startY * BPP) + (j);
int croppedIndex = (i * width * BPP) + (j);
                        //copy data: once for each channel
for (int k = 0; k < BPP; k++)
{
croppedBytes[croppedIndex + k] = origBytes[origIndex + k];
}
}
}

But this:

int origIndex = (startX * rawOriginal.Stride) + (i * rawOriginal.Stride) + (startY * BPP) + (j);

I found is incorrect.

Does anyone know what value I should set here please?

thanks

Community
  • 1
  • 1
Andrew Simpson
  • 6,883
  • 11
  • 79
  • 179

2 Answers2

2

Stride is bytes per line (Y), you shouldn't multiply x at any point by Stride

int y = startY + i;
int x = startX;
int origIndex = y * rawOriginal.Stride + x * BPP;
weston
  • 54,145
  • 21
  • 145
  • 203
  • Hi, thanks for the reply. I do not know what to do. I found the answer out eventually myself. But both you and @ppetrov are correct and deserve a green tick. But I can only do 1 tick. Should I post this dliemma as question here? – Andrew Simpson Oct 02 '13 at 19:12
  • 1
    No don't ask that here, questions like that go on http://meta.stackoverflow.com. Usually I award to the first person. ppetrov has more detail, so if that helped you further, give him the tick. But whoever you choose, you can always upvote us both just by clicking the grey up arrow next to each answer. – weston Oct 03 '13 at 08:14
2

When you're working with bitmap data, there are 2 important things to keep in mind:

  1. the BPP (bytes per pixel): which here is 4
  2. the stride (number of bytes on one line of the image), which here would be 4 * width

so if you want to get the offset of a pixel, just use this formula:

int offset = x * BPP + y * stride;

if you want to extract only a part of your bitmap you could just do this:

int i = 0;

for(int y = startY; y < startY + height; y++)
{
    for(int k = startX * bpp + y * stride; k < (startX + width) * bpp + y * stride; k++)
    {
        croppedBytes[i] = origBytes[k];
        i++;
    }
}
ppetrov
  • 3,077
  • 2
  • 15
  • 27
  • 1
    "which here would be 4 * width" - not quite, note that `Stride` is **not** always `BPP * Width`. There may be some padding depending on the width, see: http://stackoverflow.com/a/5736076/360211 – weston Oct 03 '13 at 10:00
  • @weston that's true, but not for 32bit images (at least for now), so here it is indeed `4 * width`. I don't think that bitmap manipulation classes are optimized for 64bit processors, that's why I highly doubt that there could be padding for 32bit images – ppetrov Oct 03 '13 at 12:21