public ValueTask ReadAsync(TiffPoint offset, TiffPixelBufferWriter <TDestination> destination, CancellationToken cancellationToken) { ITiffPixelBufferWriter <TDestination> destinationWriter = TiffPixelBufferUnsafeMarshal.GetBuffer(destination, out TiffPoint destinationOffset, out TiffSize size); TiffPixelBufferWriter <TSource> newDestination = new TiffPassthroughPixelBufferWriter <TSource, TDestination>(destinationWriter).AsPixelBufferWriter().Crop(destinationOffset, size); return(_source.ReadAsync(offset, newDestination, cancellationToken)); }
public ValueTask ReadAsync(TiffPoint offset, TiffPixelBufferWriter <TTiffPixel> destination, CancellationToken cancellationToken) { ITiffPixelBufferWriter <TTiffPixel> destinationWriter = TiffPixelBufferUnsafeMarshal.GetBuffer(destination, out TiffPoint destinationOffset, out TiffSize size); TiffPixelBufferWriter <TImageSharpPixel> newDestination = new ImageSharpConversionPixelBufferWriter <TImageSharpPixel, TIntermediate, TTiffPixel>(destinationWriter).AsPixelBufferWriter().Crop(destinationOffset, size); return(_source.ReadAsync(offset, newDestination, cancellationToken)); }
/// <summary> /// Crop a sub region from <paramref name="writer"/>. /// </summary> /// <typeparam name="TPixel">The pixel type.</typeparam> /// <param name="writer">The original pixel buffer.</param> /// <param name="offset">The number of columns and rows to skip.</param> /// <param name="size">The number of columns and rows to take.</param> /// <returns>A <see cref="TiffPixelBuffer{TPixel}"/> representing the cropped region.</returns> public static TiffPixelBufferWriter <TPixel> Crop <TPixel>(this ITiffPixelBufferWriter <TPixel> writer, TiffPoint offset, TiffSize size) where TPixel : unmanaged { if (writer is TiffPixelBufferWriter <TPixel> structWriter) { return(structWriter.Crop(offset, size)); } return(writer.AsPixelBufferWriter().Crop(offset, size)); }
/// <summary> /// Wraps <paramref name="writer"/> in <see cref="TiffPixelBufferWriter{TPixel}"/> structure. /// </summary> /// <typeparam name="TPixel">The pixel type.</typeparam> /// <param name="writer">The pixel buffer writer.</param> /// <returns>A <see cref="TiffPixelBufferWriter{TPixel}"/> wrapping <paramref name="writer"/>.</returns> public static TiffPixelBufferWriter <TPixel> AsPixelBufferWriter <TPixel>(this ITiffPixelBufferWriter <TPixel> writer) where TPixel : unmanaged { if (writer is TiffPixelBufferWriter <TPixel> structWriter) { return(structWriter); } return(new TiffPixelBufferWriter <TPixel>(writer)); }
public void TestCrop() { ITiffPixelBuffer <TiffGray8> pixelBuffer = PixelBufferTests.InitializePixelBuffer(out TiffGray8[] pixels); var writer = new TiffPixelBufferWriterAdapter <TiffGray8>(pixelBuffer); TiffPixelBufferWriter <TiffGray8> structWriter = writer.AsPixelBufferWriter(); Assert.Equal(3, structWriter.Width); Assert.Equal(2, structWriter.Height); Assert.False(structWriter.IsEmpty); Assert.Throws <ArgumentOutOfRangeException>("offset", () => structWriter.Crop(new TiffPoint(4, 0))); Assert.Throws <ArgumentOutOfRangeException>("offset", () => structWriter.Crop(new TiffPoint(0, 3))); Assert.Throws <ArgumentOutOfRangeException>("offset", () => structWriter.Crop(new TiffPoint(4, 3))); Assert.Throws <ArgumentOutOfRangeException>("size", () => structWriter.Crop(new TiffPoint(0, 0), new TiffSize(4, 1))); Assert.Throws <ArgumentOutOfRangeException>("size", () => structWriter.Crop(new TiffPoint(0, 0), new TiffSize(1, 3))); Assert.Throws <ArgumentOutOfRangeException>("size", () => structWriter.Crop(new TiffPoint(0, 0), new TiffSize(4, 3))); structWriter = writer.Crop(new TiffPoint(1, 1), new TiffSize(1, 1)); Assert.Equal(1, structWriter.Width); Assert.Equal(1, structWriter.Height); structWriter = writer.AsPixelBufferWriter().Crop(new TiffPoint(1, 1), new TiffSize(1, 1)); Assert.Equal(1, structWriter.Width); Assert.Equal(1, structWriter.Height); structWriter = writer.Crop(new TiffPoint(1, 1)); Assert.Equal(2, structWriter.Width); Assert.Equal(1, structWriter.Height); structWriter = writer.AsPixelBufferWriter().Crop(new TiffPoint(1, 1)); Assert.Equal(2, structWriter.Width); Assert.Equal(1, structWriter.Height); Assert.Throws <ArgumentOutOfRangeException>("rowIndex", () => structWriter.GetRowSpan(-1, 0, 1)); Assert.Throws <ArgumentOutOfRangeException>("rowIndex", () => structWriter.GetRowSpan(2, 0, 1)); Assert.Throws <ArgumentOutOfRangeException>("start", () => structWriter.GetRowSpan(0, -1, 1)); Assert.Throws <ArgumentOutOfRangeException>("start", () => structWriter.GetRowSpan(0, 3, 1)); Assert.Throws <ArgumentOutOfRangeException>("length", () => structWriter.GetRowSpan(0, 1, -1)); Assert.Throws <ArgumentOutOfRangeException>("length", () => structWriter.GetRowSpan(0, 1, 2)); Assert.Throws <ArgumentOutOfRangeException>("colIndex", () => structWriter.GetColumnSpan(-1, 0, 1)); Assert.Throws <ArgumentOutOfRangeException>("colIndex", () => structWriter.GetColumnSpan(2, 0, 1)); Assert.Throws <ArgumentOutOfRangeException>("start", () => structWriter.GetColumnSpan(0, -1, 1)); Assert.Throws <ArgumentOutOfRangeException>("start", () => structWriter.GetColumnSpan(0, 2, 1)); Assert.Throws <ArgumentOutOfRangeException>("length", () => structWriter.GetColumnSpan(0, 1, -1)); Assert.Throws <ArgumentOutOfRangeException>("length", () => structWriter.GetColumnSpan(0, 1, 2)); ITiffPixelBufferWriter <TiffGray8> writer2 = TiffPixelBufferUnsafeMarshal.GetBuffer(structWriter, out TiffPoint offset, out TiffSize size); Assert.True(ReferenceEquals(writer, writer2)); Assert.Equal(1, offset.X); Assert.Equal(1, offset.Y); Assert.Equal(2, size.Width); Assert.Equal(1, size.Height); }
public TiffCombinedPixelConverter(ITiffPixelBufferWriter <TDestination> writer, ITiffPixelSpanConverter <TSource, TIntermediate> converter1, ITiffPixelSpanConverter <TIntermediate, TDestination> converter2, bool allowInPlaceConvert = true) : base(writer, allowInPlaceConvert && Unsafe.SizeOf <TSource>() == Unsafe.SizeOf <TIntermediate>()) { _converter1 = converter1 ?? throw new ArgumentNullException(nameof(converter1)); _converter2 = converter2 ?? throw new ArgumentNullException(nameof(converter2)); _canInPlaceConvert = allowInPlaceConvert && Unsafe.SizeOf <TSource>() == Unsafe.SizeOf <TIntermediate>() && Unsafe.SizeOf <TIntermediate>() == Unsafe.SizeOf <TDestination>(); // Temparary buffer _writer = ArrayPool <byte> .Shared.Rent(writer.Width *Unsafe.SizeOf <TIntermediate>()); }
/// <summary> /// A function to get destination buffer in the specified pixel format. /// </summary> public sealed override TiffPixelBufferWriter <TPixel> GetWriter <TPixel>() { ITiffPixelConverterFactory?pixelConverterFactory = PixelConverterFactory; if (pixelConverterFactory is null) { throw new InvalidOperationException("Failed to acquire PixelConverterFactory"); } ITiffPixelBufferWriter <TDestinationPixel> buffer = TiffPixelBufferUnsafeMarshal.GetBuffer(DestinationWriter, out TiffPoint offset, out TiffSize size); return(pixelConverterFactory.CreateConverter <TPixel, TDestinationPixel>(buffer).Crop(offset, size)); }
/// <summary> /// Converts pixel buffer writer of any pixel format <typeparamref name="TBuffer"/> into <see cref="TiffPixelBufferWriter{TPixel}"/>. /// </summary> /// <typeparam name="TBuffer">The specified pixel type.</typeparam> /// <param name="writer">The writer to be converted.</param> /// <returns>The converted writer.</returns> public override TiffPixelBufferWriter <TPixel> ConvertWriter <TBuffer>(TiffPixelBufferWriter <TBuffer> writer) { ITiffPixelConverterFactory?pixelConverterFactory = PixelConverterFactory; if (pixelConverterFactory is null) { throw new InvalidOperationException("Failed to acquire PixelConverterFactory"); } ITiffPixelBufferWriter <TBuffer> innerWriter = TiffPixelBufferUnsafeMarshal.GetBuffer(writer, out TiffPoint offset, out TiffSize size); ITiffPixelBufferWriter <TPixel> converted = pixelConverterFactory.CreateConverter <TPixel, TBuffer>(innerWriter); return(converted.Crop(offset, size)); }
/// <summary> /// Wraps a <see cref="ITiffPixelBufferWriter{TPixel}"/> and creates <see cref="TiffNoopDisposablePixelBufferWriter{TPixel}"/>. /// </summary> /// <typeparam name="TPixel">The pixel type.</typeparam> /// <param name="writer">The writer to wrap.</param> /// <returns></returns> public static ITiffPixelBufferWriter <TPixel> Wrap <TPixel>(ITiffPixelBufferWriter <TPixel> writer) where TPixel : unmanaged { if (writer is null) { throw new ArgumentNullException(nameof(writer)); } if (writer is TiffNoopDisposablePixelBufferWriter <TPixel> noopWriter) { return(noopWriter); } return(new TiffNoopDisposablePixelBufferWriter <TPixel>(writer)); }
/// <summary> /// Initialize <see cref="TiffPixelBufferWriter{TPixel}"/> to wrap <paramref name="writer"/> and represents the same region as <paramref name="writer"/>. /// </summary> /// <param name="writer">The pixel buffer writer. If <paramref name="writer"/> is null, <see cref="TiffPixelBufferWriter{TPixel}"/> will be empty and represents an emtry 2-dimensional region.</param> public TiffPixelBufferWriter(ITiffPixelBufferWriter <TPixel> writer) { _writer = writer ?? TiffEmptyPixelBufferWriter <TPixel> .Default; if (_writer is TiffPixelBufferWriter <TPixel> structWriter) { _writer = structWriter._writer; _offset = structWriter._offset; _size = structWriter._size; } else { _offset = default; _size = new TiffSize(_writer.Width, _writer.Height); } }
#pragma warning disable CA1816 // CA1816: Call GC.SuppressFinalize correctly /// <inheritdoc /> public void Dispose() #pragma warning restore CA1816 // CA1816: Call GC.SuppressFinalize correctly { if (!(_cachedHandle is null)) { _cachedHandle.ReleaseBuffer(); } _cachedHandle = null; if (!(_writer is null)) { _writer.Dispose(); } _writer = null; }
/// <summary> /// Create <see cref="TiffPixelConverter{TSource, TDestination}"/> and wraps <paramref name="writer"/>. /// </summary> /// <typeparam name="TSource">The pixel format to convert from.</typeparam> /// <typeparam name="TDestination">The pixel format to convert to.</typeparam> /// <param name="writer">The writer to be wrapped.</param> /// <returns>The created <see cref="TiffPixelConverter{TSource, TDestination}"/>.</returns> public ITiffPixelBufferWriter <TSource> CreateConverter <TSource, TDestination>(ITiffPixelBufferWriter <TDestination> writer) where TSource : unmanaged where TDestination : unmanaged { if (writer is null) { throw new ArgumentNullException(nameof(writer)); } if (typeof(TSource) == typeof(TDestination)) { return(Unsafe.As <ITiffPixelBufferWriter <TSource> >(writer)); } ITiffPixelConverterFactory?factory = DefaultPixelConverterFactoryCache <TSource, TDestination> .Factory; if (factory != null) { return(factory.CreateConverter <TSource, TDestination>(writer)); } foreach (ConverterFactoryDescriptor item in DefaultPixelConverterFactoryList.Factories) { if (item.SourceType == typeof(TSource) && item.DestinationType == typeof(TDestination)) { factory = item.ConverterFactory; } } if (factory is null) { throw new InvalidOperationException($"No converter from {typeof(TSource).FullName} to {typeof(TDestination).FullName} is found."); } ITiffPixelBufferWriter <TSource> converter = factory.CreateConverter <TSource, TDestination>(writer); if (converter != null) { DefaultPixelConverterFactoryCache <TSource, TDestination> .Factory = factory; return(converter); } throw new InvalidOperationException($"No converter from {typeof(TSource).FullName} to {typeof(TDestination).FullName} is found."); }
public TiffGray8ToRgb24PixelConverter(ITiffPixelBufferWriter <TiffRgb24> writer) : base(writer) { }
public TiffGray8ToGray8ReversedPixelConverter(ITiffPixelBufferWriter <TiffGray8Reversed> writer) : base(writer) { }
public TiffBgra64ToGray16PixelConverter(ITiffPixelBufferWriter <TiffGray16> writer) : base(writer) { }
public TiffCmyk32ToBgra32PixelConverter(ITiffPixelBufferWriter <TiffBgra32> writer) : base(writer) { }
public TiffGray16ToCmyk64PixelConverter(ITiffPixelBufferWriter <TiffCmyk64> writer) : base(writer) { }
/// <inheritdoc /> public override void Decode <TPixel>(TiffPoint offset, TiffSize readSize, TiffPoint destinationOffset, ITiffPixelBufferWriter <TPixel> writer) { if (writer is null) { throw new ArgumentNullException(nameof(writer)); } readSize = new TiffSize(Math.Max(0, Math.Min(writer.Width - destinationOffset.X, readSize.Width)), Math.Max(0, Math.Min(writer.Height - destinationOffset.Y, readSize.Height))); readSize = new TiffSize(Math.Max(0, Math.Min(Width - offset.X, readSize.Width)), Math.Max(0, Math.Min(Height - offset.Y, readSize.Height))); if (readSize.IsAreaEmpty) { return; } if (_parameters.ContentSource is null) { throw new InvalidOperationException("Failed to acquire ContentSource."); } using TiffFileContentReader reader = TiffSyncFileContentSource.WrapReader(_parameters.ContentSource.OpenReader()); var context = new TiffDefaultImageDecoderContext <TPixel>() { MemoryPool = _parameters.MemoryPool ?? MemoryPool <byte> .Shared, CancellationToken = CancellationToken.None, OperationContext = _parameters.OperationContext, ContentReader = reader, SourceImageSize = _parameters.ImageSize, SourceReadOffset = offset, ReadSize = readSize, PixelConverterFactory = _parameters.PixelConverterFactory ?? TiffDefaultPixelConverterFactory.Instance, DestinationWriter = new TiffPixelBufferWriter <TPixel>(TiffNoopDisposablePixelBufferWriter.Wrap(writer)).Crop(destinationOffset, readSize) }; _pipeline.RunAsync(context).AsTask().GetAwaiter().GetResult(); }
public TiffCmyk64ToCmyk32PixelConverter(ITiffPixelBufferWriter <TiffCmyk32> writer) : base(writer) { }
public TiffBgr24ToRgba32PixelConverter(ITiffPixelBufferWriter <TiffRgba32> writer) : base(writer) { }
internal TiffPixelBufferWriter(ITiffPixelBufferWriter <TPixel> writer, TiffPoint offset, TiffSize size) { _writer = writer; _offset = offset; _size = size; }
public TiffRgba64ToBgr24PixelConverter(ITiffPixelBufferWriter <TiffBgr24> writer) : base(writer) { }
/// <summary> /// Wraps <paramref name="writer"/> as the underlying storage. /// </summary> /// <param name="writer">The wrapped writer.</param> /// <param name="allowInPlaceConvert">If the size of two pixel formats are the same, set this flag to allow conversion to happen on the same buffer without allocating temporary buffer.</param> public TiffPixelConverter(ITiffPixelBufferWriter <TDestination> writer, bool allowInPlaceConvert) { _writer = writer ?? throw new ArgumentNullException(nameof(writer)); _canInPlaceConvert = allowInPlaceConvert && Unsafe.SizeOf <TSource>() == Unsafe.SizeOf <TDestination>(); }
/// <summary> /// Wraps <paramref name="writer"/> as the underlying storage. /// </summary> /// <param name="writer">The wrapped writer.</param> public TiffPixelConverter(ITiffPixelBufferWriter <TDestination> writer) : this(writer, allowInPlaceConvert : Unsafe.SizeOf <TSource>() == Unsafe.SizeOf <TDestination>()) { }
public ITiffPixelBufferWriter <TSource> CreateConverter <TSource, TDestination>(ITiffPixelBufferWriter <TDestination> buffer) where TSource : unmanaged where TDestination : unmanaged { if (typeof(TSource) != typeof(TiffCmyk64) || typeof(TDestination) != typeof(TiffCmyk32)) { throw new InvalidOperationException(); } return(Unsafe.As <ITiffPixelBufferWriter <TSource> >(new TiffCmyk64ToCmyk32PixelConverter(Unsafe.As <ITiffPixelBufferWriter <TiffCmyk32> >(buffer)))); }
public TiffMaskToGray8PixelConverter(ITiffPixelBufferWriter <TiffGray8> writer) : base(writer) { }
public TiffRgba32ToRgba64PixelConverter(ITiffPixelBufferWriter <TiffRgba64> writer) : base(writer) { }
public ITiffPixelBufferWriter <TSource> CreateConverter <TSource, TDestination>(ITiffPixelBufferWriter <TDestination> buffer) where TSource : unmanaged where TDestination : unmanaged { if (typeof(TSource) != typeof(TiffMask) || typeof(TDestination) != typeof(TiffGray8)) { throw new InvalidOperationException(); } return(Unsafe.As <ITiffPixelBufferWriter <TSource> >(new TiffPassthroughPixelBufferWriter <TiffMask, TiffGray8>(Unsafe.As <ITiffPixelBufferWriter <TiffGray8> >(buffer)))); }
/// <inheritdoc /> public override async Task DecodeAsync <TPixel>(TiffPoint offset, TiffSize readSize, TiffPoint destinationOffset, ITiffPixelBufferWriter <TPixel> writer, CancellationToken cancellationToken = default) { if (writer is null) { throw new ArgumentNullException(nameof(writer)); } readSize = new TiffSize(Math.Max(0, Math.Min(writer.Width - destinationOffset.X, readSize.Width)), Math.Max(0, Math.Min(writer.Height - destinationOffset.Y, readSize.Height))); readSize = new TiffSize(Math.Max(0, Math.Min(Width - offset.X, readSize.Width)), Math.Max(0, Math.Min(Height - offset.Y, readSize.Height))); if (readSize.IsAreaEmpty) { return; } if (_parameters.ContentSource is null) { throw new InvalidOperationException("Failed to acquire ContentSource."); } TiffFileContentReader reader = await _parameters.ContentSource.OpenReaderAsync(cancellationToken).ConfigureAwait(false); try { var context = new TiffDefaultImageDecoderContext <TPixel>() { MemoryPool = _parameters.MemoryPool ?? MemoryPool <byte> .Shared, CancellationToken = cancellationToken, OperationContext = _parameters.OperationContext, ContentReader = reader, SourceImageSize = _parameters.ImageSize, SourceReadOffset = offset, ReadSize = readSize, PixelConverterFactory = _parameters.PixelConverterFactory ?? TiffDefaultPixelConverterFactory.Instance, DestinationWriter = new TiffPixelBufferWriter <TPixel>(TiffNoopDisposablePixelBufferWriter.Wrap(writer)).Crop(destinationOffset, readSize) }; await _pipeline.RunAsync(context).ConfigureAwait(false); } finally { await reader.DisposeAsync().ConfigureAwait(false); } }
public TiffCmyk64ToBgra64PixelConverter(ITiffPixelBufferWriter <TiffBgra64> writer) : base(writer) { }