为什么我不断收到异常?
有一些代码:为什么我不断收到异常?
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;
}
这是我的测试运行:
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;
}
输出:
400: OK
401: NOT OK
402: NOT OK
403: OK
404: OK
405: NOT OK
406: NOT OK
407: OK
408: OK
为什么我得到w % 4 ==1
或异常?
编辑:
我知道什么是例外。它是'指数越界',它发生在get { return data[(rowStarts[y] + x) * 3 + color]; }
。
不幸的是我不知道如何避免这种情况,为什么只发生在w % 4 ==1
或。这就是我发布我的问题的原因。我不需要识别异常或处理它的帮助。我只需要修复BitmapDataAccessor
和/或Bitmap2Byte
以使其工作。
编辑2: 感谢max的回答Bitmap2Byte
不会抛出异常。但是,这使我的其他功能Byte2Bitmap
抛出异常:
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;
}
而且我的输出,以显示其宽度有例外:在线路发生
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
例外:System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
及其文本方式:There was try to read or write to/from protected memory...
我认为这是因为bytes
计算不正确。我该如何做到这一点? 我不知道如何获得英文的异常信息。对于那个很抱歉。
尝试计算填充作为
int padding = Math.Abs(bd.Stride) - (w * 3);
(至少它更可读的)
并修复为BitmapDataAccessor
:
public BitmapDataAccessor(byte[] data, int width, int height, int padding)
{
this.data = data;
this.Height = height;
// width in bytes, not pixels
this.Width = width * 3 + padding;
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]
{
// row offsets already in bytes, so don't myltiply them by 3
get { return data[rowStarts[y] + x * 3 + color]; }
set { data[rowStarts[y] + x * 3 + color] = value; }
}
大约第二问题备注:
类似问题在这里 - 你计算填充像素,而不是字节。
int ww = w * 3;
int padding = (4 - (ww % 4)) % 4;
int bytes = (ww + padding) * h;
byte[] rgbValues = new byte[bytes];
int rowOffset = 0;
for (int j = 0; j < h; j++)
{
int pixelOffset = rowOffset;
for (int i = 0; i < w; i++)
{
rgbValues[pixelOffset + 0] = tablica[i, j, 2];
rgbValues[pixelOffset + 1] = tablica[i, j, 1];
rgbValues[pixelOffset + 2] = tablica[i, j, 0];
pixelOffset += 3;
}
rowOffset += ww + padding;
}
它会更有用,而不是简单地收集'ok'或'not ok',以实际检查抛出的异常,这会给你更多关于什么是不正确的信息。
尝试增加
Console.WriteLine(ex.ToString());
到catch
块。
填充不是数字或像素。它是字节数。
但是,我仍然不知道如何修复你的代码。也许别人可以做到这一点?
也许如果你真的打印出异常而不是吞咽它并将其设置为false,你会发现。异常消息通常非常有用,你知道... – 2011-01-13 13:34:57
必须说,我更喜欢`sfdsgdfs.asd`文件命名约定,我自己。 – 2011-01-13 13:38:00
`lalala.txt`很好玩的名字:P – 2011-01-13 14:02:39