/// <summary> /// Decompress a JPEG image to an RGB, grayscale, or CMYK image. /// </summary> /// <param name="jpegBuf">Pointer to a buffer containing the JPEG image to decompress. This buffer is not modified.</param> /// <param name="outBuf">The buffer into which to store the decompressed JPEG image.</param> /// <param name="destPixelFormat">Pixel format of the destination image (see <see cref="PixelFormat"/> "Pixel formats".)</param> /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param> /// <param name="width">Width of image in pixels.</param> /// <param name="height">Height of image in pixels.</param> /// <param name="stride">Bytes per line in the destination image.</param> public unsafe void Decompress(Span <byte> jpegBuf, Span <byte> outBuf, TJPixelFormat destPixelFormat, TJFlags flags, out int width, out int height, out int stride) { fixed(byte *jpegBufPtr = jpegBuf) fixed(byte *outBufPtr = outBuf) { this.Decompress((IntPtr)jpegBufPtr, (ulong)jpegBuf.Length, (IntPtr)outBufPtr, outBuf.Length, destPixelFormat, flags, out width, out height, out stride); } }
/// <summary> /// Retrieve information about a JPEG image without decompressing it. /// </summary> /// <param name="jpegBuf"> /// Pointer to a buffer containing a JPEG image. This buffer is not modified. /// </param> /// <param name="jpegBufSize"> /// Size of the JPEG image (in bytes). /// </param> /// <param name="destPixelFormat"> /// The pixel format of the uncompressed image. /// </param> /// <param name="width"> /// Pointer to an integer variable that will receive the width (in pixels) of the JPEG image. /// </param> /// <param name="height"> /// Pointer to an integer variable that will receive the height (in pixels) of the JPEG image. /// </param> /// <param name="stride"> /// Pointer to an integer variable that will receive the stride (in bytes) of the JPEG image. /// </param> /// <param name="bufSize"> /// The size of a buffer that can receive the uncompressed JPEG image. /// </param> public unsafe void GetImageInfo(ReadOnlySpan <byte> jpegBuf, TJPixelFormat destPixelFormat, out int width, out int height, out int stride, out int bufSize) { fixed(byte *jpegBufPtr = jpegBuf) { this.GetImageInfo((IntPtr)jpegBufPtr, (ulong)jpegBuf.Length, destPixelFormat, out width, out height, out stride, out bufSize); } }
/// <summary> /// Given the size of an image, determines the size of a decompressed image. /// </summary> /// <param name="height"> /// The height of the image. /// </param> /// <param name="width"> /// The width of the image. /// </param> /// <param name="destPixelFormat"> /// The pixel format of the uncompressed image. /// </param> /// <returns> /// The size of a buffer that can hold the uncompressed image. /// </returns> public int GetBufferSize(int height, int width, TJPixelFormat destPixelFormat) { Verify.NotDisposed(this); int stride = TurboJpegImport.TJPAD(width * TurboJpegImport.PixelSizes[destPixelFormat]); return(stride * height); }
/// <summary> /// Initializes a new instance of the <see cref="DecompressedImage"/> class. /// </summary> /// <param name="width">Width of image in pixels.</param> /// <param name="height">Height of image in pixels.</param> /// <param name="stride"> /// Bytes per line in the source image. /// Normally, this should be <c>width * BytesPerPixel</c> if the image is unpadded, /// or <c>TJPAD(width * BytesPerPixel</c> if each line of the image /// is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. /// You can also be clever and use this parameter to skip lines, etc. /// Setting this parameter to 0 is the equivalent of setting it to /// <c>width * BytesPerPixel</c>.</param> /// <param name="data">Decompressed Image array containing RGB, grayscale, or CMYK pixels.</param> /// <param name="pixelFormat">Pixel format of the source image (see <see cref="PixelFormat"/> "Pixel formats").</param> public DecompressedImage(int width, int height, int stride, byte[] data, TJPixelFormat pixelFormat) { this.Width = width; this.Height = height; this.Stride = stride; this.Data = data; this.PixelFormat = pixelFormat; }
/// <summary> /// Decompress a JPEG image to an RGB, grayscale, or CMYK image. /// </summary> /// <param name="jpegBuf">A buffer containing the JPEG image to decompress. This buffer is not modified.</param> /// <param name="jpegBufSize">Size of jpegBuf.</param> /// <param name="destPixelFormat">Pixel format of the destination image (see <see cref="PixelFormat"/> "Pixel formats".)</param> /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param> /// <returns>Decompressed Image.</returns> /// <exception cref="TJException">Throws if underlying decompress function failed.</exception> /// <exception cref="ObjectDisposedException">Object is disposed and can not be used anymore.</exception> public DecompressedImage Decompress(IntPtr jpegBuf, ulong jpegBufSize, TJPixelFormat destPixelFormat, TJFlags flags) { if (this.isDisposed) { throw new ObjectDisposedException("this"); } int width; int height; int stride; byte[] data = this.Decompress(jpegBuf, jpegBufSize, destPixelFormat, flags, out width, out height, out stride); return(new DecompressedImage(width, height, stride, data, destPixelFormat)); }
/// <summary> /// Decompress a JPEG image to an RGB, grayscale, or CMYK image. /// </summary> /// <param name="jpegBuf">A buffer containing the JPEG image to decompress. This buffer is not modified.</param> /// <param name="destPixelFormat">Pixel format of the destination image (see <see cref="PixelFormat"/> "Pixel formats".)</param> /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param> /// <returns>Decompressed Image.</returns> /// <exception cref="TJException">Throws if underlying decompress function failed.</exception> /// <exception cref="ObjectDisposedException">Object is disposed and can not be used anymore.</exception> public unsafe DecompressedImage Decompress(byte[] jpegBuf, TJPixelFormat destPixelFormat, TJFlags flags) { if (this.isDisposed) { throw new ObjectDisposedException("this"); } ulong length = (ulong)jpegBuf.Length; fixed(byte *numPtr = jpegBuf) { return(this.Decompress((IntPtr)((void *)numPtr), length, destPixelFormat, flags)); } }
/// <summary> /// Decompress a JPEG image to an RGB, grayscale, or CMYK image. /// </summary> /// <param name="jpegBuf">A buffer containing the JPEG image to decompress. This buffer is not modified.</param> /// <param name="destPixelFormat">Pixel format of the destination image (see <see cref="TJPixelFormat"/> "Pixel formats".)</param> /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param> /// <param name="width">Width of image in pixels.</param> /// <param name="height">Height of image in pixels.</param> /// <param name="stride">Bytes per line in the destination image.</param> /// <returns>Raw pixel data of specified format.</returns> /// <exception cref="TJException">Throws if underlying decompress function failed.</exception> /// <exception cref="ObjectDisposedException">Object is disposed and can not be used anymore.</exception> public unsafe byte[] Decompress(byte[] jpegBuf, TJPixelFormat destPixelFormat, TJFlags flags, out int width, out int height, out int stride) { if (this.isDisposed) { throw new ObjectDisposedException("this"); } var jpegBufSize = (ulong)jpegBuf.Length; fixed(byte *jpegPtr = jpegBuf) { return(this.Decompress((IntPtr)jpegPtr, jpegBufSize, destPixelFormat, flags, out width, out height, out stride)); } }
/// <summary> /// Decompress a JPEG image to an RGB, grayscale, or CMYK image. /// </summary> /// <param name="jpegBuf">Buffer containing the JPEG image to decompress. This buffer is not modified.</param> /// <param name="destPixelFormat">Pixel format of the destination image (see <see cref="TJPixelFormat"/> "Pixel formats".)</param> /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param> /// <param name="width">Width of image in pixels.</param> /// <param name="height">Height of image in pixels.</param> /// <param name="stride">Bytes per line in the destination image.</param> public unsafe byte[] Decompress(ReadOnlySpan <byte> jpegBuf, TJPixelFormat destPixelFormat, TJFlags flags, out int width, out int height, out int stride) { this.GetImageInfo(jpegBuf, destPixelFormat, out width, out height, out stride, out var outBufSize); var outBuf = new byte[outBufSize]; fixed(byte *jpegBufPtr = jpegBuf) fixed(byte *outBufPtr = outBuf) { this.Decompress((IntPtr)jpegBufPtr, (ulong)jpegBuf.Length, (IntPtr)outBufPtr, outBuf.Length, destPixelFormat, flags, out width, out height, out stride); } return(outBuf); }
/// <summary> /// Decompress a JPEG image to an RGB, grayscale, or CMYK image. /// </summary> /// <param name="jpegBuf">Pointer to a buffer containing the JPEG image to decompress. This buffer is not modified.</param> /// <param name="jpegBufSize">Size of the JPEG image (in bytes).</param> /// <param name="destPixelFormat">Pixel format of the destination image (see <see cref="TJPixelFormat"/> "Pixel formats".)</param> /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param> /// <param name="width">Width of image in pixels.</param> /// <param name="height">Height of image in pixels.</param> /// <param name="stride">Bytes per line in the destination image.</param> /// <returns>Raw pixel data of specified format.</returns> /// <exception cref="TJException">Throws if underlying decompress function failed.</exception> /// <exception cref="ObjectDisposedException">Object is disposed and can not be used anymore.</exception> public unsafe byte[] Decompress(IntPtr jpegBuf, ulong jpegBufSize, TJPixelFormat destPixelFormat, TJFlags flags, out int width, out int height, out int stride) { int outBufSize; this.GetImageInfo(jpegBuf, jpegBufSize, destPixelFormat, out width, out height, out stride, out outBufSize); var buf = new byte[outBufSize]; fixed(byte *bufPtr = buf) { this.Decompress(jpegBuf, jpegBufSize, (IntPtr)bufPtr, outBufSize, destPixelFormat, flags, out width, out height, out stride); } return(buf); }
public void DecompressArray( [CombinatorialValues( TJPixelFormat.ABGR, TJPixelFormat.RGB, TJPixelFormat.Gray)] TJPixelFormat format) { byte[] outBuf = ArrayPool <byte> .Shared.Rent(250 * 250 * 4); foreach (var data in TestUtils.GetTestImagesData("*.jpg")) { this.decompressor.Decompress(data.Item2, outBuf, format, TJFlags.None, out int width, out int height, out int stride); } ArrayPool <byte> .Shared.Return(outBuf); }
/// <summary> /// Retrieve information about a JPEG image without decompressing it. /// </summary> /// <param name="jpegBuf"> /// Pointer to a buffer containing a JPEG image. This buffer is not modified. /// </param> /// <param name="jpegBufSize"> /// Size of the JPEG image (in bytes). /// </param> /// <param name="destPixelFormat"> /// The pixel format of the uncompressed image. /// </param> /// <param name="width"> /// Pointer to an integer variable that will receive the width (in pixels) of the JPEG image. /// </param> /// <param name="height"> /// Pointer to an integer variable that will receive the height (in pixels) of the JPEG image. /// </param> /// <param name="stride"> /// Pointer to an integer variable that will receive the stride (in bytes) of the JPEG image. /// </param> /// <param name="bufSize"> /// The size of a buffer that can receive the uncompressed JPEG image. /// </param> public void GetImageInfo(IntPtr jpegBuf, ulong jpegBufSize, TJPixelFormat destPixelFormat, out int width, out int height, out int stride, out int bufSize) { int subsampl; int colorspace; var funcResult = TurboJpegImport.TjDecompressHeader( this.decompressorHandle, jpegBuf, jpegBufSize, out width, out height, out subsampl, out colorspace); stride = TurboJpegImport.TJPAD(width * TurboJpegImport.PixelSizes[destPixelFormat]); bufSize = stride * height; }
/// <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(); } } } }
/// <summary> /// Decompress a JPEG image to an RGB, grayscale, or CMYK image. /// </summary> /// <param name="jpegBuf">Pointer to a buffer containing the JPEG image to decompress. This buffer is not modified.</param> /// <param name="outBuf">The buffer into which to store the decompressed JPEG image.</param> /// <param name="destPixelFormat">Pixel format of the destination image (see <see cref="TJPixelFormat"/> "Pixel formats".)</param> /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param> /// <param name="width">Width of image in pixels.</param> /// <param name="height">Height of image in pixels.</param> /// <param name="stride">Bytes per line in the destination image.</param> public unsafe void Decompress(Span <byte> jpegBuf, Span <byte> outBuf, TJPixelFormat destPixelFormat, TJFlags flags, out int width, out int height, out int stride) { Verify.NotDisposed(this); fixed(byte *jpegBufPtr = jpegBuf) fixed(byte *outBufPtr = outBuf) { int subsampl; int colorspace; var funcResult = TurboJpegImport.TjDecompressHeader( this.decompressorHandle, jpegBufPtr, (nuint)jpegBuf.Length, out width, out height, out subsampl, out colorspace); TJUtils.ThrowOnError(funcResult); var targetFormat = destPixelFormat; stride = TurboJpegImport.TJPAD(width * TurboJpegImport.PixelSizes[targetFormat]); var bufSize = stride * height; if (outBuf.Length < bufSize) { throw new ArgumentOutOfRangeException(nameof(outBuf)); } funcResult = TurboJpegImport.TjDecompress( this.decompressorHandle, jpegBufPtr, (nuint)jpegBuf.Length, outBufPtr, width, stride, height, (int)targetFormat, (int)flags); TJUtils.ThrowOnError(funcResult); } }
/// <summary> /// Compresses input image to the jpeg format with specified quality. /// </summary> /// <param name="srcPtr"> /// Pointer to an image buffer containing RGB, grayscale, or CMYK pixels to be compressed. /// This buffer is not modified. /// </param> /// <param name="stride"> /// Bytes per line in the source image. /// Normally, this should be <c>width * BytesPerPixel</c> if the image is unpadded, /// or <c>TJPAD(width * BytesPerPixel</c> if each line of the image /// is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. /// You can also be clever and use this parameter to skip lines, etc. /// Setting this parameter to 0 is the equivalent of setting it to /// <c>width * BytesPerPixel</c>. /// </param> /// <param name="width">Width (in pixels) of the source image.</param> /// <param name="height">Height (in pixels) of the source image.</param> /// <param name="tjPixelFormat">Pixel format of the source image (see <see cref="TJPixelFormat"/> "Pixel formats").</param> /// <param name="subSamp"> /// The level of chrominance subsampling to be used when /// generating the JPEG image (see <see cref="TJSubsamplingOption"/> "Chrominance subsampling options".) /// </param> /// <param name="quality">The image quality of the generated JPEG image (1 = worst, 100 = best).</param> /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param> /// <returns> /// A <see cref="byte"/> array containing the compressed image. /// </returns> /// <exception cref="TJException"> Throws if compress function failed. </exception> /// <exception cref="ObjectDisposedException">Object is disposed and can not be used anymore.</exception> /// <exception cref="NotSupportedException"> /// Some parameters' values are incompatible: /// <list type="bullet"> /// <item><description>Subsampling not equals to <see cref="TJSubsamplingOption.Gray"/> and pixel format <see cref="TJPixelFormat.Gray"/></description></item> /// </list> /// </exception> public byte[] Compress(IntPtr srcPtr, int stride, int width, int height, TJPixelFormat tjPixelFormat, TJSubsamplingOption subSamp, int quality, TJFlags flags) { if (this.isDisposed) { throw new ObjectDisposedException("this"); } CheckOptionsCompatibilityAndThrow(subSamp, tjPixelFormat); var buf = IntPtr.Zero; ulong bufSize = 0; try { var result = TurboJpegImport.TjCompress2( this.compressorHandle, srcPtr, width, stride, height, (int)tjPixelFormat, ref buf, ref bufSize, (int)subSamp, quality, (int)flags); if (result == -1) { TJUtils.GetErrorAndThrow(); } var jpegBuf = new byte[bufSize]; Marshal.Copy(buf, jpegBuf, 0, (int)bufSize); return(jpegBuf); } finally { TurboJpegImport.TjFree(buf); } }
/// <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) { Verify.NotDisposed(this); 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) { TJUtils.ThrowOnError( TurboJpegImport.TjDecodeYUVPlanes( this.decompressorHandle, planesPtr, stridesPtr, (int)subsamp, (IntPtr)dstBufPtr, width, pitch, height, (int)pixelFormat, (int)flags)); } } }
/// <summary> /// Retrieve information about a JPEG image without decompressing it. /// </summary> /// <param name="jpegBuf"> /// Pointer to a buffer containing a JPEG image. This buffer is not modified. /// </param> /// <param name="destPixelFormat"> /// The pixel format of the uncompressed image. /// </param> /// <param name="width"> /// Pointer to an integer variable that will receive the width (in pixels) of the JPEG image. /// </param> /// <param name="height"> /// Pointer to an integer variable that will receive the height (in pixels) of the JPEG image. /// </param> /// <param name="stride"> /// Pointer to an integer variable that will receive the stride (in bytes) of the JPEG image. /// </param> /// <param name="bufSize"> /// The size of a buffer that can receive the uncompressed JPEG image. /// </param> public void GetImageInfo(Span <byte> jpegBuf, TJPixelFormat destPixelFormat, out int width, out int height, out int stride, out int bufSize) { Verify.NotDisposed(this); int subsampl; int colorspace; fixed(byte *jpegBufPtr = jpegBuf) { var funcResult = TurboJpegImport.TjDecompressHeader( this.decompressorHandle, jpegBufPtr, (nuint)jpegBuf.Length, out width, out height, out subsampl, out colorspace); stride = TurboJpegImport.TJPAD(width * TurboJpegImport.PixelSizes[destPixelFormat]); bufSize = stride * height; } }
/// <summary> /// Compresses input image to the jpeg format with specified quality. /// </summary> /// <param name="srcBuf"> /// Image buffer containing RGB, grayscale, or CMYK pixels to be compressed. /// This buffer is not modified. /// </param> /// <param name="destBuf"> /// A <see cref="byte"/> array containing the compressed image. /// </param> /// <param name="stride"> /// Bytes per line in the source image. /// Normally, this should be <c>width * BytesPerPixel</c> if the image is unpadded, /// or <c>TJPAD(width * BytesPerPixel</c> if each line of the image /// is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. /// You can also be clever and use this parameter to skip lines, etc. /// Setting this parameter to 0 is the equivalent of setting it to /// <c>width * BytesPerPixel</c>. /// </param> /// <param name="width">Width (in pixels) of the source image.</param> /// <param name="height">Height (in pixels) of the source image.</param> /// <param name="pixelFormat">Pixel format of the source image (see <see cref="TJPixelFormat"/> "Pixel formats").</param> /// <param name="subSamp"> /// The level of chrominance subsampling to be used when /// generating the JPEG image (see <see cref="TJSubsamplingOption"/> "Chrominance subsampling options".) /// </param> /// <param name="quality">The image quality of the generated JPEG image (1 = worst, 100 = best).</param> /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param> /// <returns> /// A <see cref="Span{T}"/> which is a slice of <paramref name="destBuf"/> which holds the compressed image. /// </returns> /// <exception cref="TJException"> /// Throws if compress function failed. /// </exception> /// <exception cref="ObjectDisposedException">Object is disposed and can not be used anymore.</exception> /// <exception cref="NotSupportedException"> /// Some parameters' values are incompatible: /// <list type="bullet"> /// <item><description>Subsampling not equals to <see cref="TJSubsamplingOption.Gray"/> and pixel format <see cref="TJPixelFormat.Gray"/></description></item> /// </list> /// </exception> public unsafe Span <byte> Compress(Span <byte> srcBuf, Span <byte> destBuf, int stride, int width, int height, TJPixelFormat pixelFormat, TJSubsamplingOption subSamp, int quality, TJFlags flags) { Verify.NotDisposed(this); CheckOptionsCompatibilityAndThrow(subSamp, pixelFormat); ulong destBufSize = (ulong)destBuf.Length; fixed(byte *srcBufPtr = srcBuf) fixed(byte *destBufPtr = destBuf) { IntPtr destBufPtr2 = (IntPtr)destBufPtr; var result = TurboJpegImport.TjCompress2( this.compressorHandle, (IntPtr)srcBufPtr, width, stride, height, (int)pixelFormat, ref destBufPtr2, ref destBufSize, (int)subSamp, quality, (int)flags); TJUtils.ThrowOnError(result); } return(destBuf.Slice(0, (int)destBufSize)); }
/// <exception cref="NotSupportedException"> /// Some parameters' values are incompatible: /// <list type="bullet"> /// <item><description>Subsampling not equals to <see cref="TJSubsamplingOption.Gray"/> and pixel format <see cref="TJPixelFormat.Gray"/></description></item> /// </list> /// </exception> private static void CheckOptionsCompatibilityAndThrow(TJSubsamplingOption subSamp, TJPixelFormat srcFormat) { if (srcFormat == TJPixelFormat.Gray && subSamp != TJSubsamplingOption.Gray) { throw new NotSupportedException( $"Subsampling differ from {TJSubsamplingOption.Gray} for pixel format {TJPixelFormat.Gray} is not supported"); } }
/// <summary> /// Decompress a JPEG image to an RGB, grayscale, or CMYK image. /// </summary> /// <param name="jpegBuf">Pointer to a buffer containing the JPEG image to decompress. This buffer is not modified.</param> /// <param name="jpegBufSize">Size of the JPEG image (in bytes).</param> /// <param name="outBuf">The buffer into which to store the decompressed JPEG image.</param> /// <param name="outBufSize">Size of <paramref name="outBuf"/> (in bytes).</param> /// <param name="destPixelFormat">Pixel format of the destination image (see <see cref="TJPixelFormat"/> "Pixel formats".)</param> /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param> /// <param name="width">Width of image in pixels.</param> /// <param name="height">Height of image in pixels.</param> /// <param name="stride">Bytes per line in the destination image.</param> public unsafe void Decompress(IntPtr jpegBuf, ulong jpegBufSize, IntPtr outBuf, int outBufSize, TJPixelFormat destPixelFormat, TJFlags flags, out int width, out int height, out int stride) { if (this.isDisposed) { throw new ObjectDisposedException("this"); } int subsampl; int colorspace; var funcResult = TurboJpegImport.TjDecompressHeader( this.decompressorHandle, jpegBuf, jpegBufSize, out width, out height, out subsampl, out colorspace); if (funcResult == -1) { TJUtils.GetErrorAndThrow(); } var targetFormat = destPixelFormat; stride = TurboJpegImport.TJPAD(width * TurboJpegImport.PixelSizes[targetFormat]); var bufSize = stride * height; if (outBufSize < bufSize) { throw new ArgumentOutOfRangeException(nameof(outBufSize)); } funcResult = TurboJpegImport.TjDecompress( this.decompressorHandle, jpegBuf, jpegBufSize, outBuf, width, stride, height, (int)targetFormat, (int)flags); if (funcResult == -1) { TJUtils.GetErrorAndThrow(); } }
/// <summary> /// Compresses input image to the jpeg format with specified quality. /// </summary> /// <param name="srcBuf"> /// Image buffer containing RGB, grayscale, or CMYK pixels to be compressed. /// This buffer is not modified. /// </param> /// <param name="destBuf"> /// A <see cref="byte"/> array containing the compressed image. /// </param> /// <param name="stride"> /// Bytes per line in the source image. /// Normally, this should be <c>width * BytesPerPixel</c> if the image is unpadded, /// or <c>TJPAD(width * BytesPerPixel</c> if each line of the image /// is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. /// You can also be clever and use this parameter to skip lines, etc. /// Setting this parameter to 0 is the equivalent of setting it to /// <c>width * BytesPerPixel</c>. /// </param> /// <param name="width">Width (in pixels) of the source image.</param> /// <param name="height">Height (in pixels) of the source image.</param> /// <param name="pixelFormat">Pixel format of the source image (see <see cref="PixelFormat"/> "Pixel formats").</param> /// <param name="subSamp"> /// The level of chrominance subsampling to be used when /// generating the JPEG image (see <see cref="TJSubsamplingOption"/> "Chrominance subsampling options".) /// </param> /// <param name="quality">The image quality of the generated JPEG image (1 = worst, 100 = best).</param> /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param> /// <returns> /// A <see cref="Span{T}"/> which is a slice of <paramref name="destBuf"/> which holds the compressed image. /// </returns> /// <exception cref="TJException"> /// Throws if compress function failed. /// </exception> /// <exception cref="ObjectDisposedException">Object is disposed and can not be used anymore.</exception> /// <exception cref="NotSupportedException"> /// Some parameters' values are incompatible: /// <list type="bullet"> /// <item><description>Subsampling not equals to <see cref="TJSubsamplingOption.Gray"/> and pixel format <see cref="TJPixelFormat.Gray"/></description></item> /// </list> /// </exception> public unsafe Span <byte> Compress(Span <byte> srcBuf, Span <byte> destBuf, int stride, int width, int height, TJPixelFormat pixelFormat, TJSubsamplingOption subSamp, int quality, TJFlags flags) { if (this.isDisposed) { throw new ObjectDisposedException(nameof(TJCompressor)); } CheckOptionsCompatibilityAndThrow(subSamp, pixelFormat); ulong destBufSize = (ulong)destBuf.Length; fixed(byte *srcBufPtr = srcBuf) fixed(byte *destBufPtr = destBuf) { IntPtr destBufPtr2 = (IntPtr)destBufPtr; var result = TurboJpegImport.TjCompress2( this.compressorHandle, (IntPtr)srcBufPtr, width, stride, height, (int)pixelFormat, ref destBufPtr2, ref destBufSize, (int)subSamp, quality, (int)flags); if (result == -1) { TJUtils.GetErrorAndThrow(); } } return(destBuf.Slice(0, (int)destBufSize)); }