如何在Fo-Dicom中创建并显示Overlay?代码异常排查求助
在Fo-Dicom中创建并显示Overlay层的问题排查与修复
你的代码无法显示Overlay的核心问题在于Dicom Overlay的位序规则未遵守,以及数据长度计算、像素映射逻辑存在偏差,以下是具体问题点和修复方案:
核心问题分析
- 位序错误:Dicom标准规定,Overlay的每个字节内,像素位是从**最高位(Bit7)到最低位(Bit0)**对应图像的从左到右像素,而你的代码直接将BitArray按默认顺序拷贝,导致位序完全反转。
- 数据长度计算不严谨:代码中用
bits.Length / 8计算字节数,当像素总数不是8的倍数时,会丢失最后几个像素位,应该向上取整。 - 像素映射的行顺序问题:虽然RenderTargetBitmap的行顺序与Dicom一致,但未针对每行的位序做反转处理,导致Overlay显示错位。
修复后的代码
DicomFile dicomFile = DicomFile.Open(sourceDicomFileName, FileReadOption.ReadAll); ushort width = dicomFile.Dataset.GetSingleValue<ushort>(DicomTag.Columns); ushort height = dicomFile.Dataset.GetSingleValue<ushort>(DicomTag.Rows); byte[] packedbitarray = Array.Empty<byte>(); Application.Current.Dispatcher.Invoke(() => { var grid = new Grid { Width = width, Height = height }; var text = new TextBlock { Text = "OVERLAY", FontSize = 32, FontWeight = FontWeights.Bold, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center // 确保文本垂直居中 }; grid.Children.Add(text); grid.Measure(new Size(grid.Width, grid.Height)); grid.Arrange(new Rect(new Size(grid.Width, grid.Height))); var rtb = new RenderTargetBitmap( (int)grid.Width, (int)grid.Height, 96, 96, PixelFormats.Pbgra32); rtb.Render(grid); int stride = rtb.PixelWidth * 4; int size = rtb.PixelHeight * stride; byte[] coloredPixels = new byte[size]; rtb.CopyPixels(coloredPixels, stride, 0); // 计算Overlay所需字节数:向上取整(宽*高 / 8) int overlayByteCount = (int)Math.Ceiling((width * height) / 8.0); packedbitarray = new byte[overlayByteCount]; // 逐行处理,修正位序 for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // 取Alpha通道判断像素是否可见 int pixelIndex = (y * stride) + (x * 4) + 3; bool isPixelSet = coloredPixels[pixelIndex] != 0; // 计算当前位在字节中的位置:行内左到右对应Bit7到Bit0 int bitPosition = 7 - (x % 8); int byteIndex = (y * width + x) / 8; if (isPixelSet) { packedbitarray[byteIndex] |= (byte)(1 << bitPosition); } } } }); // 用AddOrUpdate避免重复标签异常,确保Overlay属性正确 dicomFile.Dataset.AddOrUpdate(new DicomUnsignedShort(DicomTag.OverlayColumns, width)); dicomFile.Dataset.AddOrUpdate(new DicomUnsignedShort(DicomTag.OverlayRows, height)); dicomFile.Dataset.AddOrUpdate(new DicomCodeString(DicomTag.OverlayType, "G")); dicomFile.Dataset.AddOrUpdate(new DicomSignedShort(DicomTag.OverlayOrigin, new short[] { 1, 1 })); dicomFile.Dataset.AddOrUpdate(new DicomUnsignedShort(DicomTag.OverlayNumber, 1)); dicomFile.Dataset.AddOrUpdate(new DicomUnsignedShort(DicomTag.OverlayBitsPerPixel, 0)); dicomFile.Dataset.AddOrUpdate(new DicomOtherByte(DicomTag.OverlayData, packedbitarray)); dicomFile.Save(destDicomFileName);
额外注意事项
- 部分Dicom阅读器默认关闭Overlay显示,需在阅读器设置中开启Overlay渲染开关。
- 确保Overlay的尺寸(Columns/Rows)与主图像完全一致,否则会显示错位或不显示。
内容的提问来源于stack exchange,提问作者Basavaprasad Kotarki
相关产品推荐
相关产品推荐

