How to calculate padding when using direct access to image pixels? The code below should change all pixels to white, but System.AccessViolationException appears.

struct Pixel { public byte Blue; public byte Green; public byte Red; } public void startHandle() { Bitmap pic = new Bitmap(Path); var picBits = pic.LockBits(new Rectangle(0, 0, pic.Width, pic.Height), ImageLockMode.ReadWrite, pic.PixelFormat); unsafe { //получение указателя на первый пиксель изображения Pixel* px = (Pixel*)((byte*)picBits.Scan0); int padding = picBits.Stride - (pic.Width * sizeof(Pixel)); for (int j = 0; j < pic.Height - 1; j++) { for (int k = 0; k < pic.Width - 1; k++) { px->Blue = 255; px->Green = 255; px->Red = 255; px += sizeof(Pixel); } px += padding; } } pic.UnlockBits(picBits); } 
  • one
    You do not check the image format. Nothing guarantees that there will actually be three bytes per pixel in the bitmap. - VladD

1 answer 1

Assuming your format is really 24 bits per pixel, you should do something like this:

 // using потому, что нужно освободить ресурс using (var bmp = new Bitmap(path)) { // проверим формат. если он не такой, как ожидалось, наш код не имеет право его трогать if (bmp.PixelFormat != PixelFormat.Format24bppRgb) throw new ArgumentException("Мой код считает, что в картинке 3 байта на пиксель"); const int bytesPerPixel = 3; Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); BitmapData bits = null; try { bits = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat); unsafe { // указатель на Pixel не имеет смысла, лэйаут структур // в C# не определён // используем указатель на байт byte* start = (byte*)bits.Scan0; // цикл должен быть до H for (int y = 0; y < bmp.Height; y++) { // указатель на начало строки // поскольку Stride в байтах, мы вычисляем верно // а вот арифметика с Pixel* была бы здесь неверна byte* row = start + y * bits.Stride; for (int x = 0; x < bmp.Width; x++) { // указатель на текущий пиксель // опять-таки, арифметика с Pixel* была бы неверна byte* pixel = row + x * bytesPerPixel; pixel[0] = 255; pixel[1] = 255; pixel[2] = 255; } } } } finally { if (bits != null) bmp.UnlockBits(bits); } // тут можно что-то сделать с картинкой }