【转】胶片曝光时的排版!!!!!!!

这个本来没啥 不是什么算法 绝技。 都不值得一提。

其实这个是医学影像胶片曝光时排版的一个逻辑。

dicom标准第三部分 主要是讲IOD定义 在第166页有这样的描述:

表C.13.5-1图象盒象素描述组件
属性名称    标记          说明
图象位置    (2020,0010)     基于图象显示格式(2010,0010)的胶片的图象位置。
参阅C.13.5.1的规范。

这个所谓的“基于图象显示格式(2010,0010)的胶片的图象位置”到底是啥意思呢 ?还是像往常一样拿个实例瞧瞧:
20 20 10 00     ............  ..
00000010    02 00 00 00 02 00
20 20 10 00     ............  ..
00000010    02 00 00 00 03 00

dicom数据元素的结构就不多说了哈 详情请查看dicom标准。只看最后两位,可见这个所谓的“基于图象显示格式(2010,0010)的胶片的图象位置” 就是一个个的从前到后的排序。从设备工作站发送胶片曝光作业的时候 根据dicom协议 图像传输 那么它就是以这种 “序列”的方式发送的。
再看dicom标准另外一段 第三部分167页 :

C.13.5.1图象位置


胶片中图象的位置;图象位置序列的编码是基于选择的图象显示格式
(2010,0010)。图象位置序列以值1递增。
图象位置(2020,0010)定义如下:
-    标准显示格式:                 图象盒序列是主要行顺序(从左到右或从上到下);左上图象位置等于1。
-    行显示格式:                    图象盒序列是主要行顺序(从左到右或从上到下);左上图象位置等于1。
-    列显示格式:                    图象盒序列是主要列顺序(从左到右或从上到下);左上图象位置等于1。
-    SLIDE显示格式:             图象盒序列是主要行顺序(从左到右或从上到下);左上图象位置等于1。
-    SUPERSLIDE显示格式:图象盒序列是主要行顺序(从左到右或从上到下);左上图象位置等于1。

关于ImgBox 的几种方式的细节我们暂时不去管 只管第一种 ,因为就我遇到的 90%以上都是 “标准显示格式”在胶片曝光dimse的过程中 createFilmBox 的时候 会收到一个参数 command元素0x20100010, 它的值是类似这样STANDARD\1,1  这个standard 就是表示 这是一个“标准显示格式” 逗号分隔开的两个数字 第一个是列数 第二个是行数。标准显示格式就是: (在一个指定行数列数的网格里把图像按从左到右从上到下的方式排列)
如图:

说到底我们要实现的就是根据dicom标准 把这种依次编号的图像拼接成 一个整幅的网格图像 让它打印出来看上去跟工作站上阅片时的所见即所得,可以根据编号获取指定图像 可以根据几行几列或许指定图像 可以根据编号获知他是第几行第几列 可以根据第几行第几列获知他的编号。就这样简单。

来简单分析下,可以通过STANDARD\colNum,rowNum 来确定行数跟列数。这就容易了

他是一个“持续堆叠的过程”

