예제 #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 void Test(string reference, string test)
        {
            using var refImage = Image.Load <Rgb24>(reference);

            using var tiff = TiffFileReader.Open(test);

            TiffStreamOffset ifdOffset = tiff.FirstImageFileDirectoryOffset;

            while (!ifdOffset.IsZero)
            {
                TiffImageFileDirectory ifd     = tiff.ReadImageFileDirectory(ifdOffset);
                TiffImageDecoder       decoder = tiff.CreateImageDecoder(ifd, new TiffImageDecoderOptions {
                    UndoColorPreMultiplying = true
                });

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

                decoder.Decode(TiffPixelBuffer.Wrap(pixels, decoder.Width, decoder.Height));

                AssertEqual(refImage, pixels);

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

                ifdOffset = ifd.NextOffset;
            }
        }
예제 #4
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));
        }
예제 #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 void TestMemoryPixelBuffer()
        {
            ITiffPixelBuffer <TiffGray8> pixelBuffer = InitializePixelBuffer(out TiffGray8[] pixels);

            Assert.Equal(3, pixelBuffer.Width);
            Assert.Equal(2, pixelBuffer.Height);
            Span <TiffGray8> span = pixelBuffer.GetSpan();

            Assert.True(Unsafe.AreSame(ref pixels[0], ref span[0]));
            Assert.Equal(6, span.Length);

            span[0] = new TiffGray8(0xCD);
            span[5] = new TiffGray8(0xEF);

            Assert.Equal(0xCD, pixels[0].Intensity);
            Assert.Equal(0xEF, pixels[5].Intensity);

            Assert.Throws <ArgumentOutOfRangeException>("width", () => TiffPixelBuffer.Wrap(Array.Empty <TiffGray8>(), -1, 0));
            Assert.Throws <ArgumentOutOfRangeException>("height", () => TiffPixelBuffer.Wrap(Array.Empty <TiffGray8>(), 0, -1));
        }
예제 #7
0
        public void TestCrop()
        {
            ITiffPixelBuffer <TiffGray8> pixelBuffer  = InitializePixelBuffer(out TiffGray8[] pixels);
            TiffPixelBuffer <TiffGray8>  structBuffer = pixelBuffer.AsPixelBuffer();

            Assert.Equal(3, structBuffer.Width);
            Assert.Equal(2, structBuffer.Height);
            Assert.False(structBuffer.IsEmpty);

            Assert.Throws <ArgumentOutOfRangeException>("offset", () => structBuffer.Crop(new TiffPoint(4, 0)));
            Assert.Throws <ArgumentOutOfRangeException>("offset", () => structBuffer.Crop(new TiffPoint(0, 3)));
            Assert.Throws <ArgumentOutOfRangeException>("offset", () => structBuffer.Crop(new TiffPoint(4, 3)));

            Assert.Throws <ArgumentOutOfRangeException>("size", () => structBuffer.Crop(new TiffPoint(0, 0), new TiffSize(4, 1)));
            Assert.Throws <ArgumentOutOfRangeException>("size", () => structBuffer.Crop(new TiffPoint(0, 0), new TiffSize(1, 3)));
            Assert.Throws <ArgumentOutOfRangeException>("size", () => structBuffer.Crop(new TiffPoint(0, 0), new TiffSize(4, 3)));

            structBuffer = pixelBuffer.Crop(new TiffPoint(1, 1), new TiffSize(1, 1));
            Assert.Equal(1, structBuffer.Width);
            Assert.Equal(1, structBuffer.Height);

            structBuffer = pixelBuffer.AsPixelBuffer().Crop(new TiffPoint(1, 1), new TiffSize(1, 1));
            Assert.Equal(1, structBuffer.Width);
            Assert.Equal(1, structBuffer.Height);

            structBuffer = pixelBuffer.Crop(new TiffPoint(1, 1));
            Assert.Equal(2, structBuffer.Width);
            Assert.Equal(1, structBuffer.Height);

            structBuffer = pixelBuffer.AsPixelBuffer().Crop(new TiffPoint(1, 1));
            Assert.Equal(2, structBuffer.Width);
            Assert.Equal(1, structBuffer.Height);

            ITiffPixelBuffer <TiffGray8> pixelBuffer2 = TiffPixelBufferUnsafeMarshal.GetBuffer(structBuffer, out TiffPoint offset, out TiffSize size);

            Assert.True(ReferenceEquals(pixelBuffer, pixelBuffer2));
            Assert.Equal(1, offset.X);
            Assert.Equal(1, offset.Y);
            Assert.Equal(2, size.Width);
            Assert.Equal(1, size.Height);
        }
예제 #8
0
        public void Setup()
        {
            TiffGray8[] image = new TiffGray8[8192 * 8192];
            _image = TiffPixelBuffer.WrapReadOnly(image, 8192, 8192);

            var builder = new TiffImageEncoderBuilder();

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

            // Strip encoder
            builder.IsTiled      = false;
            builder.RowsPerStrip = 256;
            _stripEncoder        = builder.Build <TiffGray8>();

            // Tile encoder
            builder.IsTiled  = false;
            builder.TileSize = new TiffSize(512, 512);
            _tileEncoder     = builder.Build <TiffGray8>();
        }
예제 #9
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);
        }
        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);
        }
예제 #11
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();
            }
        }