Пример #1
0
        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));
        }
Пример #2
0
        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);
            }
        }
Пример #3
0
        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();
        }
Пример #4
0
        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);
        }
Пример #5
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();
            }
        }
Пример #6
0
        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);
        }
Пример #7
0
        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));
        }
Пример #8
0
        /// <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);
        }
Пример #9
0
        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);
        }
Пример #10
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));
        }
Пример #11
0
        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);
                }
            }
        }
Пример #12
0
        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}.");
            }
        }
Пример #13
0
        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);
        }
Пример #14
0
        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);
        }