CTiffWriter.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /***************************************************************************
  2. * Copyright ?2007 TWAIN Working Group:
  3. * Adobe Systems Incorporated, AnyDoc Software Inc., Eastman Kodak Company,
  4. * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc.,
  5. * Ricoh Corporation, and Xerox Corporation.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions are met:
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * * Neither the name of the TWAIN Working Group nor the
  16. * names of its contributors may be used to endorse or promote products
  17. * derived from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY TWAIN Working Group ``AS IS'' AND ANY
  20. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL TWAIN Working Group BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. ***************************************************************************/
  31. /**
  32. * @file CTiffWriter.cpp
  33. * Write an image to disk as a tiff file.
  34. * @author JFL Peripheral Solutions Inc.
  35. * @date October 2007
  36. */
  37. #include "CTiffWriter.h"
  38. #include <sstream>
  39. CTiffWriter::CTiffWriter(const string& _filename,
  40. const long int _width,
  41. const long int _height,
  42. const int _bitsPerPixel,
  43. const unsigned long int _bytesPerRow)
  44. {
  45. m_pImageStream = 0;
  46. m_nOffset = 0;
  47. m_filename = _filename;
  48. m_ImageWidth.TagID = kTIFF_TAG_IMGWIDTH;
  49. m_ImageWidth.DataType = kTIFF_TY_LONG;
  50. m_ImageWidth.DataCount = 1;
  51. m_ImageWidth.DataOffset = _width;
  52. m_ImageLength.TagID = kTIFF_TAG_IMGLENGTH;
  53. m_ImageLength.DataType = kTIFF_TY_LONG;
  54. m_ImageLength.DataCount = 1;
  55. m_ImageLength.DataOffset = _height;
  56. m_BitsPerSample.TagID = kTIFF_TAG_BITSPERSAMPLE;
  57. m_BitsPerSample.DataType = kTIFF_TY_SHORT;
  58. m_BitsPerSample.DataCount = 1;
  59. if(24 == _bitsPerPixel)
  60. {
  61. m_BitsPerSample.DataOffset = 8;
  62. }
  63. else
  64. {
  65. m_BitsPerSample.DataOffset = _bitsPerPixel;
  66. }
  67. m_Compression.TagID = kTIFF_TAG_COMPRESSION;
  68. m_Compression.DataType = kTIFF_TY_SHORT;
  69. m_Compression.DataCount = 1;
  70. m_Compression.DataOffset = 1;
  71. m_PhotometricInterp.TagID = kTIFF_TAG_PHOTOMETRICINT;
  72. m_PhotometricInterp.DataType = kTIFF_TY_SHORT;
  73. m_PhotometricInterp.DataCount = 1;
  74. if(24 == _bitsPerPixel)
  75. {
  76. m_PhotometricInterp.DataOffset = 2;
  77. }
  78. else
  79. {
  80. m_PhotometricInterp.DataOffset = 1;
  81. }
  82. // -there is only one strip that contains all the row data, and it starts right after the header.
  83. // -There are always 12 tags being written for each tiff.
  84. m_StripOffsets.TagID = kTIFF_TAG_STRIPOFFSETS;
  85. m_StripOffsets.DataType = kTIFF_TY_SHORT;
  86. m_StripOffsets.DataCount = 1;
  87. m_StripOffsets.DataOffset = getSizeofHeader();
  88. m_SamplesPerPixel.TagID = kTIFF_TAG_SAMPLESPERPIXEL;
  89. m_SamplesPerPixel.DataType = kTIFF_TY_SHORT;
  90. if(24 == _bitsPerPixel)
  91. {
  92. m_SamplesPerPixel.DataCount = 1;
  93. m_SamplesPerPixel.DataOffset = 3;
  94. }
  95. else
  96. {
  97. m_SamplesPerPixel.DataCount = 1;
  98. m_SamplesPerPixel.DataOffset = 1;
  99. }
  100. m_RowsPerStrip.TagID = kTIFF_TAG_ROWSPERSTRIP;
  101. m_RowsPerStrip.DataType = kTIFF_TY_LONG;
  102. m_RowsPerStrip.DataCount = 1;
  103. m_RowsPerStrip.DataOffset = _height;
  104. m_StripByteCounts.TagID = kTIFF_TAG_STRIPBYTECOUNTS;
  105. m_StripByteCounts.DataType = kTIFF_TY_LONG;
  106. m_StripByteCounts.DataCount = 1;
  107. m_StripByteCounts.DataOffset = _bytesPerRow * _height;
  108. m_XResolution.TagID = kTIFF_TAG_XRESOLUTION;
  109. m_XResolution.DataType = kTIFF_TY_RATIONAL;
  110. m_XResolution.DataCount = 1;
  111. m_XResolution.DataOffset = m_StripOffsets.DataOffset - sizeof(DWORD)*4; // fixed offset from the end of the header
  112. setXResolution(100, 1);
  113. m_YResolution.TagID = kTIFF_TAG_YRESOLUTION;
  114. m_YResolution.DataType = kTIFF_TY_RATIONAL;
  115. m_YResolution.DataCount = 1;
  116. m_YResolution.DataOffset = m_StripOffsets.DataOffset - sizeof(DWORD)*2; // fixed offset from the end of the header
  117. setYResolution(100, 1);
  118. m_ResolutionUnit.TagID = kTIFF_TAG_RESOLUTIONUNIT;
  119. m_ResolutionUnit.DataType = kTIFF_TY_SHORT;
  120. m_ResolutionUnit.DataCount = 1;
  121. m_ResolutionUnit.DataOffset = 2;
  122. }
  123. CTiffWriter::~CTiffWriter()
  124. {
  125. if(0 != m_pImageStream)
  126. {
  127. if(m_pImageStream->is_open())
  128. {
  129. m_pImageStream->close();
  130. }
  131. delete m_pImageStream;
  132. }
  133. }
  134. void CTiffWriter::setImageWidth(const long int _v)
  135. {
  136. m_ImageWidth.DataOffset = _v;
  137. }
  138. void CTiffWriter::setImageHeight(const long int _v)
  139. {
  140. m_ImageLength.DataOffset = _v;
  141. }
  142. void CTiffWriter::setBitsPerSample(const int _v)
  143. {
  144. m_BitsPerSample.DataOffset = _v;
  145. }
  146. void CTiffWriter::setCompression(const int _v)
  147. {
  148. m_Compression.DataOffset = _v;
  149. }
  150. void CTiffWriter::setPhotometricInterp(const int _v)
  151. {
  152. m_PhotometricInterp.DataOffset = _v;
  153. }
  154. void CTiffWriter::setSamplesPerPixel(const int _v)
  155. {
  156. m_SamplesPerPixel.DataOffset = _v;
  157. }
  158. void CTiffWriter::setXResolution(const int _numerator, const int _denominator)
  159. {
  160. m_xres[0] = _numerator;
  161. m_xres[1] = _denominator;
  162. }
  163. void CTiffWriter::setYResolution(const int _numerator, const int _denominator)
  164. {
  165. m_yres[0] = _numerator;
  166. m_yres[1] = _denominator;
  167. }
  168. void CTiffWriter::setBytesPerRow(const int _v)
  169. {
  170. m_StripByteCounts.DataOffset = _v * m_ImageLength.DataOffset;
  171. }
  172. void CTiffWriter::GetImageHeader(stringstream &Header)
  173. {
  174. // write the header
  175. TIFFIFH hdr = {0x4949, 0x002a, sizeof(TIFFIFH)};
  176. Header.write(reinterpret_cast<char*>(&hdr), sizeof(TIFFIFH));
  177. // write the Tags immediately after the header
  178. WORD numTags = 12;
  179. Header.write(reinterpret_cast<char*>(&numTags), sizeof(numTags));
  180. const int nsize = sizeof(TIFFTag);
  181. Header.write(reinterpret_cast<char*>(&m_ImageWidth), nsize);
  182. Header.write(reinterpret_cast<char*>(&m_ImageLength), nsize);
  183. Header.write(reinterpret_cast<char*>(&m_BitsPerSample), nsize);
  184. Header.write(reinterpret_cast<char*>(&m_Compression), nsize);
  185. Header.write(reinterpret_cast<char*>(&m_PhotometricInterp), nsize);
  186. Header.write(reinterpret_cast<char*>(&m_StripOffsets), nsize);
  187. Header.write(reinterpret_cast<char*>(&m_SamplesPerPixel), nsize);
  188. Header.write(reinterpret_cast<char*>(&m_RowsPerStrip), nsize);
  189. Header.write(reinterpret_cast<char*>(&m_StripByteCounts), nsize);
  190. Header.write(reinterpret_cast<char*>(&m_XResolution), nsize);
  191. Header.write(reinterpret_cast<char*>(&m_YResolution), nsize);
  192. Header.write(reinterpret_cast<char*>(&m_ResolutionUnit), nsize);
  193. // end the header by setting the next image offset to null
  194. DWORD end = 0;
  195. Header.write(reinterpret_cast<char*>(&end), sizeof(end));
  196. // write the X and Y resolutions
  197. Header.write(reinterpret_cast<char*>(&m_xres), sizeof(DWORD)*2);
  198. Header.write(reinterpret_cast<char*>(&m_yres), sizeof(DWORD)*2);
  199. }
  200. bool CTiffWriter::writeImageHeader()
  201. {
  202. // create the out stream if not done so already
  203. if(0 == m_pImageStream)
  204. {
  205. m_pImageStream = new ofstream();
  206. }
  207. // open the stream. If already open, reset it
  208. if(m_pImageStream->is_open())
  209. {
  210. m_pImageStream->seekp(0);
  211. }
  212. else
  213. {
  214. m_pImageStream->open(m_filename.c_str(), ios_base::out|ios_base::binary|ios_base::trunc);
  215. }
  216. stringstream Header;
  217. GetImageHeader(Header);
  218. Header.seekp(0, ios_base::end);
  219. m_nOffset =(int) Header.tellp();
  220. Header.seekg(0, ios_base::beg);
  221. char *pData = new char[m_nOffset];
  222. Header.read(pData,m_nOffset);
  223. m_pImageStream->write(pData,m_nOffset);
  224. delete []pData;
  225. return true;
  226. }
  227. bool CTiffWriter::WriteTIFFData(char *_pData, DWORD _nCount)
  228. {
  229. bool bret = false;
  230. if(0 != m_pImageStream &&
  231. m_pImageStream->good())
  232. {
  233. m_pImageStream->seekp(m_nOffset);
  234. m_pImageStream->write(_pData, _nCount);
  235. m_nOffset += _nCount;
  236. bret = true;
  237. }
  238. return bret;
  239. }
  240. unsigned int CTiffWriter::getSizeofHeader()
  241. {
  242. // Header is as follows:
  243. // TIFFIFH + Num. of Tags + each tag + Xres Data (2 dwords) + Yres Data (2 dwords) + Next Image offset (1 dword)
  244. return sizeof(TIFFIFH)+sizeof(WORD)+sizeof(TIFFTag)*12+sizeof(DWORD)*5;
  245. }