TIF圖像文件的讀取(c++代碼)

一 TIF圖像介紹

??? TIFF是最復雜的一種位圖文件格式。TIFF是基于標記的文件格式,它廣泛地應用于對圖像質量要求較高的圖像的存儲與轉換。由于它的結構靈活和包容性大,它已成為圖像文件格式的一種標準,絕大多數圖像系統都支持這種格式。

?? TIFF 是一個靈活適應性強的文件格式,通過在文件頭中包含“標簽”它能夠在一個文件中處理多幅圖像和數據。標簽能夠標明圖像的如圖像大小這樣的基本幾何尺寸或者定義圖像數據是如何排列的并且是否使用了各種各樣的圖像壓縮選項。例如,TIFF可以包含JPEG和行程長度編碼壓縮的圖像。TIFF文件也可以包含基于矢量的裁剪區域(剪切或者構成主體圖像的輪廓)。使用無損格式存儲圖像的能力使TIFF文件成為圖像存檔的有效方法。與JPEG不同,TIFF文件可以編輯然后重新存儲而不會有壓縮損失。其它的一些TIFF文件選項包括多層或者多頁。

  盡管現今它是一種被廣泛接受的標準格式,當TIFF最初出現的時候,它的可擴展性帶來了很多兼容問題。程序員可以隨意定義新的標簽和選項,但是并不是所有的實現程序都能支持這些所有這些創造出的標簽。作為結果,它的一個最小特性集成為了“這個”TIFF,即使是在今天大量的TIFF文件和讀取它們的代碼都是基于簡單的32位非壓縮圖像。

  TIFF有一個使用LZW壓縮的選項,這是一種減小文件大小的無損技術,但是這項技術在不同的司法權限內為幾個專利所涵蓋。到了2005年,除了一個之外這些專利都已經到期,其中包括Unisys所擁有的廣為人知又有很多爭議的專利。另外一個著名的專利是IBM擁有的將在2006年8月11日到期的專利,IBM也沒有要加強它的意思(who has shown no interest to date in enforcing it)。

  每個TIFF文件都是從指示字節順序的兩個字節開始的。“II”表示小字節在先、“MM”表示大字節在先字節順序。后面的兩個字節表示數字42。數字42是“為了其深刻的哲學意義"而選擇的。 42的讀法取決于頭兩個字節所表示的字節順序。整個文件根據所指出的字節順序進行讀取。

  字節順序在Apple Macintosh和微軟視窗程序之間可能產生兼容性的問題,它們通常為TIFF文件使用不同的字節順序。一些程序提供了保存為Mac或者是Windows字節順序的選項以使文件能在交叉平臺使用。

二TIF圖像的讀取

??? 1.TIF的存儲結構

?????? TIFF文件以.tif為擴展名。其數據格式是一種3級體系結構,從高到低依次為:文件頭、一個或多個稱為IFD的包含標記指針的目錄和數據。

??? 1.文件頭(IFH)

  在每一個TIFF文件中第一個數據結構稱為圖像文件頭或IFH,它是圖像文件體系結構的最高層。這個結構在一個TIFF文件中是惟一的,有固定的位置。它位于文件的開始部分,包含了正確解釋TIFF文件的其他部分所需的必要信息。

???

??????? IFH數據結構包含3個成員共計8個字節,Byte order成員可能是“MM”(0x4d4d)或“II”(0x4949),0x4d4d表示該TIFF圖是摩托羅拉整數格式 0x4949表示該圖是Intel整數格式;Version成員總是包含十進制42(0x2a),它用于進一步校驗該文件是否為TIF格式,42這個數并 不是一般人 想象中的那樣認為是tif軟件的版本,實際上,42這個數大概永遠不會變化;第三個成員是IFD(接下來要說的第二個數據結構)相對文件開始處的偏移量。