第一行堆满了堆第二行 从左往右的不断堆。
以x表示列 y表示行 从1开始,num表示编号 从1开始 , 可以得出这样的结论:
for(1 to num)
{
    if(num%colNum!=0)//不能除尽
     {
        y=num/colNun+1;
         x=num%colNum;
    else
     {
        y=num/colNun;
        x=colNum;
     }
}
你能理解这个过程么 ?什么, 能用么 你可以验证下:
num=7
7%3!=0
{
  y=7/3+1=>3
  x=7%3=>1
}

num=6
6%3==0
{
  y=6/3=>2
  x=3=>3
}

num=5
5%3!=0
{
  y=5/3+1=>3
  x=5%3=>2
}

为什么要确定x跟y呢,因为输出的时候要给单幅图像定位 就是左上角 有了x跟y 才能够实现。可以有一个image的数组 用来存储接收到的图像 它们按照编号从前到后排列。

解决一个问题了

还有另外一个问题 图像的缩放。

如果我假设输出区域是宽度=297 高度=420。胶片的分格是4行3列 。那么单幅图像的尺寸是 宽度=297/3 高度=420/4 但是每个分格的图像尺寸通常是不固定的,就像普通的看图软件都有个显示比例叫“缩放到显示区域” 我们要做的就是这个 这一过程可以用这个图说明:

预先就设定图像都有两种等比例缩放尺寸 高度对齐(让高度跟可显示区域相等) 宽度对齐(让宽度跟可显示区域相等)。
这里有一个简单的等比例公式 缩放前后
宽度对齐情况下:
显示区域宽(缩放后的宽度)/原图宽=缩放后的高度/原图高
高度对齐情况下:
显示区域高(缩放后的高度)/原图高=缩放后的宽度/原图宽
分别得出两种情况另一边的长度
显示区域宽(缩放后的宽度)*原图高/原图宽=缩放后的高度
显示区域高(缩放后的高度)*原图宽/原图高=缩放后的宽度

然后对两种情况进行判断,如果哪种情况缩放后的图像区域超出了显示范围 则被否决。
如下图 蓝色框代表图像 ,黑色框代表显示区域:

就这样就达到了适应显示范围的等比例缩放。简单吧。
怎么把上述思路整合 然后用代码实现,首先我们得定义一个类 这个类叫Paper 相当于一张胶片 他是待打印区域 。
然后相应的要有 行数列数 显示区域高度宽度 等变量, 还要有一个image数组用来存储顺序编号排列的图像。

 

 1 public class Paper2 {3     int row, col;//行数 与 列数4     int width, height;//胶片宽度 高度5     IList<Image> images;//顺序编号的图像6 7     public Paper(int _width, int _height, int _row, int _col)8     {9         width = _width; height = _height; row = _row; col = _col;
10         images = new List<Image>(row * height);
11     }
12     //初始化显示区域
13     public Paper(int _row, int _col)
14     {
15         //width = 345 * 9; height = 420 * 9; row = _row; col = _col;//14INx17IN
16         width = 297 * 9; height = 420 * 9; row = _row; col = _col;//A3
17         images = new List<Image>(row * height);
18     }
19     //新增图像
20     public void addImg(Image img)
21     {
22         if (images.Count >= row * col)
23             return;
24         else
25         {
26             images.Add(img);
27         }
28     }
29 }

 

这相当于又是定义了一个数据模型的框架 初始化一个实例代表输出一张新的胶片。面向对象的分析设计是多么的好 哇哈哈。
材料有了 。下面这个函数才是重头戏,用于实现第一部分 分析的所有逻辑[胶片排版 跟 图像缩放],请对照第一部分的说明来看:

 

 1 //排版后的输出2 //排版方式为从上到下从左到右3 public Image layout()4 {5     Image layouted = new Bitmap(width, height);6 7     Graphics g = Graphics.FromImage(layouted);8     g.Clear(Color.Green);9     for (int i = 0; i < images.Count; i++)
10     {
11         int _row, _col;
12         if ((i + 1) % col != 0)
13         {
14             _row = (i + 1) / col + 1 - 1;  //    _row = (i + 1) / col + 1 - 1;
15             _col = (i + 1) % col - 1;  //    _col = (i + 1) / col - 1;
16         }
17         else
18         {
19             _row = (i + 1) / col - 1;
20             _col = col - 1;
21         }
22         if (_col < 0)
23         {
24             _col = 0;
25         }
26         if (_row < 0)
27         {
28             _row = 0;
29         }
30         GraphicsUnit u = GraphicsUnit.Pixel;
31         RectangleF recSrc = images[i].GetBounds(ref u);//原图像大小
32         RectangleF recDst;//缩放后大小并调整偏移位置
33 
34         //宽比宽 =长比长 超出的那一边需要固定长度 缩小以调整到视野内
35         float recH = ((width / col) * recSrc.Height) / recSrc.Width,
36             recW = ((height / row) * recSrc.Width) / recSrc.Height;
37 
38         if (recW > (width / col))//宽度超出 固定宽度调整高度
39             recDst = new RectangleF((width / col) * _col + 0,
40                 (height / row) * _row + ((height / row) - recH) / 2,
41                 (width / col), recH);
42         else//高度超出 固定高度调整宽度
43             recDst = new RectangleF((width / col) * _col + ((width / col) - recW) / 2,
44                 (height / row) * _row + 0,
45                 recW, (height / row));
46 
47         g.DrawImage(images[i], recDst, images[i].GetBounds(ref u), u);
48         //if (i == 4)
49         images[i].Save(i + "out.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
50     }
51 
52     //layouted.Save("layout.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
53     g.Dispose();
54 
55     return layouted;
56 }

 

调用:

 

1 Paper film = new Paper(3, 2);
2 film.addImg(Image.FromFile("1.jpg"));
3 film.addImg(Image.FromFile("2.jpg"));
4 film.addImg(Image.FromFile("3.jpg"));
5 film.addImg(Image.FromFile("4.jpg"));
6 film.addImg(Image.FromFile("5.jpg"));
7 film.addImg(Image.FromFile("6.jpg"));
8 
9 film.layout();

 


