Twain
隨著掃描器、數位相機和其他影像採集裝置的引入,使用者熱切地發現了將影像整合到他們的文件和其他工作中的價值。然而,支援這種光柵資料的顯示和操作成本很高,應用程式開發人員需要建立使用者介面並內建裝置控制各種各樣可用的影像裝置。
一旦他們的應用程式準備好支援給定的裝置,他們就會面臨一個令人沮喪的現實:裝置不斷地升級新的功能和特性。應用程式開發人員發現他們不斷地修改他們的產品,以保持最新影像採集裝置和軟體應用程式的開發人員都認識到需要影像裝置和應用程式之間的標準通訊。一個標準有利於使用他們產品的用。它將允許更多的應用程式訪問裝置供應商的產品,而應用程式供應商可以訪問來自這些裝置的資料,而不需要關心提供這些資料的是哪種型別的裝置或特定的裝置。
TWAIN的開發正是出於對一致性和簡化的需要。
Twain 開發簡介
TWAIN定義了一個標準的軟體協議和API(應用程式程式設計介面),用於在軟體應用程式和影像採集裝置(資料的來源)之間進行通訊。
Twain的三個關鍵要素是:
- Application software
必須修改應用程式才能使用TWAIN。 - Source Manager software
該軟體管理應用程式和源程式之間的互動。這段程式碼在TWAIN開發者的工具包中提供,每個TWAIN應用程式和原始碼都應該免費提供。 - Source software
該軟體控制影像採集裝置,由裝置開發人員按照TWAIN規範編寫。傳統的裝置驅動程式現在包含在源軟體中,不需要由應用程式提供。
關於這幾要素是什麼關係呢?通俗的說就是Twain是一個協議,這個協議不需要我們自己去實現和裝置(我這裡是掃描器)的通訊,這個通訊是由一個叫做Data Source Manager的來提供,我們的應用程式只需要呼叫Data Source Manager對應的功能,然後由Data Source Manager去負責和支援Twain協議的裝置通訊(準確的說應該是裝置的驅動)。
這個Data Source Manager 在windows裡面就是由twain_32.dll實現。
Twain協議PDF https://ask.qcloudimg.com/draft/7651952/jhzuki5dnp.pdf
Twain通訊過程
TWAIN元素之間的通訊可以通過兩個入口點實現。他們是DSM_Entry()和DS_Entry()。DSM指資料來源管理器(也就是twain_32.dll),DS指資料來源(驅動程式)。
應用程式的目標是從源獲取資料。但是應用程式不能直接呼叫源。所有對資料、功能資訊、錯誤資訊等的請求都必須通過源管理器處理。
Twain定義了大約140個操作。應用程式將它們傳送到源管理器進行傳輸。應用程式指定哪個元素(源管理器或源)是每個請求操作的最終目的地。
應用程式通過源管理器唯一的入口點DSM_Entry()函式與源管理器通訊。DSM_Entry函式的引數列表包含:
- 一個識別符號結構,提供關於發起函式呼叫的應用程式的資訊。
- 請求的目的地(源管理器或源)。
- 描述請求操作的三元組(triplet)。三元組指:
操作的資料組(DG_)
操作的資料引數型別(DAT_)
操作的訊息(MSG_) - 函式呼叫返回一個值(返回碼),指示操作的成功或失敗。
TW_UINT16 TW_CALLINGSTYLE DSM_Entry
( pTW_IDENTITY pOrigin, // source of message
pTW_IDENTITY pDest, // destination of message
TW_UINT32 DG, // data group ID: DG_xxxx
TW_UINT16 DAT, // data argument type: DAT_xxxx
TW_UINT16 MSG, // message ID: MSG_xxxx
TW_MEMREF pData // pointer to data
);
Twain狀態
應用程式、源管理器和源必須通訊來管理資料的獲取。這個過程必須以特定的順序發生,這是合乎邏輯的。例如,在載入源管理器並準備好進行請求通訊之前,應用程式無法成功地請求來自源的資料傳輸。為了保證序列的正確執行,TWAIN協議定義了在TWAIN會話中存在的七種狀態。會話是應用程式通過源管理器連線到特定源的時間段。
應用程式連線到源管理器的期間是一個唯一的會話,Source Manager和Source的TWAIN元素都佔據一個特定的狀態。到新狀態的轉換是由應用程式或源請求的操作引起的,轉換可以向前或向後進行。大多數轉換都是單狀態轉換。
轉換狀態圖如下:
State 1 to 2 -載入source manager 獲取 DSM_Entry介面
State 2 to 3 - 開啟source manager
State 3 - 選擇 Source
State 3 to 4 - 開啟 Source
State 4 - 設定source的Capabilities
State 4 to 5 - 請求從source獲取資料
State 5 to 6 - 資料可以準備訊息
State 6 to 7 - 開始資料傳輸
State 7 to 6 to 5 - 完成傳輸
State 5 to 1 - 斷開連線
C# 呼叫
應用程式呼叫Source Manager,使用NTwain進行操作,在nuget裡面新增引用。
對應的github地址,裡面有原始碼和demo: https://github.com/soukoku/ntwain/tree/v3
新增引用後開啟source manager,然後可以選擇Source 或者載入預設Source。
開啟Source後狀態為4 則我們可以對裝置進行設定,而設定這些功能存在於許多種類中,但都有預設值、當前值和可能的值
其他可選的可支援的值。這些種類可以在協議裡面查到,也就是驅動裡面對應的各種設定。在Twain協議裡面把這些功能叫做Capabilities ,對應的NTwain包裡面也封裝了,比如設定掃描器雙面掃描
_twain.CurrentSource.Capabilities.CapDuplexEnabled.SetValue(BoolType.True);
關於富士通fujitsu設定影像模式:多影像輸出
這裡有個大坑,在使用NTwain設定的時候通過CapPixelType設定影像模式只能設定黑白灰度彩色三種,通過如下程式碼:
_twain.CurrentSource.Capabilities.ICapPixelType.SetValue(PixelType.RGB)
不能設定多圖輸出,在驅動裡面找看到圖片確實只支援這幾種方式,然後我一直以為是我看掉了哪個功能,看完了Twain協議,然後去網上各種找沒有這方面的資料,大部分都是很簡單的介紹,糾結了一週沒有搞清楚。然後搜到vintasoft 這個網站的時候看到一個提問才恍然大悟,原來這個設定Twain標準協議裡面確實沒有這個,我估計是富士通廠家自己搞的一個。因為上面Twain通訊過程說了各種操作只能通過DSM_Entry()函式,並且只要你傳入的三元組的( TW_UINT16 DAT,// data argument type: DAT_xxxx) Id正確且支援就行了。
使用如下程式碼new一個多影像輸出功能物件,然後像其它一樣設定即可。
new CapWrapper<MutilImageOutPutType>(dataSource, (CapabilityId)0x80f2, ValueExtensions.ConvertToEnum<MutilImageOutPutType>,
value => new TWOneValue
{
Item = (uint)value,
ItemType = ItemType.UInt16
});
public enum MutilImageOutPutType : ushort
{
Disabled = 0,
RGBAndBW = 1,
BWAndRGB = 2,
Enabled = 3,
Auto = 4,
}
最後掃描獲取圖片