There is some code:
struct BitmapDataAccessor { private readonly byte[] data; private readonly int[] rowStarts; public readonly int Height; public readonly int Width; public readonly int Padding; public BitmapDataAccessor(byte[] data, int width, int height, int padding) { this.data = data; this.Height = height; this.Width = width + (4-padding)%4; this.Padding = padding; rowStarts = new int[Height]; for (int y = 0; y < Height; y++) rowStarts[y] = y * Width; } public byte this[int x, int y, int color] // Maybe use an enum with Red = 0, Green = 1, and Blue = 2 members? { get { return data[(rowStarts[y] + x) * 3 + color]; } set { data[(rowStarts[y] + x) * 3 + color] = value; } } public byte[] Data { get { return data; } } } public static byte[, ,] Bitmap2Byte(Bitmap obraz) { int h = obraz.Height; int w = obraz.Width; byte[, ,] wynik = new byte[w, h, 3]; BitmapData bd = obraz.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); int bytes = Math.Abs(bd.Stride) * h; byte[] rgbValues = new byte[bytes]; IntPtr ptr = bd.Scan0; System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); int padding = Math.Abs(bd.Stride) - (((w * 24) + 7) / 8); BitmapDataAccessor bda = new BitmapDataAccessor(rgbValues, w, h, padding); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { wynik[j, i, 0] = bda[j, i, 2]; wynik[j, i, 1] = bda[j, i, 1]; wynik[j, i, 2] = bda[j, i, 0]; } } obraz.UnlockBits(bd); return wynik; } And this is test I run:
private void btnLoad_Click(object sender, EventArgs e) { string s = ""; for (int i = 400; i < 409; i++) { Bitmap bmp = new Bitmap(i, i); bool ok = true; try { byte[,,] tab = Grafika.Bitmap2Byte(bmp); } catch { ok = false; } s += i + ": "; if (ok) s += "OK"; else s += "NOT OK"; s += "\n"; } StreamWriter w = StreamWriter(@"C:\lalala.txt"); w.Write(s); w.Close(); return; } Output:
400: OK 401: NOT OK 402: NOT OK 403: OK 404: OK 405: NOT OK 406: NOT OK 407: OK 408: OK Why do I get exceptions for w % 4 ==1 or w % 4 == 2?
EDIT:
I know what the exception is. It is 'Index out of bounds' and it happens in line
get { return data[(rowStarts[y] + x) * 3 + color]; }.
Unfortunately I don't know how to avoid this and why is it happening only for w % 4 ==1 or w % 4 == 2. That is why I posted my question. I don't need help with identyfying the exception or handling it. I just need to fix BitmapDataAccessor and/or Bitmap2Byte to make it work.
EDIT 2: Thanks to max's answer Bitmap2Byte doesn't throw Exceptions. But this makes my other function Byte2Bitmap Throw them:
public static Bitmap Byte2Bitmap(byte[, ,] tablica) { if (tablica.GetLength(2) != 3) { throw new NieprawidlowyWymiarTablicyException(); } int w = tablica.GetLength(0); int h = tablica.GetLength(1); int padding = w % 4; int ww=w; if (padding != 0) ww += 4 - padding; int bytes = 3 * ww * h; byte[] rgbValues = new byte[bytes]; int counter = -3; for (int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { counter += 3; rgbValues[counter] = tablica[i, j, 2]; rgbValues[counter + 1] = tablica[i, j, 1]; rgbValues[counter + 2] = tablica[i, j, 0]; } if(padding!=0) counter+= padding; } Bitmap obraz = new Bitmap(w, h, PixelFormat.Format24bppRgb); BitmapData bd = obraz.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); IntPtr ptr = bd.Scan0; System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes); obraz.UnlockBits(bd); return obraz; } And my output to show for which widths there is exception:
380: OK 381: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 382: OK 383: OK 384: OK 385: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 386: OK 387: OK 388: OK 389: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 390: OK 391: OK 392: OK 393: OK 394: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 395: OK 396: OK 397: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 398: OK 399: OK 400: OK 401: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 402: OK 403: OK 404: OK 405: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 406: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 407: OK 408: OK 409: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 410: OK 411: OK 412: OK 413: OK 414: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 415: OK 416: OK 417: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 418: OK 419: OK 420: OK 421: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 422: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 423: OK 424: OK 425: NOT OK: Nastąpiła próba odczytu lub zapisu pamięci chronionej. Często wskazuje to, że inna pamięć jest uszkodzona. 426: OK 427: OK 428: OK Exception occurs in line:
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
and its text means: There was try to read or write to/from protected memory...
I think this is because bytes is not calculated correctly. How can I do this right? I don't know how to get Exception message in English. Sorry about that.
sfdsgdfs.asdfile naming convention, myself.Exceptionto find out which sizes ofBitmapcauses problems. And you are right. I should have told everything. Sorry about that.paddingused for? Looks like it's the cause of the problem..