??? 2.圖像文件目錄(IFD)

  IFD是TIFF文件中第2個數據結構,它是一個名為標記(tag)的用于區分一個或多個可變長度數據塊的表,標記中包含了有關于圖像的所有信息。IFD提供了一系列的指針(索引),這些指針告訴我們各種有關的數據字段在文件中的開始位置,并給出每個字段的數據類型及長度。這種方法允許數據字段定位在文件的任何地方,且可以是任意長度,因此文件格式十分靈活。

???? IFD是TIF圖中最重要的數據結構,它包含了一個TIF文件中最重要的信息,一個TIF圖可能有多個IFD,這說明文件中有多個圖像,每個IFD標 識1個圖像的基本屬性。 IFD結構中包含了三類成員,Directory Entry Count指出該結構里面有多少個目錄入口;接下來就是N個線性排列的DE序列,數量不定(這就是 為什么稱TIF格式文件為可擴充標記的文件,甚至用戶可以添加自定義的標記屬性),每個DE標識了圖像的某一個屬性;最后就是一個偏移量, 標識下一個文件目錄相對于文件開始處的位置,當然,如果該TIF文件只包含了一幅圖像,那么就只有一個IFD,顯然,這個偏移量就等于0;


共12個字節,見圖二。簡單說,一個DE就是一幅圖像的某一個屬性。例如圖像的大小、分辨率、是否壓縮、像素的行列數、一個像素由幾位 表示(1位代表黑白兩色,8位代表256色等等)等。其中:tag成員是該屬性的編號,在圖像文件目錄中,它是按照升序排列的。我們可以通過讀 這些編號,然后到TIF格式官方白皮書中查找相應的含義。屬性是用數據來表示的,那么type就是代表著該數據的類型,TIF官方指定的有5種數據類型。type=1就是BYTE類型(8位無標記整數)、type=2是ASCII類型(7位ASCII碼加1位二進制0)、type=3是SHORT類型 (16位無標記整數)、type=4是LONG 類型(32位無標記整數)、type=5是RATIONAL類型(2個LONG,第一個是分子,第二個是分母)。length成員是數據的數量而不是數據類型的長度。 第4個成員valueOffset很重要,它是tag標識的屬性代表的變量值相對文件開始處的偏移量。如果變量值占用的空間小于4個字節,那么該值就存放在 valueOffset中即可,沒必要再另外指向一個地方了。


????? 3.圖像數據

  根據IFD所指向的地址.存儲相關的圖像信息

以下是在6.0下運行的代碼

