123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- /***************************************************************************
- * Copyright ?2007 TWAIN Working Group:
- * Adobe Systems Incorporated, AnyDoc Software Inc., Eastman Kodak Company,
- * Fujitsu Computer Products of America, JFL Peripheral Solutions Inc.,
- * Ricoh Corporation, and Xerox Corporation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the TWAIN Working Group nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY TWAIN Working Group ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL TWAIN Working Group BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ***************************************************************************/
- /**
- * @file CTiffWriter.cpp
- * Write an image to disk as a tiff file.
- * @author JFL Peripheral Solutions Inc.
- * @date October 2007
- */
- #include "CTiffWriter.h"
- #include <sstream>
- CTiffWriter::CTiffWriter(const string& _filename,
- const long int _width,
- const long int _height,
- const int _bitsPerPixel,
- const unsigned long int _bytesPerRow)
- {
- m_pImageStream = 0;
- m_nOffset = 0;
- m_filename = _filename;
- m_ImageWidth.TagID = kTIFF_TAG_IMGWIDTH;
- m_ImageWidth.DataType = kTIFF_TY_LONG;
- m_ImageWidth.DataCount = 1;
- m_ImageWidth.DataOffset = _width;
- m_ImageLength.TagID = kTIFF_TAG_IMGLENGTH;
- m_ImageLength.DataType = kTIFF_TY_LONG;
- m_ImageLength.DataCount = 1;
- m_ImageLength.DataOffset = _height;
- m_BitsPerSample.TagID = kTIFF_TAG_BITSPERSAMPLE;
- m_BitsPerSample.DataType = kTIFF_TY_SHORT;
- m_BitsPerSample.DataCount = 1;
- if(24 == _bitsPerPixel)
- {
- m_BitsPerSample.DataOffset = 8;
- }
- else
- {
- m_BitsPerSample.DataOffset = _bitsPerPixel;
- }
- m_Compression.TagID = kTIFF_TAG_COMPRESSION;
- m_Compression.DataType = kTIFF_TY_SHORT;
- m_Compression.DataCount = 1;
- m_Compression.DataOffset = 1;
- m_PhotometricInterp.TagID = kTIFF_TAG_PHOTOMETRICINT;
- m_PhotometricInterp.DataType = kTIFF_TY_SHORT;
- m_PhotometricInterp.DataCount = 1;
- if(24 == _bitsPerPixel)
- {
- m_PhotometricInterp.DataOffset = 2;
- }
- else
- {
- m_PhotometricInterp.DataOffset = 1;
- }
- // -there is only one strip that contains all the row data, and it starts right after the header.
- // -There are always 12 tags being written for each tiff.
- m_StripOffsets.TagID = kTIFF_TAG_STRIPOFFSETS;
- m_StripOffsets.DataType = kTIFF_TY_SHORT;
- m_StripOffsets.DataCount = 1;
- m_StripOffsets.DataOffset = getSizeofHeader();
- m_SamplesPerPixel.TagID = kTIFF_TAG_SAMPLESPERPIXEL;
- m_SamplesPerPixel.DataType = kTIFF_TY_SHORT;
- if(24 == _bitsPerPixel)
- {
- m_SamplesPerPixel.DataCount = 1;
- m_SamplesPerPixel.DataOffset = 3;
- }
- else
- {
- m_SamplesPerPixel.DataCount = 1;
- m_SamplesPerPixel.DataOffset = 1;
- }
- m_RowsPerStrip.TagID = kTIFF_TAG_ROWSPERSTRIP;
- m_RowsPerStrip.DataType = kTIFF_TY_LONG;
- m_RowsPerStrip.DataCount = 1;
- m_RowsPerStrip.DataOffset = _height;
- m_StripByteCounts.TagID = kTIFF_TAG_STRIPBYTECOUNTS;
- m_StripByteCounts.DataType = kTIFF_TY_LONG;
- m_StripByteCounts.DataCount = 1;
- m_StripByteCounts.DataOffset = _bytesPerRow * _height;
- m_XResolution.TagID = kTIFF_TAG_XRESOLUTION;
- m_XResolution.DataType = kTIFF_TY_RATIONAL;
- m_XResolution.DataCount = 1;
- m_XResolution.DataOffset = m_StripOffsets.DataOffset - sizeof(DWORD)*4; // fixed offset from the end of the header
- setXResolution(100, 1);
- m_YResolution.TagID = kTIFF_TAG_YRESOLUTION;
- m_YResolution.DataType = kTIFF_TY_RATIONAL;
- m_YResolution.DataCount = 1;
- m_YResolution.DataOffset = m_StripOffsets.DataOffset - sizeof(DWORD)*2; // fixed offset from the end of the header
- setYResolution(100, 1);
- m_ResolutionUnit.TagID = kTIFF_TAG_RESOLUTIONUNIT;
- m_ResolutionUnit.DataType = kTIFF_TY_SHORT;
- m_ResolutionUnit.DataCount = 1;
- m_ResolutionUnit.DataOffset = 2;
- }
- CTiffWriter::~CTiffWriter()
- {
- if(0 != m_pImageStream)
- {
- if(m_pImageStream->is_open())
- {
- m_pImageStream->close();
- }
- delete m_pImageStream;
- }
- }
- void CTiffWriter::setImageWidth(const long int _v)
- {
- m_ImageWidth.DataOffset = _v;
- }
- void CTiffWriter::setImageHeight(const long int _v)
- {
- m_ImageLength.DataOffset = _v;
- }
- void CTiffWriter::setBitsPerSample(const int _v)
- {
- m_BitsPerSample.DataOffset = _v;
- }
- void CTiffWriter::setCompression(const int _v)
- {
- m_Compression.DataOffset = _v;
- }
- void CTiffWriter::setPhotometricInterp(const int _v)
- {
- m_PhotometricInterp.DataOffset = _v;
- }
- void CTiffWriter::setSamplesPerPixel(const int _v)
- {
- m_SamplesPerPixel.DataOffset = _v;
- }
- void CTiffWriter::setXResolution(const int _numerator, const int _denominator)
- {
- m_xres[0] = _numerator;
- m_xres[1] = _denominator;
- }
- void CTiffWriter::setYResolution(const int _numerator, const int _denominator)
- {
- m_yres[0] = _numerator;
- m_yres[1] = _denominator;
- }
- void CTiffWriter::setBytesPerRow(const int _v)
- {
- m_StripByteCounts.DataOffset = _v * m_ImageLength.DataOffset;
- }
- void CTiffWriter::GetImageHeader(stringstream &Header)
- {
- // write the header
- TIFFIFH hdr = {0x4949, 0x002a, sizeof(TIFFIFH)};
- Header.write(reinterpret_cast<char*>(&hdr), sizeof(TIFFIFH));
- // write the Tags immediately after the header
- WORD numTags = 12;
- Header.write(reinterpret_cast<char*>(&numTags), sizeof(numTags));
- const int nsize = sizeof(TIFFTag);
- Header.write(reinterpret_cast<char*>(&m_ImageWidth), nsize);
- Header.write(reinterpret_cast<char*>(&m_ImageLength), nsize);
- Header.write(reinterpret_cast<char*>(&m_BitsPerSample), nsize);
- Header.write(reinterpret_cast<char*>(&m_Compression), nsize);
- Header.write(reinterpret_cast<char*>(&m_PhotometricInterp), nsize);
- Header.write(reinterpret_cast<char*>(&m_StripOffsets), nsize);
- Header.write(reinterpret_cast<char*>(&m_SamplesPerPixel), nsize);
- Header.write(reinterpret_cast<char*>(&m_RowsPerStrip), nsize);
- Header.write(reinterpret_cast<char*>(&m_StripByteCounts), nsize);
- Header.write(reinterpret_cast<char*>(&m_XResolution), nsize);
- Header.write(reinterpret_cast<char*>(&m_YResolution), nsize);
- Header.write(reinterpret_cast<char*>(&m_ResolutionUnit), nsize);
- // end the header by setting the next image offset to null
- DWORD end = 0;
- Header.write(reinterpret_cast<char*>(&end), sizeof(end));
- // write the X and Y resolutions
- Header.write(reinterpret_cast<char*>(&m_xres), sizeof(DWORD)*2);
- Header.write(reinterpret_cast<char*>(&m_yres), sizeof(DWORD)*2);
- }
- bool CTiffWriter::writeImageHeader()
- {
- // create the out stream if not done so already
- if(0 == m_pImageStream)
- {
- m_pImageStream = new ofstream();
- }
- // open the stream. If already open, reset it
- if(m_pImageStream->is_open())
- {
- m_pImageStream->seekp(0);
- }
- else
- {
- m_pImageStream->open(m_filename.c_str(), ios_base::out|ios_base::binary|ios_base::trunc);
- }
- stringstream Header;
- GetImageHeader(Header);
- Header.seekp(0, ios_base::end);
- m_nOffset =(int) Header.tellp();
- Header.seekg(0, ios_base::beg);
- char *pData = new char[m_nOffset];
- Header.read(pData,m_nOffset);
- m_pImageStream->write(pData,m_nOffset);
- delete []pData;
- return true;
- }
- bool CTiffWriter::WriteTIFFData(char *_pData, DWORD _nCount)
- {
- bool bret = false;
- if(0 != m_pImageStream &&
- m_pImageStream->good())
- {
- m_pImageStream->seekp(m_nOffset);
- m_pImageStream->write(_pData, _nCount);
- m_nOffset += _nCount;
- bret = true;
- }
- return bret;
- }
- unsigned int CTiffWriter::getSizeofHeader()
- {
- // Header is as follows:
- // TIFFIFH + Num. of Tags + each tag + Xres Data (2 dwords) + Yres Data (2 dwords) + Next Image offset (1 dword)
- return sizeof(TIFFIFH)+sizeof(WORD)+sizeof(TIFFTag)*12+sizeof(DWORD)*5;
- }
|