internal static void SaveTiffToWICMemory(PixelBuffer[] pixelBuffers, int count, ImageDescription description, Stream imageStream) { SaveToWICMemory(pixelBuffers, count, WICFlags.AllFrames, ImageFileType.Tiff, imageStream); }
//------------------------------------------------------------------------------------- // Decodes an image array, resizing/format converting as needed //------------------------------------------------------------------------------------- private static Image DecodeMultiframe(WICFlags flags, ImageDescription metadata, BitmapDecoder decoder) { var image = Image.New(metadata); Guid sourceGuid; if (!ToWIC(metadata.Format, out sourceGuid)) { return(null); } for (int index = 0; index < metadata.ArraySize; ++index) { var pixelBuffer = image.PixelBuffer[index, 0]; using (var frame = decoder.GetFrame(index)) { var pfGuid = frame.PixelFormat; var size = frame.Size; if (pfGuid == sourceGuid) { if (size.Width == metadata.Width && size.Height == metadata.Height) { // This frame does not need resized or format converted, just copy... frame.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } else { // This frame needs resizing, but not format converted using (var scaler = new BitmapScaler(Factory)) { scaler.Initialize(frame, metadata.Width, metadata.Height, GetWICInterp(flags)); scaler.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } } } else { // This frame required format conversion using (var converter = new FormatConverter(Factory)) { converter.Initialize(frame, pfGuid, GetWICDither(flags), null, 0, BitmapPaletteType.Custom); if (size.Width == metadata.Width && size.Height == metadata.Height) { converter.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } else { // This frame needs resizing, but not format converted using (var scaler = new BitmapScaler(Factory)) { scaler.Initialize(frame, metadata.Width, metadata.Height, GetWICInterp(flags)); scaler.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } } } } } } return(image); }
/// <summary> /// Initializes a new instance of the <see cref="Image" /> class. /// </summary> /// <param name="description">The image description.</param> /// <param name="dataPointer">The pointer to the data buffer.</param> /// <param name="offset">The offset from the beginning of the data buffer.</param> /// <param name="handle">The handle (optional).</param> /// <param name="bufferIsDisposable">if set to <c>true</c> [buffer is disposable].</param> /// <param name="pitchFlags">The <see cref="PitchFlags"/></param> /// <exception cref="System.InvalidOperationException">If the format is invalid, or width/height/depth/arraysize is invalid with respect to the dimension.</exception> internal unsafe Image(ImageDescription description, IntPtr dataPointer, int offset, GCHandle?handle, bool bufferIsDisposable, PitchFlags pitchFlags = PitchFlags.None) { Initialize(description, dataPointer, offset, handle, bufferIsDisposable, pitchFlags); }
internal unsafe void Initialize(ImageDescription description, IntPtr dataPointer, int offset, GCHandle?handle, bool bufferIsDisposable, PitchFlags pitchFlags = PitchFlags.None) { if (!FormatHelper.IsValid(description.Format) || FormatHelper.IsVideo(description.Format)) { throw new InvalidOperationException("Unsupported DXGI Format"); } this.handle = handle; switch (description.Dimension) { case TextureDimension.Texture1D: if (description.Width <= 0 || description.Height != 1 || description.Depth != 1 || description.ArraySize == 0) { throw new InvalidOperationException("Invalid Width/Height/Depth/ArraySize for Image 1D"); } // Check that miplevels are fine description.MipLevels = Texture.CalculateMipLevels(description.Width, 1, description.MipLevels); break; case TextureDimension.Texture2D: case TextureDimension.TextureCube: if (description.Width <= 0 || description.Height <= 0 || description.Depth != 1 || description.ArraySize == 0) { throw new InvalidOperationException("Invalid Width/Height/Depth/ArraySize for Image 2D"); } if (description.Dimension == TextureDimension.TextureCube) { if ((description.ArraySize % 6) != 0) { throw new InvalidOperationException("TextureCube must have an arraysize = 6"); } } // Check that miplevels are fine description.MipLevels = Texture.CalculateMipLevels(description.Width, description.Height, description.MipLevels); break; case TextureDimension.Texture3D: if (description.Width <= 0 || description.Height <= 0 || description.Depth <= 0 || description.ArraySize != 1) { throw new InvalidOperationException("Invalid Width/Height/Depth/ArraySize for Image 3D"); } // Check that miplevels are fine description.MipLevels = Texture.CalculateMipLevels(description.Width, description.Height, description.Depth, description.MipLevels); break; } // Calculate mipmaps int pixelBufferCount; mipMapToZIndex = CalculateImageArray(description, pitchFlags, out pixelBufferCount, out totalSizeInBytes); mipmapDescriptions = CalculateMipMapDescription(description, pitchFlags); zBufferCountPerArraySlice = mipMapToZIndex[mipMapToZIndex.Count - 1]; // Allocate all pixel buffers pixelBuffers = new PixelBuffer[pixelBufferCount]; pixelBufferArray = new PixelBufferArray(this); // Setup all pointers // only release buffer that is not pinned and is asked to be disposed. this.bufferIsDisposable = !handle.HasValue && bufferIsDisposable; buffer = dataPointer; if (dataPointer == IntPtr.Zero) { buffer = SharpDX.Utilities.AllocateMemory(totalSizeInBytes); offset = 0; this.bufferIsDisposable = true; } SetupImageArray((IntPtr)((byte *)buffer + offset), totalSizeInBytes, description, pitchFlags, pixelBuffers); Description = description; // PreCompute databoxes dataBoxArray = ComputeDataBox(); }
/// <summary> /// Creates a new instance of <see cref="Image"/> from an image description. /// </summary> /// <param name="description">The image description.</param> /// <param name="dataPointer">Pointer to an existing buffer.</param> /// <returns>A new image.</returns> public static Image New(ImageDescription description, IntPtr dataPointer) { return(new Image(description, dataPointer, 0, null, false)); }
/// <summary> /// Creates a new instance of <see cref="Image"/> from an image description. /// </summary> /// <param name="description">The image description.</param> /// <returns>A new image.</returns> public static Image New(ImageDescription description) { return(New(description, IntPtr.Zero)); }