[cpp]?view plaincopy
  1. #ifndef?TIFREADER_H???
  2. #define?TIFREADER_H???
  3. ??
  4. #include?<stdio.h>??
  5. #include?<string.h>??
  6. ??
  7. #ifndef?NULL??
  8. #define?NULL???0??
  9. #endif??
  10. ??
  11. #ifndef?TRUE??
  12. #define?TRUE???1??
  13. #define?FALSE??0??
  14. #endif??
  15. ??
  16. ??
  17. typedef?struct????
  18. {??
  19. ??unsigned?short?Byte_order;//??
  20. ??unsigned?short?Version;//校驗文件是否是TIF文件??
  21. ??unsigned???int?OffsetToFirstFID;//相對對文件開始處的偏移量??
  22. ?//?unsigned?short?wDECount;//多少目錄入口??
  23. }IFH;??
  24. ??
  25. typedef?struct??
  26. {??
  27. ????unsigned?short?tag;//屬性的編號??
  28. ????unsigned?short?type;//數據類型??
  29. ????unsigned?long?length;//數據的數量??
  30. ????unsigned?long?valueOffset;//tag標識的屬性代表的變量值相對文件開始處的偏移量??
  31. }DE;??
  32. typedef?struct????
  33. {??
  34. ????int?width;??
  35. ????int?height;??
  36. ??????
  37. }Size;??
  38. typedef?struct???
  39. ?{??
  40. ????int?*data;??
  41. }DATA;??
  42. typedef?struct???
  43. {??
  44. ????DE?*pde;??
  45. ????int?wDECount;??
  46. }PDE;??
  47. bool?readTIF(char*?path,IFH?&ifh,PDE?&de,Size?&size,DATA?&Data)??
  48. {??
  49. ????unsigned?char?*data;??
  50. ????int?*dat;??
  51. ????unsigned?short?wDECount;//多少目錄入口??
  52. ??????
  53. //??ZeroMemory(&ifh,?sizeof(IFH));??
  54. //??ZeroMemory(&de,?sizeof(DE));??
  55. ??
  56. ????FILE?*fp;??
  57. ????fp=fopen(path,"rb");??
  58. ????if(fp?==?NULL)??
  59. ????{??
  60. ????????cout<<"open?file?error"<<endl;??
  61. ????????return?false;??
  62. ????}??
  63. ????if(sizeof(IFH)?!=?fread(&ifh,?1,sizeof(IFH),fp))??
  64. ????{??
  65. ????????cout<<"讀TIF文件頭失敗";??
  66. ????????return?FALSE;??
  67. ????}??
  68. ?????if(0x2a?!=?ifh.Version)??
  69. ?????{??
  70. ??????????cout<<"該文件不是TIF格式,讀文件失敗";??
  71. ??????????return?FALSE;??
  72. ?????}??
  73. ??
  74. ?????if(0x4949?!=?ifh.Byte_order)??
  75. ?????{??
  76. ??????????cout<<"該TIF文件不是IBMPC字節序,讀文件失敗";??
  77. ??????????return?FALSE;??
  78. ?????}??
  79. ??
  80. ?????fseek(fp,ifh.OffsetToFirstFID,SEEK_SET);//將文件指針定位到IFD??
  81. ?????//讀文件有多少個目錄入口???
  82. ????if(2?!=?fread(&wDECount,1,sizeof(unsigned?short),fp))??
  83. ?????{??
  84. ??????????cout<<"無法獲得TIF文件目錄入口數量";??
  85. ??????????return?FALSE;??
  86. ?????}??
  87. ????cout<<"該TIF文件有"<<wDECount<<"個目錄入口"<<endl;??
  88. ????//創建DE數組,接收信息,數組中有wDECount個元素???
  89. ????de.pde?=?new?DE[wDECount];??
  90. ????DE*?pTemp?=?de.pde;??
  91. ????de.wDECount?=?wDECount;??
  92. ????memset(de.pde,?0,?sizeof(DE)*wDECount);??
  93. ?????if(sizeof(DE)*wDECount?!=?fread(de.pde,1,?sizeof(DE)*wDECount,fp))??
  94. ?????{??
  95. ??????????cout<<"讀圖象文件目錄失敗";??
  96. ??????????delete?[]de.pde;??
  97. ??????????return?false?;??
  98. ?????}??
  99. ????//把圖像的大小和圖像數據的容量保存到成員變量中??
  100. ?????int?m_size_x;??
  101. ?????int?m_size_y;??
  102. ?????int?m_size;??
  103. ?????int?i;??
  104. ????for(i=0;?i<wDECount;?i++)??
  105. ?????{??
  106. ??????????pTemp?=de.pde?+?i;??
  107. ??????????if(256?==?pTemp->tag)?//tag為256的目錄入口中的變量標識了圖象寬度??
  108. ??????????{??
  109. ??????????????m_size_x?=?pTemp->valueOffset;??
  110. ??????????}??
  111. ??????????if(257?==?pTemp->tag)?//圖象高度??
  112. ??????????{??
  113. ??????????????m_size_y?=?pTemp->valueOffset;??
  114. ??????????}??
  115. ??????????if(273?==?pTemp->tag)?//計算圖象數據占用字節數??
  116. ??????????{??
  117. ???????????//m_dwBmSize?=?pTemp->valueOffset?-?sizeof(IFH);??
  118. ???????????//或者把tag=256的valueOffset乘以tag=257的valueOffset??
  119. ??????????????m_size?=?m_size_x?*?m_size_y;??
  120. ??????????}??
  121. ????}??
  122. ????//填充所有像素數據,?顛倒圖象數據從最后一行開始讀起??
  123. ?????int?j?=?0;??
  124. ????//?int?i?=?0;??
  125. ?????data?=?(unsigned?char*)malloc(m_size*sizeof(BYTE));??
  126. ?????dat?=?(int*)malloc(m_size*sizeof(int));??
  127. ?????for(i=m_size_y-1;?i>=0;?i--)??
  128. ?????{??
  129. ?????????fseek(fp,sizeof(IFH)?+?i*m_size_x,?SEEK_SET);??
  130. ?????????fread((BYTE*)(data?+?1)?+?j*m_size_x,sizeof(BYTE),?m_size_x,fp);??
  131. ??????????j++;??
  132. ?????}??
  133. ?????cout<<"width:"<<m_size_x<<endl;??
  134. ?????cout<<"height:"<<m_size_y<<endl;??
  135. ?????unsigned?char*?p;??
  136. ?????p?=?data;??
  137. ?????int?*ptr;??
  138. ?????ptr?=?dat;??
  139. ?????for?(i=0;i<m_size;i++,p++,ptr++)??
  140. ?????{??
  141. ?????????*ptr?=?(int)(*p);??
  142. ?????????int??h=?*ptr;??
  143. ????????//?cout<<h<<"?";??
  144. ?????}??
  145. ?????size.width?=?m_size_x;??
  146. ?????size.height?=?m_size_y;??
  147. ?????Data.data?=?dat;??
  148. ?????return?TRUE;??
  149. ????
  150. }??
  151. bool?saveTIF(char*?path,IFH?ifh,PDE?de,Size?size,DATA?Data)??
  152. {??
  153. ????unsigned?char?*data;??
  154. //????unsigned?short?wDECount;//多少目錄入口??
  155. ??????
  156. //??ZeroMemory(&ifh,?sizeof(IFH));??
  157. //??ZeroMemory(&de,?sizeof(DE));??
  158. ??
  159. ????FILE?*fp;??
  160. ????fp=fopen(path,"wb");??
  161. ????if(fp?==?NULL)??
  162. ????{??
  163. ????????cout<<"open?file?error"<<endl;??
  164. ????????return?false;??
  165. ????}??
  166. ????if(sizeof(IFH)?!=?fwrite(&ifh,?1,sizeof(IFH),fp))??
  167. ????{??
  168. ????????cout<<"寫TIF文件頭失敗";??
  169. ????????return?FALSE;??
  170. ????}??
  171. ?????fseek(fp,ifh.OffsetToFirstFID,SEEK_SET);//將文件指針定位到IFD??
  172. ?????//讀文件有多少個目錄入口???
  173. ????if(2?!=?fwrite(&de.wDECount,1,sizeof(unsigned?short),fp))??
  174. ?????{??
  175. ??????????cout<<"無法獲得TIF文件目錄入口數量";??
  176. ??????????return?FALSE;??
  177. ?????}??
  178. ????//創建DE數組,接收信息,數組中有wDECount個元素???
  179. ???
  180. ?????if(sizeof(DE)*de.wDECount?!=?fwrite(de.pde,1,?sizeof(DE)*de.wDECount,fp))??
  181. ?????{??
  182. ??????????cout<<"讀圖象文件目錄失敗";??
  183. ??????????return?false?;??
  184. ?????}??
  185. ????//填充所有像素數據,?顛倒圖象數據從最后一行開始讀起??
  186. ?????int?j?=?0;??
  187. ?????int?i?=?0;??
  188. ?????data?=?(unsigned?char*)malloc(size.width*size.height*sizeof(BYTE));??
  189. ?????int?*ptr?=?Data.data;??
  190. ??
  191. ?????unsigned?char*?p;??
  192. ?????p?=?data;??
  193. ?????for?(i=0;i<size.width*size.height;i++,p++,ptr++)??
  194. ?????{??
  195. ?????????*p?=?(unsigned?char)(*ptr);??
  196. ????????//?int??h=?*ptr;??
  197. ????????//?cout<<h<<"?";??
  198. ?????}????
  199. ?????for(i=size.height-1;?i>=0;?i--)??
  200. ?????{??
  201. ?????????fseek(fp,sizeof(IFH)?+?i*size.width,?SEEK_SET);??
  202. ?????????fwrite((BYTE*)(data?+?1)?+?j*size.width,sizeof(BYTE),?size.width,fp);??
  203. ??????????j++;??
  204. ?????}??
  205. ??
  206. ?????return?TRUE;??
  207. ????
  208. }??
  209. #endif??


