【转】胶片曝光时的排版!!!!!!!
這個本來沒啥 不是什么算法 絕技。 都不值得一提。
其實這個是醫學影像膠片曝光時排版的一個邏輯。
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協議的通訊 ,看來下次吧。
源碼及測試文件下載猛擊此處
總結
以上是生活随笔為你收集整理的【转】胶片曝光时的排版!!!!!!!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第一次办信用卡没通过怎么办
- 下一篇: 个人如何进行黄金投资?黄金投资的主要方式