@@ -687,6 +687,7 @@ class TIFFFormat : public ImageFormat
687687 size_t units;
688688 grk_io_callback grkReclaimCallback_;
689689 void * grkReclaimUserData_;
690+ grk::PlanarToInterleaved<T>* interleaver_;
690691};
691692
692693#ifdef GRK_CUSTOM_TIFF_IO
@@ -756,13 +757,14 @@ TIFF* TIFFFormat<T>::MyTIFFOpen(const char* name, const char* mode)
756757template <typename T>
757758TIFFFormat<T>::TIFFFormat()
758759 : tif_(nullptr ), chroma_subsample_x(1 ), chroma_subsample_y(1 ), units(0 ),
759- grkReclaimCallback_ (nullptr ), grkReclaimUserData_(nullptr )
760+ grkReclaimCallback_ (nullptr ), grkReclaimUserData_(nullptr ), interleaver_( nullptr )
760761
761762{}
762763
763764template <typename T>
764765TIFFFormat<T>::~TIFFFormat ()
765766{
767+ delete interleaver_;
766768 if (tif_)
767769 TIFFClose (tif_);
768770}
@@ -1085,8 +1087,25 @@ bool TIFFFormat<T>::writeImageBand(uint32_t yBegin, uint32_t yEnd)
10851087 }
10861088 bool success = false ;
10871089 uint16_t numcomps = image_->decompress_num_comps ;
1088- auto planes = std::make_unique<T*[]>(numcomps);
1089- auto planesBegin = std::make_unique<T*[]>(numcomps);
1090+ constexpr uint16_t kMaxStackComps = 4 ;
1091+ T* stackPlanes[kMaxStackComps ];
1092+ T* stackPlanesBegin[kMaxStackComps ];
1093+ std::unique_ptr<T*[]> heapPlanes;
1094+ std::unique_ptr<T*[]> heapPlanesBegin;
1095+ T** planes;
1096+ T** planesBegin;
1097+ if (numcomps <= kMaxStackComps )
1098+ {
1099+ planes = stackPlanes;
1100+ planesBegin = stackPlanesBegin;
1101+ }
1102+ else
1103+ {
1104+ heapPlanes = std::make_unique<T*[]>(numcomps);
1105+ heapPlanesBegin = std::make_unique<T*[]>(numcomps);
1106+ planes = heapPlanes.get ();
1107+ planesBegin = heapPlanesBegin.get ();
1108+ }
10901109 GrkIOBuf packedBuf;
10911110
10921111 if (isFinalOutputSubsampled (image_))
@@ -1169,28 +1188,27 @@ bool TIFFFormat<T>::writeImageBand(uint32_t yBegin, uint32_t yEnd)
11691188 {
11701189 planes[i] = (T*)image_->comps [i].data + (uint64_t )yBegin * image_->comps [0 ].stride ;
11711190 }
1172- auto iter = grk::InterleaverFactory<T>::makeInterleaver (image_->decompress_prec );
1173- if (!iter)
1174- goto cleanup;
1191+ if (!interleaver_)
1192+ {
1193+ interleaver_ = grk::InterleaverFactory<T>::makeInterleaver (image_->decompress_prec );
1194+ if (!interleaver_)
1195+ goto cleanup;
1196+ }
11751197 uint32_t h = yBegin;
11761198 while (h < yEnd)
11771199 {
11781200 uint32_t stripRows = (std::min)(image_->rows_per_strip , yEnd - h);
11791201 packedBuf = pool.get (image_->packed_row_bytes * stripRows);
1180- iter ->interleave (((T**) planes. get ()) , numcomps, packedBuf.data , image_->decompress_width ,
1181- image_->comps [0 ].stride , image_->packed_row_bytes , stripRows, 0 );
1202+ interleaver_ ->interleave (planes, numcomps, packedBuf.data , image_->decompress_width ,
1203+ image_->comps [0 ].stride , image_->packed_row_bytes , stripRows, 0 );
11821204 packedBuf.pooled = true ;
11831205 packedBuf.offset = orchestrator.getOffset ();
11841206 packedBuf.len = image_->packed_row_bytes * stripRows;
11851207 packedBuf.index = orchestrator.getNumPooledRequests ();
11861208 if (!writeStripCore (0 , packedBuf))
1187- {
1188- delete iter;
11891209 goto cleanup;
1190- }
11911210 h += stripRows;
11921211 }
1193- delete iter;
11941212 }
11951213 success = true ;
11961214cleanup:
0 commit comments