這個代碼這是對特定的TIF進行讀取,在保存時不知道為什么,不能再windows下正常顯示,期待大俠解決呀

轉載于:https://www.cnblogs.com/ainima/p/6331168.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259148.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259148.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259148.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

g menu i meun_長沙話讀“這里”,到底是閣(gó)里還是該(gái)里

“帶籠子”、“打抱秋”……這些地道的長沙話&#xff0c;長沙人&#xff0c;你有多久沒聽過了&#xff1f;/ 長沙人&#xff0c;你還記得長沙話嗎 / “去了很多地方&#xff0c;最后還是回到了長沙”“我聽見了一句長沙話&#xff0c;就想回長沙了。”逗霸妹聽過很多人回長沙的…

git使用---工作區和暫存區

轉載于:https://www.cnblogs.com/momo-unique/articles/4380551.html

UC/OS-II的學習

粗略的的看了邵貝貝老師的那本書&#xff0c;感覺有點眉目。UC/OS-II的全局變量繁多&#xff0c;剛接觸的時候容易弄混淆&#xff0c;現在總結下&#xff1a; OSRunning&#xff1a; 用于標識多任務環境是否已經開啟運行&#xff0c;在OSStart()函數里啟動任務后就置為True。 …

偶數哥德巴赫猜想

