/// <summary> /// Decode a set of Y, U (Cb), and V (Cr) image planes into an RGB or grayscale image. /// </summary> /// <param name="yPlane"> /// A pointer to the Y image planes of the YUV image to be decoded. /// The size of the plane should match the value returned by tjPlaneSizeYUV() for the given image width, height, strides, and level of chrominance subsampling. /// </param> /// <param name="uPlane"> /// A pointer to the U (Cb) image plane (or just <see langword="null"/>, if decoding a grayscale image) of the YUV image to be decoded. /// The size of the plane should match the value returned by tjPlaneSizeYUV() for the given image width, height, strides, and level of chrominance subsampling. /// </param> /// <param name="vPlane"> /// A pointer to the V (Cr)image plane (or just <see langword="null"/>, if decoding a grayscale image) of the YUV image to be decoded. /// The size of the plane should match the value returned by tjPlaneSizeYUV() for the given image width, height, strides, and level of chrominance subsampling. /// </param> /// <param name="strides"> /// An array of integers, each specifying the number of bytes per line in the corresponding plane of the YUV source image. /// Setting the stride for any plane to 0 is the same as setting it to the plane width (see YUV Image Format Notes.) /// If strides is <see langword="null"/>, then the strides for all planes will be set to their respective plane widths. /// You can adjust the strides in order to specify an arbitrary amount of line padding in each plane or to decode a subregion of a larger YUV planar image. /// </param> /// <param name="subsamp"> /// The level of chrominance subsampling used in the YUV source image (see Chrominance subsampling options.) /// </param> /// <param name="dstBuf"> /// A pointer to an image buffer that will receive the decoded image. This buffer should normally be <paramref name="pitch"/> * <paramref name="height"/> bytes in size, /// but the <paramref name="dstBuf"/> pointer can also be used to decode into a specific region of a larger buffer. /// </param> /// <param name="width"> /// Width (in pixels) of the source and destination images. /// </param> /// <param name="pitch"> /// Bytes per line in the destination image. Normally, this should be <paramref name="width"/> * <c>tjPixelSize[pixelFormat]</c> /// if the destination image is unpadded, or <c>TJPAD(width * tjPixelSize[pixelFormat])</c> if each line of the destination image /// should be padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. You can also be clever and use the /// pitch parameter to skip lines, etc. /// Setting this parameter to <c>0</c> is the equivalent of setting it to <paramref name="width"/> * <c>tjPixelSize[pixelFormat]</c>. /// </param> /// <param name="height"> /// Height (in pixels) of the source and destination images. /// </param> /// <param name="pixelFormat"> /// Pixel format of the destination image. /// </param> /// <param name="flags"> /// The bitwise OR of one or more of the flags. /// </param> /// <remarks> /// <para> /// This function uses the accelerated color conversion routines in the underlying codec but does not execute any of the other steps in the JPEG decompression process. /// </para> /// <para> /// The <paramref name="yPlane"/>, <paramref name="uPlane"/> and <paramref name="vPlane"/> planes can be contiguous or non-contiguous in memory. /// Refer to YUV Image Format Notes for more details. /// </para> /// </remarks> public unsafe void DecodeYUVPlanes( Span <byte> yPlane, Span <byte> uPlane, Span <byte> vPlane, int[] strides, TJSubsamplingOption subsamp, Span <byte> dstBuf, int width, int pitch, int height, TJPixelFormat pixelFormat, TJFlags flags) { if (this.isDisposed) { throw new ObjectDisposedException(nameof(TJDecompressor)); } fixed(byte *yPlanePtr = yPlane) fixed(byte *uPlanePtr = uPlane) fixed(byte *vPlanePtr = vPlane) { byte *[] planes = new byte *[] { yPlanePtr, uPlanePtr, vPlanePtr }; fixed(int *stridesPtr = strides) fixed(byte **planesPtr = planes) fixed(byte *dstBufPtr = dstBuf) { if (TurboJpegImport.TjDecodeYUVPlanes( this.decompressorHandle, planesPtr, stridesPtr, (int)subsamp, (IntPtr)dstBufPtr, width, pitch, height, (int)pixelFormat, (int)flags) == -1) { TJUtils.GetErrorAndThrow(); } } } }