@@ -75,6 +75,8 @@ TiffDecoder::TiffDecoder()
75
75
TIFFSetWarningHandler ( GrFmtSilentTIFFErrorHandler );
76
76
}
77
77
m_hdr = false ;
78
+ m_buf_supported = true ;
79
+ m_buf_pos = 0 ;
78
80
}
79
81
80
82
@@ -115,6 +117,76 @@ ImageDecoder TiffDecoder::newDecoder() const
115
117
return makePtr<TiffDecoder>();
116
118
}
117
119
120
+ class TiffDecoderBufHelper
121
+ {
122
+ public:
123
+ static tmsize_t read ( thandle_t handle, void * buffer, tmsize_t n )
124
+ {
125
+ TiffDecoder *decoder = reinterpret_cast <TiffDecoder*>(handle);
126
+ const Mat& buf = decoder->m_buf ;
127
+ const tmsize_t size = buf.cols *buf.rows *buf.elemSize ();
128
+ tmsize_t pos = decoder->m_buf_pos ;
129
+ if ( n > (size - pos) )
130
+ {
131
+ n = size - pos;
132
+ }
133
+ memcpy (buffer, buf.ptr () + pos, n);
134
+ decoder->m_buf_pos += n;
135
+ return n;
136
+ }
137
+
138
+ static tmsize_t write ( thandle_t /* handle*/ , void * /* buffer*/ , tmsize_t /* n*/ )
139
+ {
140
+ // Not used for decoding.
141
+ return 0 ;
142
+ }
143
+
144
+ static toff_t seek ( thandle_t handle, toff_t offset, int whence )
145
+ {
146
+ TiffDecoder *decoder = reinterpret_cast <TiffDecoder*>(handle);
147
+ const Mat& buf = decoder->m_buf ;
148
+ const toff_t size = buf.cols *buf.rows *buf.elemSize ();
149
+ toff_t new_pos = decoder->m_buf_pos ;
150
+ switch (whence)
151
+ {
152
+ case SEEK_SET:
153
+ new_pos = offset;
154
+ break ;
155
+ case SEEK_CUR:
156
+ new_pos += offset;
157
+ break ;
158
+ case SEEK_END:
159
+ new_pos = size + offset;
160
+ break ;
161
+ }
162
+ new_pos = std::min (new_pos, size);
163
+ decoder->m_buf_pos = (size_t )new_pos;
164
+ return new_pos;
165
+ }
166
+
167
+ static int map ( thandle_t handle, void ** base, toff_t * size )
168
+ {
169
+ TiffDecoder *decoder = reinterpret_cast <TiffDecoder*>(handle);
170
+ Mat& buf = decoder->m_buf ;
171
+ *base = buf.ptr ();
172
+ *size = buf.cols *buf.rows *buf.elemSize ();
173
+ return 0 ;
174
+ }
175
+
176
+ static toff_t size ( thandle_t handle )
177
+ {
178
+ TiffDecoder *decoder = reinterpret_cast <TiffDecoder*>(handle);
179
+ const Mat& buf = decoder->m_buf ;
180
+ return buf.cols *buf.rows *buf.elemSize ();
181
+ }
182
+
183
+ static int close ( thandle_t /* handle*/ )
184
+ {
185
+ // Do nothing.
186
+ return 0 ;
187
+ }
188
+ };
189
+
118
190
bool TiffDecoder::readHeader ()
119
191
{
120
192
bool result = false ;
@@ -124,7 +196,18 @@ bool TiffDecoder::readHeader()
124
196
{
125
197
// TIFFOpen() mode flags are different to fopen(). A 'b' in mode "rb" has no effect when reading.
126
198
// http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
127
- tif = TIFFOpen (m_filename.c_str (), " r" );
199
+ if ( !m_buf.empty () )
200
+ {
201
+ m_buf_pos = 0 ;
202
+ tif = TIFFClientOpen ( " " , " r" , reinterpret_cast <thandle_t >(this ), &TiffDecoderBufHelper::read,
203
+ &TiffDecoderBufHelper::write, &TiffDecoderBufHelper::seek,
204
+ &TiffDecoderBufHelper::close, &TiffDecoderBufHelper::size,
205
+ &TiffDecoderBufHelper::map, /* unmap=*/ 0 );
206
+ }
207
+ else
208
+ {
209
+ tif = TIFFOpen (m_filename.c_str (), " r" );
210
+ }
128
211
}
129
212
130
213
if ( tif )
@@ -472,11 +555,7 @@ bool TiffDecoder::readHdrData(Mat& img)
472
555
TiffEncoder::TiffEncoder ()
473
556
{
474
557
m_description = " TIFF Files (*.tiff;*.tif)" ;
475
- #ifdef HAVE_TIFF
476
- m_buf_supported = false ;
477
- #else
478
558
m_buf_supported = true ;
479
- #endif
480
559
}
481
560
482
561
TiffEncoder::~TiffEncoder ()
@@ -509,6 +588,81 @@ void TiffEncoder::writeTag( WLByteStream& strm, TiffTag tag,
509
588
510
589
#ifdef HAVE_TIFF
511
590
591
+ class TiffEncoderBufHelper
592
+ {
593
+ public:
594
+
595
+ TiffEncoderBufHelper (std::vector<uchar> *buf)
596
+ : m_buf(buf), m_buf_pos(0 )
597
+ {}
598
+
599
+ TIFF* open ()
600
+ {
601
+ return TIFFClientOpen ( " " , " w" , reinterpret_cast <thandle_t >(this ), &TiffEncoderBufHelper::read,
602
+ &TiffEncoderBufHelper::write, &TiffEncoderBufHelper::seek,
603
+ &TiffEncoderBufHelper::close, &TiffEncoderBufHelper::size,
604
+ /* map=*/ 0 , /* unmap=*/ 0 );
605
+ }
606
+
607
+ static tmsize_t read ( thandle_t /* handle*/ , void * /* buffer*/ , tmsize_t /* n*/ )
608
+ {
609
+ // Not used for encoding.
610
+ return 0 ;
611
+ }
612
+
613
+ static tmsize_t write ( thandle_t handle, void * buffer, tmsize_t n )
614
+ {
615
+ TiffEncoderBufHelper *helper = reinterpret_cast <TiffEncoderBufHelper*>(handle);
616
+ size_t begin = (size_t )helper->m_buf_pos ;
617
+ size_t end = begin + n;
618
+ if ( helper->m_buf ->size () < end )
619
+ {
620
+ helper->m_buf ->resize (end);
621
+ }
622
+ memcpy (&(*helper->m_buf )[begin], buffer, n);
623
+ helper->m_buf_pos = end;
624
+ return n;
625
+ }
626
+
627
+ static toff_t seek ( thandle_t handle, toff_t offset, int whence )
628
+ {
629
+ TiffEncoderBufHelper *helper = reinterpret_cast <TiffEncoderBufHelper*>(handle);
630
+ const toff_t size = helper->m_buf ->size ();
631
+ toff_t new_pos = helper->m_buf_pos ;
632
+ switch (whence)
633
+ {
634
+ case SEEK_SET:
635
+ new_pos = offset;
636
+ break ;
637
+ case SEEK_CUR:
638
+ new_pos += offset;
639
+ break ;
640
+ case SEEK_END:
641
+ new_pos = size + offset;
642
+ break ;
643
+ }
644
+ helper->m_buf_pos = new_pos;
645
+ return new_pos;
646
+ }
647
+
648
+ static toff_t size ( thandle_t handle )
649
+ {
650
+ TiffEncoderBufHelper *helper = reinterpret_cast <TiffEncoderBufHelper*>(handle);
651
+ return helper->m_buf ->size ();
652
+ }
653
+
654
+ static int close ( thandle_t /* handle*/ )
655
+ {
656
+ // Do nothing.
657
+ return 0 ;
658
+ }
659
+
660
+ private:
661
+
662
+ std::vector<uchar>* m_buf;
663
+ toff_t m_buf_pos;
664
+ };
665
+
512
666
static void readParam (const std::vector<int >& params, int key, int & value)
513
667
{
514
668
for (size_t i = 0 ; i + 1 < params.size (); i += 2 )
@@ -559,7 +713,17 @@ bool TiffEncoder::writeLibTiff( const Mat& img, const std::vector<int>& params)
559
713
560
714
// do NOT put "wb" as the mode, because the b means "big endian" mode, not "binary" mode.
561
715
// http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
562
- TIFF* pTiffHandle = TIFFOpen (m_filename.c_str (), " w" );
716
+ TIFF* pTiffHandle;
717
+
718
+ TiffEncoderBufHelper buf_helper (m_buf);
719
+ if ( m_buf )
720
+ {
721
+ pTiffHandle = buf_helper.open ();
722
+ }
723
+ else
724
+ {
725
+ pTiffHandle = TIFFOpen (m_filename.c_str (), " w" );
726
+ }
563
727
if (!pTiffHandle)
564
728
{
565
729
return false ;
@@ -655,7 +819,19 @@ bool TiffEncoder::writeHdr(const Mat& _img)
655
819
{
656
820
Mat img;
657
821
cvtColor (_img, img, COLOR_BGR2XYZ);
658
- TIFF* tif = TIFFOpen (m_filename.c_str (), " w" );
822
+
823
+ TIFF* tif;
824
+
825
+ TiffEncoderBufHelper buf_helper (m_buf);
826
+ if ( m_buf )
827
+ {
828
+ tif = buf_helper.open ();
829
+ }
830
+ else
831
+ {
832
+ tif = TIFFOpen (m_filename.c_str (), " w" );
833
+ }
834
+
659
835
if (!tif)
660
836
{
661
837
return false ;
@@ -686,8 +862,6 @@ bool TiffEncoder::write( const Mat& img, const std::vector<int>& params)
686
862
bool TiffEncoder::write ( const Mat& img, const std::vector<int >& /* params*/ )
687
863
#endif
688
864
{
689
- int channels = img.channels ();
690
- int width = img.cols , height = img.rows ;
691
865
int depth = img.depth ();
692
866
#ifdef HAVE_TIFF
693
867
if (img.type () == CV_32FC3)
@@ -699,6 +873,11 @@ bool TiffEncoder::write( const Mat& img, const std::vector<int>& /*params*/)
699
873
if (depth != CV_8U && depth != CV_16U)
700
874
return false ;
701
875
876
+ #ifdef HAVE_TIFF
877
+ return writeLibTiff (img, params);
878
+ #else
879
+ int channels = img.channels ();
880
+ int width = img.cols , height = img.rows ;
702
881
int bytesPerChannel = depth == CV_8U ? 1 : 2 ;
703
882
int fileStep = width * channels * bytesPerChannel;
704
883
@@ -711,12 +890,8 @@ bool TiffEncoder::write( const Mat& img, const std::vector<int>& /*params*/)
711
890
}
712
891
else
713
892
{
714
- #ifdef HAVE_TIFF
715
- return writeLibTiff (img, params);
716
- #else
717
893
if ( !strm.open (m_filename) )
718
894
return false ;
719
- #endif
720
895
}
721
896
722
897
int rowsPerStrip = (1 << 13 )/fileStep;
@@ -876,6 +1051,7 @@ bool TiffEncoder::write( const Mat& img, const std::vector<int>& /*params*/)
876
1051
}
877
1052
878
1053
return true ;
1054
+ #endif
879
1055
}
880
1056
881
1057
}
0 commit comments