一直说想要讲下dicom协议的通讯 ,看来下次吧。
源码及测试文件下载猛击此处

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/435921.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机课数学,这4个专业,对数学要求很高,数学不好的慎选!

建筑学专业这个专业就是典型数学课程比较多的专业&#xff0c;如果数学成绩不好&#xff0c;真心建议千万不要选择这个专业&#xff0c;因为学习的课程与大多与数学有关&#xff0c;而且难度较大。像代数&#xff0c;微积分&#xff0c;线性规划&#xff0c;统计学等课程都是在…

架构师之路(5)---IoC框架

1 IoC理论的背景 我们都知道在面向对象的应用中&#xff0c;软件系统都是由N个对象组成的&#xff0c;它们通过彼此的合作&#xff0c;最终实现业务逻辑。 图1&#xff1a;耦合在一起的对象 如果我们打开机械式手表的后盖&#xff0c;就会看到与上面类似的情形&#xff0c;各…

【转】数据库软考笔记(一)第一章 计算机硬件基础知识笔记总结

转自&#xff1a;https://blog.csdn.net/qq_36411874/article/details/115057569 目录 运算器&#xff1a;ALU、AC、DR、PSW 控制器&#xff1a;IR、PC、AR、ID 寄存器组&#xff08;了解即可&#xff09; 存储器 存储器与总线&#xff08;了解&#xff0c;考分类&#xf…

【转】DICOM医学图像处理:开源库mDCM与DCMTK的比較分析(一),JPEG无损压缩DCM图像

转自&#xff1a;https://www.cnblogs.com/mfrbuaa/p/4004114.html 有修订 背景介绍&#xff1a; 近期项目需求&#xff0c;需要使用C#进行最新的UI和相关DICOM3.0医学图像模块的开发。在C语言下&#xff0c;我使用的是应用最广泛的DCMTK开源库&#xff0c;在本专栏的起初阶段…

xfire客户端对返回list很挑剔,所以需要使用泛型。

casldap异常分析 | xfirewebservice(服务器配置篇) 2008-12-31xfirewebservice(客户端调用篇) 服务接口&#xff0c;就是用来调用的&#xff0c;所以客户端显得尤为重要&#xff0c;xfire客户端对返回list很挑剔&#xff0c;所以需要使用泛型。 如何建立webservice client 步骤…

在虚拟机上运行vxWorks

Vxworks是一个嵌入式系统&#xff0c;主要运行在arm、ppc、mips等嵌入式处理器上&#xff0c;它同样可以运行在X86处理器上。风河公司开发的tornado开发环境就 包括了pentium版本&#xff0c;并且发布了相应的bsp。因此我们可在vmware虚拟机上运行vxworks&#xff0c;利用虚拟机…

使用SDL打造游戏世界之入门篇 - 7

打开和显示图片在这个例子里我们将学习如何使用SDL程序中打开和显示图片。示例程序将绘制一个漂亮的背景&#xff0c;上面显示一个正方形图案&#xff0c;并可以使用键盘的方向键移动它。如果比较熟悉“推箱子”这个游戏&#xff0c;可以看出这个程序实际就是推箱子游戏的基础。…

【转】GPS从入门到放弃(一) --- GPS基础原理

转自&#xff1a;https://blog.csdn.net/tyst08/article/details/100529424 GPS从入门到放弃&#xff08;一&#xff09; — GPS基础原理 GPS&#xff0c;全称Global Positioning System&#xff0c;已经广泛应用于我们的日常生活中了&#xff0c;现在的智能手机 里都会自带G…

【转】10个推荐的 PACS/DICOM Server开源项目

10个推荐的 PACS/DICOM Server开源项目 转自&#xff1a;https://zhuanlan.zhihu.com/p/65437040 soolaugust 喜欢我的分享可以关注公众号&#xff1a;雨夜随笔 35 人赞同了该文章 本文仅授权给公众号&#xff1a;雨夜随笔&#xff0c; 欢迎关注 本文翻译自&#xff1a;To…

字节序、位序

字节序 字节序&#xff0c;又称端序、尾序&#xff0c;英文单词为Endian&#xff0c;该单词来源于于乔纳森斯威夫特的小说《格列佛游记》&#xff0c;小说中的小人国因为吃鸡蛋的问题而内战&#xff0c;战争开始是由于以下的原因&#xff1a;我们大家都认为&#xff0c;吃鸡蛋前…

