如何在C# Bitmap数据处理类中避免使用硬编码数值
解决动态图像尺寸下数组初始化的问题
嘿,这问题其实很好搞定——核心就是把数组的声明和初始化分开,让数组字段在构造函数里根据图像的动态尺寸来创建,这样输出方法就能正常访问啦。我给你一步步拆解解决方案:
关键修改思路
- 把原来硬编码初始化的数组字段,改成只做声明(不指定长度)
- 在构造函数里,根据
ImageToTreat的Width、以及你需要的行范围长度,动态初始化每个数组 - 顺便把代码里硬编码的数值(比如131)也改成动态计算的,彻底摆脱硬编码的限制
修改后的完整代码
class DataFromBitmap { static public Bitmap ImageToTreat; // 只声明数组,不初始化长度 double[] ValeurPixelsExperiment; double[] ValeurPixelsReference; double[] ValeurPixelsSumExperiment; double[] ValeurPixelsSumReference; int[] PixelColorCount; int[] PixelColorCountReady; /// <summary> /// Retrieves data from an input bitmap. Retrieved data : Ref and Exp pixel column mean values and count of each color level population. Output : double[] under ExpOutput() and RefOutput(), and int[] under ColorCountOutput /// </summary> /// <param Bitmap to treat="pImageToTreat"></param> public DataFromBitmap(Bitmap pImageToTreat) { ImageToTreat = pImageToTreat; unsafe { int width = ImageToTreat.Width; int height = ImageToTreat.Height; int bytesPerPixel = 1; int stride = width * bytesPerPixel; // 动态计算需要的数组长度,替代硬编码数值 int experimentRowRange = 288 - 157; // 对应原来的131 int referenceRowRange = 615 - 484; // 同样是131,这里也动态计算 int colorLevelCount = 256; // 如果这个也需要动态,可根据PixelFormat调整 // 动态初始化所有数组 ValeurPixelsExperiment = new double[experimentRowRange]; ValeurPixelsReference = new double[referenceRowRange]; ValeurPixelsSumExperiment = new double[width]; ValeurPixelsSumReference = new double[width]; PixelColorCount = new int[colorLevelCount]; PixelColorCountReady = new int[colorLevelCount]; System.Drawing.Imaging.BitmapData bData = ImageToTreat.LockBits( new System.Drawing.Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.ReadWrite, ImageToTreat.PixelFormat); byte* scan0 = (byte*)bData.Scan0.ToPointer(); byte B; for (int i = 0; i < width; i++) { // 处理实验像素行 for (int j = 157; j < 288; j++) { int Pixel = bytesPerPixel * i + stride * j; B = scan0[Pixel + 0]; ValeurPixelsExperiment[j - 157] = B; PixelColorCount[B] += 1; } // 用动态计算的长度替代硬编码的131 ValeurPixelsSumExperiment[i] = ValeurPixelsExperiment.Sum() / (experimentRowRange - 1); // 处理参考像素行 for (int j = 484; j < 615; j++) { int Pixel = bytesPerPixel * i + stride * j; B = scan0[Pixel + 0]; ValeurPixelsReference[j - 484] = B; PixelColorCount[B] += 1; } ValeurPixelsSumReference[i] = ValeurPixelsReference.Sum() / (referenceRowRange - 1); } ImageToTreat.UnlockBits(bData); PixelColorCountReady = PixelColorCount.DeepClone(); } } public double[] ExpOutput() { return ValeurPixelsSumExperiment; } public double[] RefOutput() { return ValeurPixelsSumReference; } public int[] ColorCountOutput() { return PixelColorCountReady; } }
重点说明
- 数组字段的声明:把原来带硬编码长度的初始化去掉,只保留字段类型和名称,这样我们就能在构造函数里动态分配内存。
- 动态长度计算:
ValeurPixelsSumExperiment和ValeurPixelsSumReference的长度直接用width(也就是ImageToTreat.Width),完美适配不同宽度的图像。- 对于
ValeurPixelsExperiment这类依赖行范围的数组,我们用288-157计算出长度,避免硬编码131,后续如果行范围调整,只需要改这两个数字就行。
- 输出方法的访问性:因为数组字段是类的成员变量,构造函数初始化后,
ExpOutput()等方法自然能访问到这些数组,完全没问题。
另外提个小建议:ImageToTreat设为static可能会有线程安全问题,如果你的项目是多线程处理图像,最好改成实例字段哦。
内容的提问来源于stack exchange,提问作者Trion
相关产品推荐
相关产品推荐

