@@ -539,7 +539,6 @@ bool TiffDecoder::readData( Mat& img )
539
539
540
540
bool TiffDecoder::readData_32FC3 (Mat& img)
541
541
{
542
-
543
542
int rows_per_strip = 0 , photometric = 0 ;
544
543
if (!m_tif)
545
544
{
@@ -724,44 +723,8 @@ static void readParam(const std::vector<int>& params, int key, int& value)
724
723
}
725
724
}
726
725
727
- bool TiffEncoder::writeLibTiff ( const Mat& img , const std::vector<int >& params)
726
+ bool TiffEncoder::writeLibTiff ( const std::vector< Mat>& img_vec , const std::vector<int >& params)
728
727
{
729
- int channels = img.channels ();
730
- int width = img.cols , height = img.rows ;
731
- int depth = img.depth ();
732
-
733
- int bitsPerChannel = -1 ;
734
- switch (depth)
735
- {
736
- case CV_8U:
737
- {
738
- bitsPerChannel = 8 ;
739
- break ;
740
- }
741
- case CV_16U:
742
- {
743
- bitsPerChannel = 16 ;
744
- break ;
745
- }
746
- default :
747
- {
748
- return false ;
749
- }
750
- }
751
-
752
- const int bitsPerByte = 8 ;
753
- size_t fileStep = (width * channels * bitsPerChannel) / bitsPerByte;
754
-
755
- int rowsPerStrip = (int )((1 << 13 )/fileStep);
756
- readParam (params, TIFFTAG_ROWSPERSTRIP, rowsPerStrip);
757
-
758
- if ( rowsPerStrip < 1 )
759
- rowsPerStrip = 1 ;
760
-
761
- if ( rowsPerStrip > height )
762
- rowsPerStrip = height;
763
-
764
-
765
728
// do NOT put "wb" as the mode, because the b means "big endian" mode, not "binary" mode.
766
729
// http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
767
730
TIFF* pTiffHandle;
@@ -780,86 +743,133 @@ bool TiffEncoder::writeLibTiff( const Mat& img, const std::vector<int>& params)
780
743
return false ;
781
744
}
782
745
746
+ // Settings that matter to all images
783
747
// defaults for now, maybe base them on params in the future
784
- int compression = COMPRESSION_LZW;
785
- int predictor = PREDICTOR_HORIZONTAL;
748
+ int compression = COMPRESSION_LZW;
749
+ int predictor = PREDICTOR_HORIZONTAL;
786
750
787
751
readParam (params, TIFFTAG_COMPRESSION, compression);
788
752
readParam (params, TIFFTAG_PREDICTOR, predictor);
789
753
790
- int colorspace = channels > 1 ? PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK;
791
-
792
- if ( !TIFFSetField (pTiffHandle, TIFFTAG_IMAGEWIDTH, width)
793
- || !TIFFSetField (pTiffHandle, TIFFTAG_IMAGELENGTH, height)
794
- || !TIFFSetField (pTiffHandle, TIFFTAG_BITSPERSAMPLE, bitsPerChannel)
795
- || !TIFFSetField (pTiffHandle, TIFFTAG_COMPRESSION, compression)
796
- || !TIFFSetField (pTiffHandle, TIFFTAG_PHOTOMETRIC, colorspace)
797
- || !TIFFSetField (pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, channels)
798
- || !TIFFSetField (pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)
799
- || !TIFFSetField (pTiffHandle, TIFFTAG_ROWSPERSTRIP, rowsPerStrip)
800
- )
801
- {
802
- TIFFClose (pTiffHandle);
803
- return false ;
804
- }
805
-
806
- if (compression != COMPRESSION_NONE && !TIFFSetField (pTiffHandle, TIFFTAG_PREDICTOR, predictor) )
754
+ // Iterate through each image in the vector and write them out as Tiff directories
755
+ for (size_t page = 0 ; page < img_vec.size (); page++)
807
756
{
808
- TIFFClose (pTiffHandle);
809
- return false ;
810
- }
811
-
812
- // row buffer, because TIFFWriteScanline modifies the original data!
813
- size_t scanlineSize = TIFFScanlineSize (pTiffHandle);
814
- AutoBuffer<uchar> _buffer (scanlineSize+32 );
815
- uchar* buffer = _buffer;
816
- if (!buffer)
817
- {
818
- TIFFClose (pTiffHandle);
819
- return false ;
820
- }
757
+ const Mat& img = img_vec[page];
758
+ int channels = img.channels ();
759
+ int width = img.cols , height = img.rows ;
760
+ int depth = img.depth ();
821
761
822
- for (int y = 0 ; y < height; ++y)
823
- {
824
- switch (channels)
762
+ int bitsPerChannel = -1 ;
763
+ switch (depth)
825
764
{
826
- case 1 :
827
- {
828
- memcpy (buffer, img.ptr (y), scanlineSize);
829
- break ;
830
- }
831
-
832
- case 3 :
765
+ case CV_8U:
833
766
{
834
- if (depth == CV_8U)
835
- icvCvt_BGR2RGB_8u_C3R ( img.ptr (y), 0 , buffer, 0 , cvSize (width,1 ) );
836
- else
837
- icvCvt_BGR2RGB_16u_C3R ( img.ptr <ushort>(y), 0 , (ushort*)buffer, 0 , cvSize (width,1 ) );
767
+ bitsPerChannel = 8 ;
838
768
break ;
839
769
}
840
-
841
- case 4 :
770
+ case CV_16U:
842
771
{
843
- if (depth == CV_8U)
844
- icvCvt_BGRA2RGBA_8u_C4R ( img.ptr (y), 0 , buffer, 0 , cvSize (width,1 ) );
845
- else
846
- icvCvt_BGRA2RGBA_16u_C4R ( img.ptr <ushort>(y), 0 , (ushort*)buffer, 0 , cvSize (width,1 ) );
772
+ bitsPerChannel = 16 ;
847
773
break ;
848
774
}
849
-
850
775
default :
851
776
{
852
- TIFFClose (pTiffHandle);
853
777
return false ;
854
778
}
855
779
}
856
780
857
- int writeResult = TIFFWriteScanline (pTiffHandle, buffer, y, 0 );
858
- if (writeResult != 1 )
781
+ const int bitsPerByte = 8 ;
782
+ size_t fileStep = (width * channels * bitsPerChannel) / bitsPerByte;
783
+
784
+ int rowsPerStrip = (int )((1 << 13 ) / fileStep);
785
+ readParam (params, TIFFTAG_ROWSPERSTRIP, rowsPerStrip);
786
+
787
+ if (rowsPerStrip < 1 )
788
+ rowsPerStrip = 1 ;
789
+
790
+ if (rowsPerStrip > height)
791
+ rowsPerStrip = height;
792
+
793
+ int colorspace = channels > 1 ? PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK;
794
+
795
+ if (!TIFFSetField (pTiffHandle, TIFFTAG_IMAGEWIDTH, width)
796
+ || !TIFFSetField (pTiffHandle, TIFFTAG_IMAGELENGTH, height)
797
+ || !TIFFSetField (pTiffHandle, TIFFTAG_BITSPERSAMPLE, bitsPerChannel)
798
+ || !TIFFSetField (pTiffHandle, TIFFTAG_COMPRESSION, compression)
799
+ || !TIFFSetField (pTiffHandle, TIFFTAG_PHOTOMETRIC, colorspace)
800
+ || !TIFFSetField (pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, channels)
801
+ || !TIFFSetField (pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)
802
+ || !TIFFSetField (pTiffHandle, TIFFTAG_ROWSPERSTRIP, rowsPerStrip)
803
+ || (img_vec.size () > 1 && (
804
+ !TIFFSetField (pTiffHandle, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE)
805
+ || !TIFFSetField (pTiffHandle, TIFFTAG_PAGENUMBER, page, img_vec.size () )))
806
+ )
807
+ {
808
+ TIFFClose (pTiffHandle);
809
+ return false ;
810
+ }
811
+
812
+ if (compression != COMPRESSION_NONE && !TIFFSetField (pTiffHandle, TIFFTAG_PREDICTOR, predictor))
813
+ {
814
+ TIFFClose (pTiffHandle);
815
+ return false ;
816
+ }
817
+
818
+ // row buffer, because TIFFWriteScanline modifies the original data!
819
+ size_t scanlineSize = TIFFScanlineSize (pTiffHandle);
820
+ AutoBuffer<uchar> _buffer (scanlineSize + 32 );
821
+ uchar* buffer = _buffer;
822
+ if (!buffer)
859
823
{
860
824
TIFFClose (pTiffHandle);
861
825
return false ;
862
826
}
827
+
828
+ for (int y = 0 ; y < height; ++y)
829
+ {
830
+ switch (channels)
831
+ {
832
+ case 1 :
833
+ {
834
+ memcpy (buffer, img.ptr (y), scanlineSize);
835
+ break ;
836
+ }
837
+
838
+ case 3 :
839
+ {
840
+ if (depth == CV_8U)
841
+ icvCvt_BGR2RGB_8u_C3R ( img.ptr (y), 0 , buffer, 0 , cvSize (width, 1 ));
842
+ else
843
+ icvCvt_BGR2RGB_16u_C3R ( img.ptr <ushort>(y), 0 , (ushort*)buffer, 0 , cvSize (width, 1 ));
844
+ break ;
845
+ }
846
+
847
+ case 4 :
848
+ {
849
+ if (depth == CV_8U)
850
+ icvCvt_BGRA2RGBA_8u_C4R ( img.ptr (y), 0 , buffer, 0 , cvSize (width, 1 ));
851
+ else
852
+ icvCvt_BGRA2RGBA_16u_C4R ( img.ptr <ushort>(y), 0 , (ushort*)buffer, 0 , cvSize (width, 1 ));
853
+ break ;
854
+ }
855
+
856
+ default :
857
+ {
858
+ TIFFClose (pTiffHandle);
859
+ return false ;
860
+ }
861
+ }
862
+
863
+ int writeResult = TIFFWriteScanline (pTiffHandle, buffer, y, 0 );
864
+ if (writeResult != 1 )
865
+ {
866
+ TIFFClose (pTiffHandle);
867
+ return false ;
868
+ }
869
+ }
870
+
871
+ TIFFWriteDirectory (pTiffHandle);
872
+
863
873
}
864
874
865
875
TIFFClose (pTiffHandle);
@@ -946,6 +956,11 @@ bool TiffEncoder::write_32FC1(const Mat& _img)
946
956
return true ;
947
957
}
948
958
959
+ bool TiffEncoder::writemulti (const std::vector<Mat>& img_vec, const std::vector<int >& params)
960
+ {
961
+ return writeLibTiff (img_vec, params);
962
+ }
963
+
949
964
bool TiffEncoder::write ( const Mat& img, const std::vector<int >& params)
950
965
{
951
966
int depth = img.depth ();
@@ -961,7 +976,9 @@ bool TiffEncoder::write( const Mat& img, const std::vector<int>& params)
961
976
962
977
CV_Assert (depth == CV_8U || depth == CV_16U);
963
978
964
- return writeLibTiff (img, params);
979
+ std::vector<Mat> img_vec;
980
+ img_vec.push_back (img);
981
+ return writeLibTiff (img_vec, params);
965
982
}
966
983
967
984
} // namespace
0 commit comments