private Task EncodeImageAsync <TPixel>(ImageFrame <TPixel> image, TiffImageFileDirectoryWriter ifdWriter, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel <TPixel> { ITiffEncoderOptions options = _options; var builder = new TiffImageEncoderBuilder(); builder.MemoryPool = _memoryPool; builder.PhotometricInterpretation = options.PhotometricInterpretation; builder.Compression = options.Compression; builder.IsTiled = options.IsTiled; builder.RowsPerStrip = options.RowsPerStrip; builder.TileSize = new TiffSize(options.TileSize.Width, options.TileSize.Height); builder.Predictor = options.Predictor; builder.EnableTransparencyForRgb = options.EnableTransparencyForRgb; builder.Orientation = options.Orientation; builder.DeflateCompressionLevel = options.DeflateCompressionLevel; builder.JpegOptions = new TiffJpegEncodingOptions { Quality = options.JpegQuality, OptimizeCoding = options.JpegOptimizeCoding }; builder.HorizontalChromaSubSampling = options.HorizontalChromaSubSampling; builder.VerticalChromaSubSampling = options.VerticalChromaSubSampling; TiffImageEncoder <TPixel> encoder = builder.BuildForImageSharp <TPixel>(); return(encoder.EncodeAsync(ifdWriter, image, cancellationToken)); }
private async Task EncodeCoreAsync <TPixel>(Image <TPixel> image, Stream stream, bool isAsync, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel <TPixel> { TiffFileWriter writer; if (isAsync) { writer = await TiffFileWriter.OpenAsync(stream, leaveOpen : true, cancellationToken : cancellationToken).ConfigureAwait(false); } else { writer = await TiffFileWriter.OpenAsync(new ImageSharpContentReaderWriter(stream), leaveOpen : true, cancellationToken : cancellationToken).ConfigureAwait(false); } try { using (TiffImageFileDirectoryWriter ifdWriter = writer.CreateImageFileDirectory()) { await EncodeImageAsync(image.Frames.RootFrame, ifdWriter, cancellationToken).ConfigureAwait(false); writer.SetFirstImageFileDirectoryOffset(await ifdWriter.FlushAsync(cancellationToken).ConfigureAwait(false)); } await writer.FlushAsync(cancellationToken).ConfigureAwait(false); } finally { await writer.DisposeAsync().ConfigureAwait(false); } }
public async Task EncodeTileImage() { await using TiffFileWriter writer = await TiffFileWriter.OpenAsync(new EmptyContentReaderWriter (), false, false); using (TiffImageFileDirectoryWriter ifdWriter = writer.CreateImageFileDirectory()) { await _tileEncoder.EncodeAsync(ifdWriter, _image); writer.SetFirstImageFileDirectoryOffset(await ifdWriter.FlushAsync()); } await writer.FlushAsync(); }
public static async Task <int> Merge(FileInfo[] source, FileInfo output, CancellationToken cancellationToken) { if (source is null || source.Length == 0) { Console.WriteLine("Input TIFF file are not specified."); return(1); } if (output is null) { Console.WriteLine("Output TIFF file is not specified"); return(1); } await using TiffFileWriter writer = await TiffFileWriter.OpenAsync(output.FullName); TiffStreamOffset fistIfdOffset = default; TiffStreamOffset previousIfdOffset = default; foreach (FileInfo sourceFile in source) { await using TiffFileReader reader = await TiffFileReader.OpenAsync(sourceFile.FullName); await using TiffFileContentReader contentReader = await reader.CreateContentReaderAsync(); await using TiffFieldReader fieldReader = await reader.CreateFieldReaderAsync(cancellationToken); TiffStreamOffset inputIfdOffset = reader.FirstImageFileDirectoryOffset; while (!inputIfdOffset.IsZero) { TiffImageFileDirectory ifd = await reader.ReadImageFileDirectoryAsync(inputIfdOffset, cancellationToken); using (TiffImageFileDirectoryWriter ifdWriter = writer.CreateImageFileDirectory()) { await CopyIfdAsync(contentReader, fieldReader, ifd, ifdWriter, cancellationToken); previousIfdOffset = await ifdWriter.FlushAsync(previousIfdOffset); if (fistIfdOffset.IsZero) { fistIfdOffset = previousIfdOffset; } } inputIfdOffset = ifd.NextOffset; } } writer.SetFirstImageFileDirectoryOffset(fistIfdOffset); await writer.FlushAsync(); return(0); }
private static async Task GenerateImageAsync(Stream stream, TiffImageEncoderBuilder builder, TiffPixelBuffer <TiffGray8> image) { using (TiffFileWriter writer = await TiffFileWriter.OpenAsync(stream, true)) { TiffStreamOffset ifdOffset; using (TiffImageFileDirectoryWriter ifdWriter = writer.CreateImageFileDirectory()) { TiffImageEncoder <TiffGray8> encoder = builder.Build <TiffGray8>(); await encoder.EncodeAsync(ifdWriter, image); ifdOffset = await ifdWriter.FlushAsync(); } writer.SetFirstImageFileDirectoryOffset(ifdOffset); await writer.FlushAsync(); } }
private static async Task <Stream> GenerateTiffAsync(bool bigTiff, Func <TiffImageFileDirectoryWriter, Task> ifdAction) { var ms = new MemoryStream(); using (TiffFileWriter writer = await TiffFileWriter.OpenAsync(ms, leaveOpen: true, useBigTiff: bigTiff)) { using (TiffImageFileDirectoryWriter ifd = writer.CreateImageFileDirectory()) { await ifdAction(ifd); writer.SetFirstImageFileDirectoryOffset(await ifd.FlushAsync()); } await writer.FlushAsync(); } ms.Seek(0, SeekOrigin.Begin); return(ms); }
public override Task EncodeAsync(TiffImageFileDirectoryWriter writer, TiffPoint offset, TiffSize size, ITiffPixelBufferReader <TExposedPixel> reader, CancellationToken cancellationToken = default) { if (writer is null) { throw new ArgumentNullException(nameof(writer)); } if (reader is null) { throw new ArgumentNullException(nameof(reader)); } if (typeof(TExposedPixel) == typeof(TIntermediate)) { return(_encoder.EncodeAsync(writer, offset, size, new TiffPassthroughPixelBufferReader <TExposedPixel, TTiffPixel>(reader), cancellationToken)); } return(_encoder.EncodeAsync(writer, offset, size, new ImageSharpConversionPixelBufferReader <TExposedPixel, TIntermediate, TTiffPixel>(reader), cancellationToken)); }
/// <inheritdoc /> public override async Task EncodeAsync(TiffImageFileDirectoryWriter writer, TiffPoint offset, TiffSize size, ITiffPixelBufferReader <TPixel> reader, CancellationToken cancellationToken) { if (writer is null) { throw new ArgumentNullException(nameof(writer)); } if (reader is null) { throw new ArgumentNullException(nameof(reader)); } if (_ifdEncoder is null) { throw new InvalidOperationException("Ifd encoder is not configured."); } TiffPixelBufferReader <TPixel> structReader = reader.AsPixelBufferReader(); size = new TiffSize(Math.Max(0, Math.Min(structReader.Width - offset.X, structReader.Width)), Math.Max(0, Math.Min(structReader.Height - offset.Y, structReader.Height))); if (size.IsAreaEmpty) { throw new ArgumentOutOfRangeException(nameof(size), "The image size is zero."); } var context = new TiffDefaultImageEncoderContext <TPixel> { MemoryPool = _memoryPool ?? MemoryPool <byte> .Shared, CancellationToken = cancellationToken, FileWriter = writer.FileWriter, IfdWriter = writer, ImageSize = size, PixelConverterFactory = TiffDefaultPixelConverterFactory.Instance, PixelBufferReader = structReader }; await _ifdEncoder.RunAsync(context).ConfigureAwait(false); }
public static async Task <int> Wrap(FileInfo source, FileInfo output, CancellationToken cancellationToken) { if (source is null || !source.Exists) { Console.WriteLine(source is null ? "Input JPEG image is not specified." : "File not found: " + source.FullName); return(1); } if (output is null) { Console.WriteLine("Output TIFF file is not specified."); return(1); } byte[] jpegFile = await File.ReadAllBytesAsync(source.FullName, cancellationToken); var decoder = new JpegDecoder(); decoder.SetInput(jpegFile); decoder.Identify(loadQuantizationTables: false); ushort[] bitsPerSample = new ushort[decoder.NumberOfComponents]; ushort bits = (ushort)decoder.Precision; for (int i = 0; i < bitsPerSample.Length; i++) { bitsPerSample[i] = bits; } TiffPhotometricInterpretation photometricInterpretation = bitsPerSample.Length == 1 ? TiffPhotometricInterpretation.BlackIsZero : bitsPerSample.Length == 3 ? TiffPhotometricInterpretation.YCbCr : throw new InvalidDataException("Photometric interpretation not supported."); using (TiffFileWriter writer = await TiffFileWriter.OpenAsync(output.FullName, useBigTiff: false)) { TiffStreamOffset imageOffset = await writer.WriteAlignedBytesAsync(jpegFile); TiffStreamOffset ifdOffset; using (TiffImageFileDirectoryWriter ifdWriter = writer.CreateImageFileDirectory()) { await ifdWriter.WriteTagAsync(TiffTag.ImageWidth, TiffValueCollection.Single((ushort)decoder.Width)); await ifdWriter.WriteTagAsync(TiffTag.ImageLength, TiffValueCollection.Single((ushort)decoder.Height)); await ifdWriter.WriteTagAsync(TiffTag.BitsPerSample, TiffValueCollection.UnsafeWrap(bitsPerSample)); await ifdWriter.WriteTagAsync(TiffTag.Compression, TiffValueCollection.Single((ushort)TiffCompression.Jpeg)); await ifdWriter.WriteTagAsync(TiffTag.PhotometricInterpretation, TiffValueCollection.Single((ushort)photometricInterpretation)); await ifdWriter.WriteTagAsync(TiffTag.SamplesPerPixel, TiffValueCollection.Single((ushort)bitsPerSample.Length)); await ifdWriter.WriteTagAsync(TiffTag.PlanarConfiguration, TiffValueCollection.Single((ushort)TiffPlanarConfiguration.Chunky)); await ifdWriter.WriteTagAsync(TiffTag.RowsPerStrip, TiffValueCollection.Single((ushort)decoder.Height)); await ifdWriter.WriteTagAsync(TiffTag.StripOffsets, TiffValueCollection.Single((uint)imageOffset.Offset)); await ifdWriter.WriteTagAsync(TiffTag.StripByteCounts, TiffValueCollection.Single((uint)jpegFile.Length)); if (photometricInterpretation == TiffPhotometricInterpretation.YCbCr) { int maxHorizontalSampling = decoder.GetMaximumHorizontalSampling(); int maxVerticalSampling = decoder.GetMaximumVerticalSampling(); int yHorizontalSubSampling = maxHorizontalSampling / decoder.GetHorizontalSampling(0); int yVerticalSubSampling = maxVerticalSampling / decoder.GetVerticalSampling(0); int cbHorizontalSubSampling = maxHorizontalSampling / decoder.GetHorizontalSampling(1) / yHorizontalSubSampling; int cbVerticalSubSampling = maxVerticalSampling / decoder.GetVerticalSampling(1) / yVerticalSubSampling; int crHorizontalSubSampling = maxHorizontalSampling / decoder.GetHorizontalSampling(2) / yHorizontalSubSampling; int crVerticalSubSampling = maxVerticalSampling / decoder.GetVerticalSampling(2) / yVerticalSubSampling; if (cbHorizontalSubSampling != crHorizontalSubSampling || cbVerticalSubSampling != crVerticalSubSampling) { throw new InvalidDataException("Unsupported JPEG image."); } await ifdWriter.WriteTagAsync(TiffTag.YCbCrSubSampling, TiffValueCollection.UnsafeWrap(new ushort[] { (ushort)cbHorizontalSubSampling, (ushort)cbVerticalSubSampling })); } // Write other properties here (eg, XResolution, YResolution) await ifdWriter.WriteTagAsync(TiffTag.XResolution, TiffValueCollection.Single(new TiffRational(96, 1))); await ifdWriter.WriteTagAsync(TiffTag.YResolution, TiffValueCollection.Single(new TiffRational(96, 1))); await ifdWriter.WriteTagAsync(TiffTag.ResolutionUnit, TiffValueCollection.Single((ushort)TiffResolutionUnit.Inch)); ifdOffset = await ifdWriter.FlushAsync(); } writer.SetFirstImageFileDirectoryOffset(ifdOffset); await writer.FlushAsync(); } return(0); }
private static async Task CopyStrippedImageAsync(TiffFileContentReader contentReader, TiffTagReader tagReader, TiffImageFileDirectoryWriter dest, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); TiffValueCollection <ulong> offsets = await tagReader.ReadStripOffsetsAsync(cancellationToken); TiffValueCollection <ulong> byteCounts = await tagReader.ReadStripByteCountsAsync(cancellationToken); if (offsets.Count != byteCounts.Count) { throw new InvalidDataException("Failed to copy stripped image data. StripOffsets and StripByteCounts don't have the same amount of elements."); } uint[] offsets32 = new uint[offsets.Count]; uint[] byteCounts32 = new uint[offsets.Count]; byte[]? buffer = null; try { for (int i = 0; i < offsets.Count; i++) { int offset = checked ((int)offsets[i]); int byteCount = checked ((int)byteCounts[i]); byteCounts32[i] = checked ((uint)byteCount); if (buffer is null || byteCount > buffer.Length) { if (!(buffer is null)) { ArrayPool <byte> .Shared.Return(buffer); } buffer = ArrayPool <byte> .Shared.Rent(byteCount); } if (await contentReader.ReadAsync(offset, new ArraySegment <byte>(buffer, 0, byteCount), cancellationToken) != byteCount) { throw new InvalidDataException("Invalid ByteCount field."); } TiffStreamOffset region = await dest.FileWriter.WriteAlignedBytesAsync(buffer, 0, byteCount); offsets32[i] = checked ((uint)region.Offset); } } finally { if (!(buffer is null)) { ArrayPool <byte> .Shared.Return(buffer); } } await dest.WriteTagAsync(TiffTag.StripOffsets, TiffValueCollection.UnsafeWrap(offsets32)); await dest.WriteTagAsync(TiffTag.StripByteCounts, TiffValueCollection.UnsafeWrap(byteCounts32)); }
private static async Task CopyIfdAsync(TiffFileContentReader contentReader, TiffFieldReader fieldReader, TiffImageFileDirectory ifd, TiffImageFileDirectoryWriter dest, CancellationToken cancellationToken) { var tagReader = new TiffTagReader(fieldReader, ifd); foreach (TiffImageFileDirectoryEntry entry in ifd) { // Stripped image data if (entry.Tag == TiffTag.StripOffsets) { await CopyStrippedImageAsync(contentReader, tagReader, dest, cancellationToken); } else if (entry.Tag == TiffTag.StripByteCounts) { // Ignore this } // Tiled image data else if (entry.Tag == TiffTag.TileOffsets) { await CopyTiledImageAsync(contentReader, tagReader, dest, cancellationToken); } else if (entry.Tag == TiffTag.TileByteCounts) { // Ignore this } // Other fields else { await CopyFieldValueAsync(fieldReader, entry, dest, cancellationToken); } } }
private static async Task CopyFieldValueAsync(TiffFieldReader reader, TiffImageFileDirectoryEntry entry, TiffImageFileDirectoryWriter ifdWriter, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); switch (entry.Type) { case TiffFieldType.Byte: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadByteFieldAsync(entry)); break; case TiffFieldType.ASCII: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadASCIIFieldAsync(entry)); break; case TiffFieldType.Short: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadShortFieldAsync(entry)); break; case TiffFieldType.Long: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadLongFieldAsync(entry)); break; case TiffFieldType.Rational: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadRationalFieldAsync(entry)); break; case TiffFieldType.SByte: await ifdWriter.WriteTagAsync(entry.Tag, entry.Type, await reader.ReadByteFieldAsync(entry)); break; case TiffFieldType.Undefined: await ifdWriter.WriteTagAsync(entry.Tag, entry.Type, await reader.ReadByteFieldAsync(entry)); break; case TiffFieldType.SShort: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadSShortFieldAsync(entry)); break; case TiffFieldType.SLong: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadSLongFieldAsync(entry)); break; case TiffFieldType.SRational: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadSRationalFieldAsync(entry)); break; case TiffFieldType.Float: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadFloatFieldAsync(entry)); break; case TiffFieldType.Double: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadDoubleFieldAsync(entry)); break; case TiffFieldType.IFD: throw new NotSupportedException("This IFD type is not supported yet."); case TiffFieldType.Long8: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadLong8FieldAsync(entry)); break; case TiffFieldType.SLong8: await ifdWriter.WriteTagAsync(entry.Tag, await reader.ReadSLong8FieldAsync(entry)); break; case TiffFieldType.IFD8: throw new NotSupportedException("This IFD type is not supported yet."); default: throw new NotSupportedException($"Unsupported IFD field type: {entry.Type}."); } }
internal async Task <TiffStreamOffset> GenerateReducedResolutionLayerAsync(int layer, TiffStreamOffset ifdOffset, IRipperReducedResolutionGenerationReporter reporter, CancellationToken cancellationToken) { int outputTileSize = _options.OutputTileSize; int outputTileSize2 = 2 * outputTileSize; TiffImageFileDirectory ifd = await _fileReader.ReadImageFileDirectoryAsync(ifdOffset).ConfigureAwait(false); TiffImageDecoder image = await _fileReader.CreateImageDecoderAsync(ifd); int width = image.Width; int height = image.Height; int tiffRowCount = (width / 2 + outputTileSize - 1) / outputTileSize; int tiffColCount = (height / 2 + outputTileSize - 1) / outputTileSize; int index = 0; ulong[] offsets = new ulong[tiffRowCount * tiffColCount]; ulong[] byteCounts = new ulong[tiffRowCount * tiffColCount]; ulong totalByteCount = 0; reporter?.ReportStartReducedResolutionLayerGeneration(layer, offsets.Length, width / 2, height / 2); using (Image <Rgb24> canvas2 = new Image <Rgb24>(_configuration, outputTileSize2, outputTileSize2)) { for (int y = 0; y < height; y += outputTileSize2) { for (int x = 0; x < width; x += outputTileSize2) { cancellationToken.ThrowIfCancellationRequested(); MemoryMarshal.AsBytes(canvas2.GetPixelSpan()).Clear(); await image.DecodeAsync(new TiffPoint(x, y), canvas2).ConfigureAwait(false); using (Image <Rgb24> tile24 = canvas2.Clone(ctx => { ctx.Resize(outputTileSize, outputTileSize); })) { cancellationToken.ThrowIfCancellationRequested(); TiffStreamRegion region = await _encoder.EncodeAsync(_fileWriter, tile24).ConfigureAwait(false); offsets[index] = (ulong)region.Offset.Offset; byteCounts[index] = (uint)region.Length; totalByteCount += (uint)region.Length; index++; reporter?.ReportReducedResolutionLayerGenerationProgress(layer, index, offsets.Length); } } } } cancellationToken.ThrowIfCancellationRequested(); using (TiffImageFileDirectoryWriter ifdWriter = _fileWriter.CreateImageFileDirectory()) { await ifdWriter.WriteTagAsync(TiffTag.NewSubfileType, new TiffValueCollection <ushort>((ushort)TiffNewSubfileType.ReducedResolution)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.PhotometricInterpretation, new TiffValueCollection <ushort>((ushort)TiffPhotometricInterpretation.YCbCr)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.Compression, new TiffValueCollection <ushort>((ushort)TiffCompression.Jpeg)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.SamplesPerPixel, new TiffValueCollection <ushort>((ushort)3)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileWidth, new TiffValueCollection <ushort>((ushort)outputTileSize)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileLength, new TiffValueCollection <ushort>((ushort)outputTileSize)).ConfigureAwait(false); //ifdWriter.AddTag(TiffTag.ResolutionUnit, (ushort)TiffResolutionUnit.Inch); //await ifdWriter.WriteTagAsync(TiffTag.XResolution, new TiffValueCollection<TiffRational>(new TiffRational(72, 1))); //await ifdWriter.WriteTagAsync(TiffTag.YResolution, new TiffValueCollection<TiffRational>(new TiffRational(72, 1))); await ifdWriter.WriteTagAsync(TiffTag.SampleFormat, new TiffValueCollection <ushort>(new ushort[] { 1, 1, 1 })).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.BitsPerSample, new TiffValueCollection <ushort>(new ushort[] { 8, 8, 8 })).ConfigureAwait(false); if (UseBigTiff) { await ifdWriter.WriteTagAsync(TiffTag.ImageWidth, new TiffValueCollection <ulong>((ulong)(width / 2))).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.ImageLength, new TiffValueCollection <ulong>((ulong)(height / 2))).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileOffsets, new TiffValueCollection <ulong>(offsets)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileByteCounts, new TiffValueCollection <ulong>(byteCounts)).ConfigureAwait(false); } else { await ifdWriter.WriteTagAsync(TiffTag.ImageWidth, new TiffValueCollection <uint>((uint)(width / 2))).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.ImageLength, new TiffValueCollection <uint>((uint)(height / 2))).ConfigureAwait(false); uint[] tempArr = new uint[offsets.Length]; for (int i = 0; i < tempArr.Length; i++) { tempArr[i] = (uint)offsets[i]; } await ifdWriter.WriteTagAsync(TiffTag.TileOffsets, new TiffValueCollection <uint>(tempArr)).ConfigureAwait(false); for (int i = 0; i < tempArr.Length; i++) { tempArr[i] = (uint)byteCounts[i]; } await ifdWriter.WriteTagAsync(TiffTag.TileByteCounts, new TiffValueCollection <uint>(tempArr)).ConfigureAwait(false); } string software = Software; if (!string.IsNullOrEmpty(software)) { await ifdWriter.WriteTagAsync(TiffTag.Software, new TiffValueCollection <string>(software)); } ifdOffset = await ifdWriter.FlushAsync(ifdOffset).ConfigureAwait(false); } reporter?.ReportCompleteReducedResolutionLayerGeneration(layer, offsets.Length, (long)totalByteCount); return(ifdOffset); }
public async Task RipBaseLayerAsync(IRipperInitialLayerAcquisitionReporter reporter, CancellationToken cancellationToken) { int outputTileSize = _options.OutputTileSize; int tiffRowCount = (ImageHeight + outputTileSize - 1) / outputTileSize; int tiffColCount = (ImageWidth + outputTileSize - 1) / outputTileSize; int index = 0; ulong[] offsets = new ulong[tiffRowCount * tiffColCount]; ulong[] byteCounts = new ulong[tiffRowCount * tiffColCount]; ulong totalByteCount = 0; reporter?.ReportStartInitialLayerAcquisition(offsets.Length); using (var regionReader = new TileRegionReader(this)) using (Image <Rgb24> canvas = new Image <Rgb24>(_configuration, outputTileSize, outputTileSize)) { for (int row = 0; row < tiffRowCount; row++) { int rowYOffset = row * outputTileSize; for (int col = 0; col < tiffColCount; col++) { int colXOffset = col * outputTileSize; MemoryMarshal.AsBytes(canvas.GetPixelSpan()).Clear(); await regionReader.FillRegionAsync(colXOffset, rowYOffset, canvas, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); TiffStreamRegion region = await _encoder.EncodeAsync(_fileWriter, canvas).ConfigureAwait(false); offsets[index] = (ulong)region.Offset.Offset; byteCounts[index] = (uint)region.Length; totalByteCount += (uint)region.Length; index++; reporter?.ReportInitialLayerAcquisitionProgress(index, offsets.Length); } } } cancellationToken.ThrowIfCancellationRequested(); TiffStreamOffset ifdOffset; using (TiffImageFileDirectoryWriter ifdWriter = _fileWriter.CreateImageFileDirectory()) { await ifdWriter.WriteTagAsync(TiffTag.PhotometricInterpretation, new TiffValueCollection <ushort>((ushort)TiffPhotometricInterpretation.YCbCr)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.Compression, new TiffValueCollection <ushort>((ushort)TiffCompression.Jpeg)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.SamplesPerPixel, new TiffValueCollection <ushort>((ushort)3)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileWidth, new TiffValueCollection <ushort>((ushort)outputTileSize)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileLength, new TiffValueCollection <ushort>((ushort)outputTileSize)).ConfigureAwait(false); //ifdWriter.AddTag(TiffTag.ResolutionUnit, (ushort)TiffResolutionUnit.Inch); //await ifdWriter.WriteTagAsync(TiffTag.XResolution, new TiffValueCollection<TiffRational>(new TiffRational(72, 1))); //await ifdWriter.WriteTagAsync(TiffTag.YResolution, new TiffValueCollection<TiffRational>(new TiffRational(72, 1))); await ifdWriter.WriteTagAsync(TiffTag.SampleFormat, new TiffValueCollection <ushort>(new ushort[] { 1, 1, 1 })).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.BitsPerSample, new TiffValueCollection <ushort>(new ushort[] { 8, 8, 8 })).ConfigureAwait(false); if (UseBigTiff) { await ifdWriter.WriteTagAsync(TiffTag.ImageWidth, new TiffValueCollection <ulong>((ulong)_manifest.Width)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.ImageLength, new TiffValueCollection <ulong>((ulong)_manifest.Height)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileOffsets, new TiffValueCollection <ulong>(offsets)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.TileByteCounts, new TiffValueCollection <ulong>(byteCounts)).ConfigureAwait(false); } else { await ifdWriter.WriteTagAsync(TiffTag.ImageWidth, new TiffValueCollection <uint>((uint)_manifest.Width)).ConfigureAwait(false); await ifdWriter.WriteTagAsync(TiffTag.ImageLength, new TiffValueCollection <uint>((uint)_manifest.Height)).ConfigureAwait(false); uint[] tempArr = new uint[offsets.Length]; for (int i = 0; i < tempArr.Length; i++) { tempArr[i] = (uint)offsets[i]; } await ifdWriter.WriteTagAsync(TiffTag.TileOffsets, new TiffValueCollection <uint>(tempArr)).ConfigureAwait(false); for (int i = 0; i < tempArr.Length; i++) { tempArr[i] = (uint)byteCounts[i]; } await ifdWriter.WriteTagAsync(TiffTag.TileByteCounts, new TiffValueCollection <uint>(tempArr)).ConfigureAwait(false); } string software = Software; if (!string.IsNullOrEmpty(software)) { await ifdWriter.WriteTagAsync(TiffTag.Software, new TiffValueCollection <string>(software)); } ifdOffset = await ifdWriter.FlushAsync().ConfigureAwait(false); } _fileWriter.SetFirstImageFileDirectoryOffset(ifdOffset); await _fileWriter.FlushAsync().ConfigureAwait(false); reporter?.ReportCompleteInitialLayerAcquisition(offsets.Length, (long)totalByteCount); }