怎么抓取屏幕截图计算机考试时间,定时抓屏快照(电脑截屏工具)V4.8 最新版

定时抓屏快照(电脑截屏工具)是一款非常实用的电脑屏幕定时抓拍软件。想定时截取电脑屏幕&#xff1f;定时抓屏快照(电脑截屏工具)轻松帮助用户。马上要放假了&#xff0c;家长一定很担心小孩最新的上网情况&#xff0c;看是在电脑上玩什么&#xff0c;用户通过该软件可以及时了…

【转】matlab函数编译成dll供Cpp调用的方法

转自&#xff1a;https://www.cnblogs.com/vincenzo/archive/2009/09/09/1563467.html 以前做过matlab7与c的混合编程&#xff1a;将m函数编译成dll给C调用&#xff0c;从而加快开发的进度。但是今天在matlab2008b下面又做了一遍&#xff0c;发现matlab又改了很多东西&#xf…

可以测试流放之路伤害的软件,测试平台及细节一览 - 《流放之路》国服硬件需求测试:低配也能续写ARPG传奇 - 超能网...

测试平台、场景说明测试平台测试平台配置主要分为两套&#xff0c;第一套配置为Skylake平台基础搭建的ASUS MAXIMUS VIIIGEN(Z170)主板&#xff0c;处理器为Intel Core i7-6700K&#xff0c;内存是G.Skill Ripjaws V 4GB DDR43200x2组成的双通道&#xff1b;第二套配置为Kaveri…

关于增强(五)-Class Enhancement

Class/Interface增强允许增加&#xff0c; 对已有的方法增加可选参数 添加方法&#xff0c;事件&#xff0c;事件处理 参考接口 对存在的方法添加出口&#xff0c;其中包括方法开始前的出口&#xff08;Pre-Exit&#xff09;&#xff0c;方法结束快结束的出口(Post-Exit)&#…

【转】彻底理解cookie,session,token

转自&#xff1a;https://zhuanlan.zhihu.com/p/63061864 彻底理解cookie&#xff0c;session&#xff0c;token 发展史 1、很久很久以前&#xff0c;Web 基本上就是文档的浏览而已&#xff0c; 既然是浏览&#xff0c;作为服务器&#xff0c; 不需要记录谁在某一段时间里都浏…

【转】c#数字图像处理(一)Bitmap类、 Bitmapdata类和 Graphics类

转自&#xff1a;https://www.cnblogs.com/dearzhoubi/p/8553763.html Bitmap类、 Bitmapdata类和 Graphics类是C#图像处理中最重要的3个类,如果要用C# 进行图像处理,就一定要掌握它们。 1.1 Bitmap类 Bitmap对象封装了GDI中的一个位图,此位图由图形图像及其属性的像素数据组成…

【转】c#数字图像处理(二)彩色图像灰度化,灰度图像二值化

转自&#xff1a;https://www.cnblogs.com/dearzhoubi/p/8571652.html 为加快处理速度,在图像处理算法中,往往需要把彩色图像转换为灰度图像,在灰度图像上得到验证的算法,很容易移 植到彩色图像上。 24位彩色图像每个像素用3个字节表示,每个字节对应着R、G、B分量的亮度(红、绿…

【转】c#数字图像处理(三)灰度直方图

转自&#xff1a;https://www.cnblogs.com/dearzhoubi/p/8621804.html 灰度直方图是灰度的函数,描述的是图像中具有该灰度级的像素的个数。如果用直角坐标系来表示,则它的横坐标是灰度级,纵坐标是该灰度出现的概率(像素的个数)。 using System; using System.Collections.Gener…

电梯门禁系统服务器一般在哪,别被吓住了,电梯门禁(梯控)安装其实并不难...

电梯门禁又称梯控&#xff0c;主要用于对电梯的出入权限进入控制&#xff0c;只有授权卡在读卡器刷过后&#xff0c;才能到达指定楼层。梯控的使用越来越普遍了&#xff0c;很多人觉得梯控很神秘&#xff0c;很高不可攀&#xff0c;其实说到底它不过是门禁的一种&#xff0c;只…

【转】c#数字图像处理(四)线性点运算

转自&#xff1a;https://www.cnblogs.com/dearzhoubi/p/8622325.html 灰度图像的点运算可分为线性点运算和非线性点运算两种。 4.1线性点运算定义 线性点运算就是输出灰度级与输入灰度级呈线性关系的点运算。在这种情况下,灰度变换函数的形式为: g(x, y)pf(x,y)L 其中 f(x,…