コード例 #1
0
        public async Task TestRoundtrip(bool isTile)
        {
            TiffGray8[] refImage  = new TiffGray8[2048 * 2048];
            TiffGray8[] testImage = new TiffGray8[2048 * 2048];

            var rand = new Random(42);

            rand.NextBytes(MemoryMarshal.AsBytes(refImage.AsSpan()));

            var builder = new TiffImageEncoderBuilder();

            builder.PhotometricInterpretation = TiffPhotometricInterpretation.BlackIsZero;
            builder.Compression = TiffCompression.NoCompression;
            builder.IsTiled     = isTile;
            // Make sure we have at least CacheSize strips or tiles
            // Cache size in the current implementation is 256
            // Any value greater than 256 should be OK.
            builder.RowsPerStrip = 2;                    // 1024 strips
            builder.TileSize     = new TiffSize(16, 16); // 16384 tiles

            var ms = new MemoryStream();

            await GenerateImageAsync(ms, builder, TiffPixelBuffer.WrapReadOnly(refImage, 2048, 2048));

            ms.Seek(0, SeekOrigin.Begin);

            await using TiffFileReader tiff = await TiffFileReader.OpenAsync(ms, leaveOpen : true);

            TiffImageDecoder decoder = await tiff.CreateImageDecoderAsync();

            await decoder.DecodeAsync(TiffPixelBuffer.Wrap(testImage, 2048, 2048));

            Assert.True(refImage.AsSpan().SequenceEqual(testImage.AsSpan()));
        }
コード例 #2
0
        public async Task TestAsync(string reference, string test)
        {
            using var refImage = Image.Load <L8>(reference);

            await using TiffFileReader tiff = await TiffFileReader.OpenAsync(test);

            TiffStreamOffset ifdOffset = tiff.FirstImageFileDirectoryOffset;

            while (!ifdOffset.IsZero)
            {
                TiffImageFileDirectory ifd = await tiff.ReadImageFileDirectoryAsync(ifdOffset);

                TiffImageDecoder decoder = await tiff.CreateImageDecoderAsync(ifd, new TiffImageDecoderOptions { UndoColorPreMultiplying = true });

                Assert.Equal(refImage.Width, decoder.Width);
                Assert.Equal(refImage.Height, decoder.Height);
                TiffGray8[] pixels = new TiffGray8[decoder.Width * decoder.Height];

                await decoder.DecodeAsync(TiffPixelBuffer.Wrap(pixels, decoder.Width, decoder.Height));

                AssertEqual(refImage, pixels);

                using (var image = new Image <L8>(decoder.Width, decoder.Height))
                {
                    decoder.Decode(image);
                    AssertEqual(refImage, image);
                }

                ifdOffset = ifd.NextOffset;
            }
        }