已知不小于6的偶數都可以分成兩個素數之和。請編寫6到100000的所有偶數的分解&#xff0c;若有一個偶數可以分解成多個素數之和&#xff0c;只需寫出一種即可。 #include <iostream> #include <algorithm> using namespace std;bool isprime(int n)//判斷素數{int …

[20170420]表達式加0或者減0不一樣.txt

[20170420]表達式加0或者減0不一樣.txt --//oracle 有時候避免某個索引采用字段0或者-0的方式&#xff0c;不使用索引&#xff0c;但是兩者存在一點點區別&#xff0c;通過例子說明。 1.環境&#xff1a; SCOTTbook> &r/ver1 PORT_STRING VERSION …

MAPLAP開發環境中release模式和debug模式燒寫.hex文件的不同之處

昨天看了齊工的報告才知道release模式和debug模式燒寫.hex文件的不同。 三&#xff1a;問題分析 1. PIC系列的仿真器和集成開發環境的情況&#xff1a; Release模式和Debug模式是有區別的&#xff1b;Release模式是只把代碼燒錄到單片機的flash區內&#xff0c;上電執行&am…

JavaWeb -- Session實例 -- 自動登錄 和 防止表單重復提交(令牌產生器) MD5碼

1、 自動登錄 http://blog.csdn.net/xj626852095/article/details/16825659 2. 防止表單重復提交 表單Servlet //負責產生表單 public class FormServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletEx…

電腦常見故障處理_彩超常見故障及維修

彩超是醫學檢測手段中重要的環節之一&#xff0c;是對產婦以及對病人進行內部組織和結構觀察的重要方式之一&#xff0c;彩超應用得當可以及早的診斷出病人的疾病&#xff0c;為患者解除疾病的困擾。彩超設備是一種極為先進的診斷系統&#xff0c;一般彩超系統包括以下幾個部分…

微軟歷史最高市值是多少?

有人說微軟在1999 年 12 月達到股價歷史最高點 $58.38并不準確。我1999年12月22日增加微軟&#xff0c;公司依照1999年12月27日的價格&#xff08;119.125&#xff0c;拆股后變為59.5625&#xff09;給了我一筆期權&#xff0c;這個價格&#xff0c;成為微軟股價空前絕后最高點…

京東2016校招編程題

