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); } } }
/// <summary> /// Read the values of InteroperabilityIndex tag. /// Field description: Indicates the identification of the Interoperability rule. /// </summary> /// <param name="tagReader">The tag reader to use.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that fires if the user want to stop the current task.</param> /// <returns>A <see cref="ValueTask{TiffValueCollection}"/> that completes when the value of the tag is read and return the read values.</returns> public static ValueTask <string?> ReadInteroperabilityIndexAsync(this TiffTagReader tagReader, CancellationToken cancellationToken = default) { ValueTask <TiffValueCollection <string> > valueTask = tagReader.ReadASCIIFieldAsync((TiffTag)0x0001, cancellationToken); if (valueTask.IsCompletedSuccessfully) { TiffValueCollection <string> result = valueTask.GetAwaiter().GetResult(); return(new ValueTask <string?>(result.GetFirstOrDefault())); } return(new ValueTask <string?>(TransformValueTaskAsync(valueTask)));
private static async Task DumpWellKnownTagsAsync(TiffFieldReader fieldReader, TiffImageFileDirectory ifd, CancellationToken cancellationToken) { int count = 0; var tagReader = new TiffTagReader(fieldReader, ifd); if (ifd.Contains(TiffTag.PhotometricInterpretation)) { Console.WriteLine(" PhotometricInterpretation = " + (await tagReader.ReadPhotometricInterpretationAsync(cancellationToken))); count++; } if (ifd.Contains(TiffTag.SamplesPerPixel)) { Console.WriteLine(" SamplesPerPixel = " + (await tagReader.ReadSamplesPerPixelAsync(cancellationToken))); count++; } if (ifd.Contains(TiffTag.BitsPerSample)) { Console.Write(" BitsPerSample = "); DumpValueCollecionSimple(await tagReader.ReadBitsPerSampleAsync(cancellationToken)); Console.WriteLine(); count++; } if (ifd.Contains(TiffTag.ImageWidth)) { Console.WriteLine(" ImageWidth = " + (await tagReader.ReadImageWidthAsync(cancellationToken))); count++; } if (ifd.Contains(TiffTag.ImageLength)) { Console.WriteLine(" ImageLength = " + (await tagReader.ReadImageLengthAsync(cancellationToken))); count++; } if (ifd.Contains(TiffTag.Compression)) { Console.WriteLine(" Compression = " + (await tagReader.ReadCompressionAsync(cancellationToken))); count++; } if (ifd.Contains(TiffTag.FillOrder)) { Console.WriteLine(" FillOrder = " + (await tagReader.ReadFillOrderAsync(cancellationToken))); count++; } if (ifd.Contains(TiffTag.Predictor)) { Console.WriteLine(" Predictor = " + (await tagReader.ReadPredictorAsync(cancellationToken))); count++; } if (ifd.Contains(TiffTag.Orientation)) { Console.WriteLine(" Orientation = " + (await tagReader.ReadOrientationAsync(cancellationToken))); count++; } if (ifd.Contains(TiffTag.RowsPerStrip)) { Console.WriteLine(" RowsPerStrip = " + (await tagReader.ReadRowsPerStripAsync(cancellationToken))); count++; } if (ifd.Contains(TiffTag.TileWidth)) { Console.WriteLine(" TileWidth = " + (await tagReader.ReadTileWidthAsync(cancellationToken))); count++; } if (ifd.Contains(TiffTag.TileLength)) { Console.WriteLine(" TileLength = " + (await tagReader.ReadTileLengthAsync(cancellationToken))); count++; } if (count == 0) { Console.WriteLine(" No well-known tags found."); } }
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)); }