コード例 #3
0
        public async Task TestImageDecodeAsync(string refImage, int refIfd, int refBitDepth, string testImage, int testIfd, int testBitDepth)
        {
            const int BufferBitDepth = 16;

            // We do not support decoding into 32 bit buffer yet.
            refBitDepth  = Math.Min(refBitDepth, BufferBitDepth);
            testBitDepth = Math.Min(testBitDepth, BufferBitDepth);

            TiffStreamOffset       ifdOffset;
            TiffImageFileDirectory ifd;

            // Load reference image
            await using TiffFileReader refTiff = await TiffFileReader.OpenAsync(refImage);

            ifdOffset = refTiff.FirstImageFileDirectoryOffset;
            Assert.False(ifdOffset.IsZero);
            for (int i = 0; i < refIfd; i++)
            {
                ifd = await refTiff.ReadImageFileDirectoryAsync(ifdOffset);

                ifdOffset = ifd.NextOffset;
                Assert.False(ifdOffset.IsZero);
            }
            ifd = await refTiff.ReadImageFileDirectoryAsync(ifdOffset);

            TiffImageDecoder refDecoder = await refTiff.CreateImageDecoderAsync(ifd);

            // Load test image
            await using TiffFileReader testTiff = await TiffFileReader.OpenAsync(testImage);

            ifdOffset = testTiff.FirstImageFileDirectoryOffset;
            Assert.False(ifdOffset.IsZero);
            for (int i = 0; i < testIfd; i++)
            {
                ifd = await testTiff.ReadImageFileDirectoryAsync(ifdOffset);

                ifdOffset = ifd.NextOffset;
                Assert.False(ifdOffset.IsZero);
            }
            ifd = await testTiff.ReadImageFileDirectoryAsync(ifdOffset);

            TiffImageDecoder testDecoder = await testTiff.CreateImageDecoderAsync(ifd);

            Assert.Equal(refDecoder.Width, testDecoder.Width);
            Assert.Equal(refDecoder.Height, testDecoder.Height);

            TiffRgba64[] refBuffer  = new TiffRgba64[refDecoder.Width * refDecoder.Height];
            TiffRgba64[] testBuffer = new TiffRgba64[testDecoder.Width * testDecoder.Height];

            await refDecoder.DecodeAsync(TiffPixelBuffer.Wrap(refBuffer, refDecoder.Width, refDecoder.Height));

            await testDecoder.DecodeAsync(TiffPixelBuffer.Wrap(testBuffer, testDecoder.Width, testDecoder.Height));

            ShiftPixels(MemoryMarshal.Cast <TiffRgba64, ushort>(refBuffer), BufferBitDepth - refBitDepth);
            ShiftPixels(MemoryMarshal.Cast <TiffRgba64, ushort>(testBuffer), BufferBitDepth - testBitDepth);

            Assert.True(refBuffer.AsSpan().SequenceEqual(testBuffer));
        }
コード例 #4
0
        private async Task <IImageInfo> IdentifyCoreAsync(TiffFileContentSource contentSource, CancellationToken cancellationToken)
        {
            using TiffFileReader tiff = await TiffFileReader.OpenAsync(contentSource, cancellationToken : cancellationToken).ConfigureAwait(false);

            TiffImageFileDirectory ifd = await tiff.ReadImageFileDirectoryAsync(cancellationToken).ConfigureAwait(false);

            TiffImageDecoder decoder = await tiff.CreateImageDecoderAsync(ifd, _options, cancellationToken).ConfigureAwait(false);

            return(new ImageInfo()
            {
                Width = decoder.Width,
                Height = decoder.Height
            });
        }
コード例 #5
0
        public async Task TestRoundtrip(bool isTile, int maxDegreeOfParallelism, bool isYCbCr)
        {
            TiffGray8[] refImage  = new TiffGray8[4096 * 4096];
            TiffGray8[] testImage = new TiffGray8[4096 * 4096];

            var rand = new Random(42);

            rand.NextBytes(MemoryMarshal.AsBytes(refImage.AsSpan()));

            var builder = new TiffImageEncoderBuilder();

            if (isYCbCr)
            {
                builder.PhotometricInterpretation   = TiffPhotometricInterpretation.YCbCr;
                builder.HorizontalChromaSubSampling = 2;
                builder.VerticalChromaSubSampling   = 2;
            }
            else
            {
                builder.PhotometricInterpretation = TiffPhotometricInterpretation.BlackIsZero;
                builder.Predictor = TiffPredictor.HorizontalDifferencing;
            }

            builder.Compression            = TiffCompression.Lzw;
            builder.IsTiled                = isTile;
            builder.RowsPerStrip           = 64;
            builder.TileSize               = new TiffSize(64, 64);
            builder.MaxDegreeOfParallelism = maxDegreeOfParallelism;

            var ms = new MemoryStream();

            await GenerateImageAsync(ms, builder, TiffPixelBuffer.WrapReadOnly(refImage, 4096, 4096));

            ms.Seek(0, SeekOrigin.Begin);

            await using TiffFileReader tiff = await TiffFileReader.OpenAsync(ms, leaveOpen : true);

            TiffImageDecoder decoder = await tiff.CreateImageDecoderAsync();

            await decoder.DecodeAsync(TiffPixelBuffer.Wrap(testImage, 4096, 4096));

            Assert.True(refImage.AsSpan().SequenceEqual(testImage.AsSpan()));
        }