記得有一個大題&#xff0c;說的是給定一個n*n的矩陣&#xff0c;要求從1開始填充矩陣&#xff0c;最后的矩陣是蛇形的。即如下&#xff1a; n3, 7 8 1 6 9 2 5 4 3 n4, 10 11 12 1 9 16 13 2 8 15 14 3 7 6 5 4 給出代碼&#xff1a; #incl…

leetcode21

/*** Definition for singly-linked list.* public class ListNode {* public int val;* public ListNode next;* public ListNode(int x) { val x; }* }*/ public class Solution {public ListNode MergeTwoLists(ListNode l1, ListNode l2) {//遞歸實現鏈表合并…

springmvc02

1&#xff0c;創建實體類對象User 注意要導入 bean-validator.jar 包 package com.yangw.springmvc.entity;import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.Range; im…

用基本信號畫出如下的信號_股市入門基本知識丨下跌時期可以抄底的安全信號有哪些...

點擊藍色字體 關注我們 帶來更多精彩股票市場中的秘籍其實就是“低買高賣”&#xff0c;不過我們不能在大盤一開始下跌的時候就進行買入&#xff0c;因為不清楚下跌的時間&#xff0c;太早介入&#xff0c;只有在反彈幅度超出我們介入的點的時候才可以進行高賣。那么什么時候才…

Flume數據傳輸事務分析[轉]

本文基于ThriftSource,MemoryChannel,HdfsSink三個組件&#xff0c;對Flume數據傳輸的事務進行分析&#xff0c;如果使用的是其他組件&#xff0c;Flume事務具體的處理方式將會不同。一般情況下&#xff0c;用MemoryChannel就好了&#xff0c;我們公司用的就是這個&#xff0c;…

最近的一些校招試題摘錄

最近又參加了一些校招&#xff0c;真是馬不停蹄啊。多參加考試是好的&#xff0c;可以不斷發現一些新的問題。下面摘錄一些我不太會的題。 1.volatile的作用是什么&#xff1f; 答案&#xff1a;volatile是類型修飾符&#xff0c;用它修飾的類型變量可能會被編譯器未知的因素…

yii2中的rules驗證規則

2019獨角獸企業重金招聘Python工程師標準>>> Rules驗證規則&#xff1a;required : 必須值驗證屬性||CRequiredValidator 的別名, 確保了特性不為空.[[字段名],required,requiredValue>必填值,message>提示信息];email : 郵箱驗證||CEmailValidator 的別名,確…

weblogic數據源配置的問題,weblogic密碼破解

weblogic 報錯 please increase XXX,得知是連接池出了問題&#xff0c;查看weblogic配置&#xff0c;發現沒有設置超時 查看oracle 當前session&#xff0c;可以看到連接的機器&#xff0c;用戶&#xff0c;當前執行的sqlid select * from v$session; select v$sql where sql_i…

自己寫的簡易多任務系統---基于pic18fxxx

這個工程只是實現了最簡單的OS任務調度&#xff0c;對于理解任務調度有點幫助。其實就是從UC/OS-II里面摘出來的&#xff0c;沒有原來的那么復雜&#xff0c;很精簡&#xff0c;但道理上是一樣的。工程中的CPU.C文件時直接拿Nathan Brown寫好的&#xff0c;因為關于PIC任務切換…

python語言整數類型-Python 的內置數值類型

Python 是一種敏捷的、動態類型化的、極富表現力的開源編程語言&#xff0c;可以被自由地安裝到多種平臺上。Python 代碼是被解釋的。如果您對編輯、構建和執行循環較為熟悉&#xff0c;則 Python 代碼對您來說更簡單。但是&#xff0c;請不要搞錯&#xff1a;Python 器可以是簡…

滴滴出行2016校招編程題

1. 給定一個m*n的數組&#xff08;m,n>2,數組值>0&#xff09;&#xff0c;要求選出和最大的子2*2數組。例如&#xff1a; 1 2 3 4 5 6 7 8 9 顯然和最大的2*2子數組是5 6;8 9.下面完成這個功能。 Input: &#xff08;m*n的數組&#xff09; 1 2 3 ; 4 5 6 ; 7 8 9 …