@@ -74,6 +74,8 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals
7474 /// </summary>
7575 private const TiffPhotometricInterpretation DefaultPhotometricInterpretation = TiffPhotometricInterpretation . Rgb ;
7676
77+ private readonly List < ( long , uint ) > frameMarkers = new List < ( long , uint ) > ( ) ;
78+
7779 /// <summary>
7880 /// Initializes a new instance of the <see cref="TiffEncoderCore"/> class.
7981 /// </summary>
@@ -147,13 +149,25 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
147149 // Make sure, the Encoder options makes sense in combination with each other.
148150 this . SanitizeAndSetEncoderOptions ( bitsPerPixel , image . PixelType . BitsPerPixel , photometricInterpretation , compression , predictor ) ;
149151
150- using ( var writer = new TiffStreamWriter ( stream ) )
152+ using var writer = new TiffStreamWriter ( stream ) ;
153+ long ifdMarker = this . WriteHeader ( writer ) ;
154+
155+ Image < TPixel > metadataImage = image ;
156+ foreach ( ImageFrame < TPixel > frame in image . Frames )
151157 {
152- long firstIfdMarker = this . WriteHeader ( writer ) ;
158+ var subfileType = ( TiffNewSubfileType ) ( frame . Metadata . ExifProfile ? . GetValue ( ExifTag . SubfileType ) ? . Value ?? ( int ) TiffNewSubfileType . FullImage ) ;
153159
154- // TODO: multiframing is not supported
155- this . WriteImage ( writer , image , firstIfdMarker ) ;
160+ ifdMarker = this . WriteFrame ( writer , frame , image . Metadata , metadataImage , ifdMarker ) ;
161+ metadataImage = null ;
162+ }
163+
164+ long currentOffset = writer . BaseStream . Position ;
165+ foreach ( ( long , uint ) marker in this . frameMarkers )
166+ {
167+ writer . WriteMarkerFast ( marker . Item1 , marker . Item2 ) ;
156168 }
169+
170+ writer . BaseStream . Seek ( currentOffset , SeekOrigin . Begin ) ;
157171 }
158172
159173 /// <summary>
@@ -174,41 +188,56 @@ public long WriteHeader(TiffStreamWriter writer)
174188 /// Writes all data required to define an image.
175189 /// </summary>
176190 /// <typeparam name="TPixel">The pixel format.</typeparam>
177- /// <param name="writer">The <see cref="BinaryWriter"/> to write data to.</param>
178- /// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
191+ /// <param name="writer">The <see cref="BinaryWriter" /> to write data to.</param>
192+ /// <param name="frame">The tiff frame.</param>
193+ /// <param name="imageMetadata">The image metadata (resolution values for each frame).</param>
194+ /// <param name="image">The image (common metadata for root frame).</param>
179195 /// <param name="ifdOffset">The marker to write this IFD offset.</param>
180- private void WriteImage < TPixel > ( TiffStreamWriter writer , Image < TPixel > image , long ifdOffset )
196+ /// <returns>
197+ /// The next IFD offset value.
198+ /// </returns>
199+ private long WriteFrame < TPixel > (
200+ TiffStreamWriter writer ,
201+ ImageFrame < TPixel > frame ,
202+ ImageMetadata imageMetadata ,
203+ Image < TPixel > image ,
204+ long ifdOffset )
181205 where TPixel : unmanaged, IPixel < TPixel >
182206 {
183- var entriesCollector = new TiffEncoderEntriesCollector ( ) ;
184-
185207 using TiffBaseCompressor compressor = TiffCompressorFactory . Create (
186208 this . CompressionType ?? TiffCompression . None ,
187209 writer . BaseStream ,
188210 this . memoryAllocator ,
189- image . Width ,
211+ frame . Width ,
190212 ( int ) this . BitsPerPixel ,
191213 this . compressionLevel ,
192214 this . HorizontalPredictor == TiffPredictor . Horizontal ? this . HorizontalPredictor . Value : TiffPredictor . None ) ;
193215
216+ var entriesCollector = new TiffEncoderEntriesCollector ( ) ;
194217 using TiffBaseColorWriter < TPixel > colorWriter = TiffColorWriterFactory . Create (
195218 this . PhotometricInterpretation ,
196- image . Frames . RootFrame ,
219+ frame ,
197220 this . quantizer ,
198221 this . memoryAllocator ,
199222 this . configuration ,
200223 entriesCollector ,
201224 ( int ) this . BitsPerPixel ) ;
202225
203- int rowsPerStrip = this . CalcRowsPerStrip ( image . Frames . RootFrame . Height , colorWriter . BytesPerRow ) ;
226+ int rowsPerStrip = this . CalcRowsPerStrip ( frame . Height , colorWriter . BytesPerRow ) ;
204227
205228 colorWriter . Write ( compressor , rowsPerStrip ) ;
206229
230+ if ( image != null )
231+ {
232+ entriesCollector . ProcessMetadata ( image ) ;
233+ }
234+
235+ entriesCollector . ProcessFrameInfo ( frame , imageMetadata ) ;
207236 entriesCollector . ProcessImageFormat ( this ) ;
208- entriesCollector . ProcessGeneral ( image ) ;
209237
210- writer . WriteMarker ( ifdOffset , ( uint ) writer . Position ) ;
211- long nextIfdMarker = this . WriteIfd ( writer , entriesCollector . Entries ) ;
238+ this . frameMarkers . Add ( ( ifdOffset , ( uint ) writer . Position ) ) ;
239+
240+ return this . WriteIfd ( writer , entriesCollector . Entries ) ;
212241 }
213242
214243 /// <summary>
@@ -272,7 +301,7 @@ private long WriteIfd(TiffStreamWriter writer, List<IExifValue> entries)
272301 }
273302 else
274303 {
275- var raw = new byte [ length ] ;
304+ byte [ ] raw = new byte [ length ] ;
276305 int sz = ExifWriter . WriteValue ( entry , raw , 0 ) ;
277306 DebugGuard . IsTrue ( sz == raw . Length , "Incorrect number of bytes written" ) ;
278307 largeDataBlocks . Add ( raw ) ;
0 commit comments