コード例 #6
0
        public async Task Setup()
        {
            TiffGray8[] image = new TiffGray8[8192 * 8192];
            _scratchSpace = TiffPixelBuffer.Wrap(image, 8192, 8192);

            var builder = new TiffImageEncoderBuilder();

            builder.PhotometricInterpretation = TiffPhotometricInterpretation.WhiteIsZero;
            builder.Compression = Compression;

            // Generate a image with many strips
            var ms = new MemoryStream();

            builder.IsTiled      = false;
            builder.RowsPerStrip = 256;
            await GenerateImageAsync(ms, builder, _scratchSpace);

            _stripTestTiff = ms.ToArray();

            ms.SetLength(0);

            // Generate a image with many tiles
            builder.IsTiled  = true;
            builder.TileSize = new TiffSize(512, 512);
            await GenerateImageAsync(ms, builder, _scratchSpace);

            _tileTestTiff = ms.ToArray();

            _stripReader = await TiffFileReader.OpenAsync(_stripTestTiff);

            _stripDecoder = await _stripReader.CreateImageDecoderAsync(new TiffImageDecoderOptions { MaxDegreeOfParallelism = DegreeOfParallelism });

            await _stripDecoder.DecodeAsync(_scratchSpace);

            _tileReader = await TiffFileReader.OpenAsync(_tileTestTiff);

            _tileDecoder = await _tileReader.CreateImageDecoderAsync(new TiffImageDecoderOptions { MaxDegreeOfParallelism = DegreeOfParallelism });

            await _tileDecoder.DecodeAsync(_scratchSpace);
        }
コード例 #7
0
        public async Task Setup()
        {
            TiffGray8[] image = new TiffGray8[8192 * 8192];
            _scratchSpace = TiffPixelBuffer.Wrap(image, 8192, 8192);

            var builder = new TiffImageEncoderBuilder();

            builder.PhotometricInterpretation = TiffPhotometricInterpretation.BlackIsZero;
            builder.Compression = TiffCompression.NoCompression;

            // Generate a image with many strips
            var ms = new MemoryStream();

            builder.IsTiled      = false;
            builder.RowsPerStrip = 1;
            await GenerateImageAsync(ms, builder, _scratchSpace);

            _stripTestTiff = ms.ToArray();

            ms.SetLength(0);

            // Generate a image with many tiles
            builder.IsTiled  = true;
            builder.TileSize = new TiffSize(16, 16); // the minimum tile size
            await GenerateImageAsync(ms, builder, _scratchSpace);

            _tileTestTiff = ms.ToArray();

            _stripReader = await TiffFileReader.OpenAsync(_stripTestTiff);

            _stripDecoder = await _stripReader.CreateImageDecoderAsync();

            await _stripDecoder.DecodeAsync(_scratchSpace);

            _tileReader = await TiffFileReader.OpenAsync(_tileTestTiff);

            _tileDecoder = await _tileReader.CreateImageDecoderAsync();

            await _tileDecoder.DecodeAsync(_scratchSpace);
        }
コード例 #8
0
        private async Task <Image <TPixel> > DecodeCoreAsync <TPixel>(TiffFileContentSource contentSource, CancellationToken cancellationToken)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            using TiffFileReader tiff = await TiffFileReader.OpenAsync(contentSource, cancellationToken : cancellationToken).ConfigureAwait(false);

            TiffImageFileDirectory ifd = await tiff.ReadImageFileDirectoryAsync(cancellationToken).ConfigureAwait(false);

            TiffImageDecoder decoder = await tiff.CreateImageDecoderAsync(ifd, _options, cancellationToken).ConfigureAwait(false);

            Image <TPixel>?image = new Image <TPixel>(_configuration, decoder.Width, decoder.Height);

            try
            {
                await decoder.DecodeAsync(image, cancellationToken).ConfigureAwait(false);

                return(Interlocked.Exchange <Image <TPixel>?>(ref image, null) !);
            }
            finally
            {
                image?.Dispose();
            }
        }
コード例 #9
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);
        }