/// <summary> /// Retrieve information about a JPEG image without decompressing it. /// </summary> /// <param name="jpegBuf">A buffer containing a JPEG image.</param> /// <param name="width">An output variable that will receive the width (in pixels) of the JPEG image.</param> /// <param name="height">An output variable that will receive the height (in pixels) of the JPEG image.</param> /// <param name="subsamp">An output variable that will receive the the level of chrominance subsampling used when compressing the JPEG image.</param> /// <param name="colorspace">An output variable that will receive one of the JPEG <see cref="Colorspace"/> constants, indicating the colorspace of the JPEG image.</param> public void DecompressHeader(byte[] jpegBuf, out int width, out int height, out ChrominanceSubsampling subsamp, out Colorspace colorspace) { if (jpegBuf == null) { throw new ArgumentNullException(nameof(jpegBuf)); } Library.tjDecompressHeader3(_handle, jpegBuf, out width, out height, out subsamp, out colorspace); }
/// <summary> /// Compress an RGB or grayscale image into a JPEG image. /// </summary> /// <param name="handle">a handle to a TurboJPEG compressor or transformer instance.</param> /// <param name="srcBuf">pointer to an image buffer containing RGB or grayscale pixels to be compressed.</param> /// <param name="width">width (in pixels) of the source image.</param> /// <param name="pitch"> /// bytes per line of the source image. Normally, this should be /// <paramref name="width"/> * <see cref="PixelFormatExtensions.GetPixelSize"/>(<paramref name="pixelFormat"/>) if the image is unpadded, or /// <see cref="TJPAD"/>(<paramref name="width"/> * <see cref="PixelFormatExtensions.GetPixelSize"/>(<paramref name="pixelFormat"/>)) 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 /// <paramref name="width"/> * <see cref="PixelFormatExtensions.GetPixelSize"/>(<paramref name="pixelFormat"/>). /// </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"/>.).</param> /// <param name="jpegBuf"> /// address of a pointer to an image buffer that will receive the /// JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to /// accommodate the size of the JPEG image. Thus, you can choose to: /// <list type="bullet"> /// <item> /// <description> /// pre-allocate the JPEG buffer with an arbitrary size using /// <see cref="tjAlloc"/> and let TurboJPEG grow the buffer as needed, /// </description> /// </item> /// <item> /// <description> /// set <paramref name="jpegBuf"/> to NULL to tell TurboJPEG to allocate the buffer /// for you, or /// </description> /// </item> /// <item> /// <description> /// pre-allocate the buffer to a "worst case" size determined by calling /// <see cref="tjBufSize"/>. This should ensure that the buffer never has to be /// re-allocated (setting <see cref="FunctionFlags.NoRealloc"/> guarantees this.) /// </description> /// </item> /// </list> /// If you choose option 1, <paramref name="jpegSize"/> should be set to the size of your /// pre-allocated buffer. In any case, unless you have set <see cref="FunctionFlags.NoRealloc"/>, /// you should always check <c>jpegBuf</c> upon return from this function, as /// it may have changed. /// </param> /// <param name="jpegSize"> /// pointer to an unsigned long variable that holds the size of /// the JPEG image buffer. If <paramref name="jpegBuf"/> points to a pre-allocated /// buffer, then <c>jpegSize</c> should be set to the size of the buffer. /// Upon return, <c>jpegSize</c> will contain the size of the JPEG image (in /// bytes.) If <paramref name="jpegBuf"/> points to a JPEG image buffer that is being /// reused from a previous call to one of the JPEG compression functions, then /// <c>jpegSize</c> is ignored. /// </param> /// <param name="jpegSubsamp"> /// the level of chrominance subsampling to be used when /// generating the JPEG image (see <see cref="ChrominanceSubsampling"/>.) /// </param> /// <param name="jpegQual">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="FunctionFlags"/>.</param> /// <exception cref="TurboJPEGException">Thrown if an error occurred.</exception> /// <remarks> /// Defined in turbojpeg.h as: /// /// DLLEXPORT int DLLCALL tjCompress2 (tjhandle handle, const unsigned char* srcBuf, /// int width, int pitch, int height, int pixelFormat, unsigned char** jpegBuf, /// unsigned long* jpegSize, int jpegSubsamp, int jpegQual, int flags); /// </remarks> internal static void tjCompress2(IntPtr handle, byte [] srcBuf, int width, int pitch, int height, PixelFormat pixelFormat, ref IntPtr jpegBuf, ref uint jpegSize, ChrominanceSubsampling jpegSubsamp, int jpegQual, FunctionFlags flags) { int retval; if (IsLP64) { ulong jpegSize64 = jpegSize; retval = tjCompress2_64 (handle, srcBuf, width, pitch, height, pixelFormat, ref jpegBuf, ref jpegSize64, jpegSubsamp, jpegQual, flags); jpegSize = (uint)jpegSize64; } else retval = tjCompress2_32(handle, srcBuf, width, pitch, height, pixelFormat, ref jpegBuf, ref jpegSize, jpegSubsamp, jpegQual, flags); if (retval != 0) throw new TurboJPEGException (); }
public static extern int tjPlaneWidth(int componentID, int width, ChrominanceSubsampling subsamp);
/// <summary> /// The size of the buffer (in bytes) required to hold a YUV image plane with /// the given parameters. /// </summary> /// <param name="componentID">ID number of the image plane (0 = Y, 1 = U/Cb, 2 = V/Cr)</param> /// <param name="width"> /// width (in pixels) of the YUV image. NOTE: this is the width of /// the whole image, not the plane width. /// </param> /// <param name="stride"> /// bytes per line in the image plane. Setting this to 0 is the /// equivalent of setting it to the plane width. /// </param> /// <param name="height"> /// height (in pixels) of the YUV image. NOTE: this is the height /// of the whole image, not the plane height. /// </param> /// <param name="subsamp"> /// level of chrominance subsampling in the image (see /// <see cref="ChrominanceSubsampling"/>.) /// </param> /// <returns>the size of the buffer (in bytes) required to hold the YUV image plane.</returns> /// <exception cref="ArgumentOutOfRangeException">Thrown if one of the arguments is out of bounds.</exception> /// <remarks> /// Defined in turbojpeg.h as: /// /// DLLEXPORT unsigned long DLLCALL tjPlaneSizeYUV(int componentID, int width, /// int stride, int height, int subsamp); /// </remarks> public static ulong tjPlaneSizeYUV( int componentID, int width, int stride, int height, ChrominanceSubsampling subsamp) { if (IsLP64) { ulong retval = tjPlaneSizeYUV_64(componentID, width, stride, height, subsamp); if (retval == ulong.MaxValue) throw new ArgumentOutOfRangeException (); return retval; } else { uint retval = tjPlaneSizeYUV_32(componentID, width, stride, height, subsamp); if (retval == uint.MaxValue) throw new ArgumentOutOfRangeException (); return retval; } }
public static extern int tjPlaneHeight(int componentID, int height, ChrominanceSubsampling subsamp);
/// <summary> /// Compress an RGB, grayscale, or CMYK image into a JPEG image. /// </summary> /// <returns>A byte array containing the compressed JPEG result.</returns> /// <param name="srcBuf">An image buffer containing RGB, grayscale, or CMYK pixels to be compressed.</param> /// <param name="width">Width (in pixels) of the source image.</param> /// <param name="pitch"> /// Bytes per line of the source image. Normally, this should be /// <c>width * format.GetPixelSize()</c> if the image is unpadded, /// or <c><see cref="Library.TJPAD"/>(width * format.GetPixelSize())</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 * format.GetPixelSize()</c>. /// </param> /// <param name="height">Height (in pixels) of the source image.</param> /// <param name="format">Pixel format of the source image.</param> /// <param name="jpegQual">The image quality of the generated JPEG image (1 = worst, 100 = best).</param> /// <param name="jpegSubsamp">The level of chrominance subsampling to be used when generating the JPEG image.</param> /// <param name="bottomUp">If true, then the uncompressed source image is stored in bottom-up (Windows, OpenGL) order, not top-down (X11) order.</param> public byte[] Compress(byte[] srcBuf, int width, int pitch, int height, PixelFormat format, int jpegQual, ChrominanceSubsampling jpegSubsamp = ChrominanceSubsampling.SAMP_420, bool bottomUp = false) { if (srcBuf == null) { throw new ArgumentNullException(nameof(srcBuf)); } IntPtr jpegBuf = IntPtr.Zero; byte[] output; FunctionFlags flags = FunctionFlags.NoRealloc; if (bottomUp) { flags |= FunctionFlags.BottomUp; } try { // Although tjBufSize almost always returns a bigger buffer than we need, // it's better to have extra and only allocate once, instead of incurring // the cost of realloc and a mid compress buffer copy. uint jpegSize = Library.tjBufSize(width, height, jpegSubsamp); if (jpegSize == uint.MaxValue) { throw new Exception(Library.tjGetErrorStr()); } jpegBuf = Library.tjAlloc((int)jpegSize); if (jpegBuf == IntPtr.Zero) { throw new Exception(String.Format("tjAlloc failed to allocate {0} bytes", jpegSize)); } Library.tjCompress2(_handle, srcBuf, width, pitch, height, format, ref jpegBuf, ref jpegSize, jpegSubsamp, jpegQual, flags); output = new byte[jpegSize]; Marshal.Copy(jpegBuf, output, 0, output.Length); } finally { if (jpegBuf != IntPtr.Zero) { Library.tjFree(jpegBuf); } } return(output); }
/// <summary> /// Gets the MCU block width for a given level of chrominance subsampling. /// </summary> /// <returns>The MCU block width, in pixels.</returns> /// <param name="samp">A subsampling level.</param> /// <remarks> /// MCU block sizes: /// * - 8x8 for no subsampling or grayscale /// * - 16x8 for 4:2:2 /// * - 8x16 for 4:4:0 /// * - 16x16 for 4:2:0 /// * - 32x8 for 4:1:1 /// </remarks> public static int GetMCUWidth(this ChrominanceSubsampling samp) { return(MCUWidth[(int)samp]); }
/// <summary> /// Retrieve information about a JPEG image without decompressing it. /// </summary> /// <param name="handle">a handle to a TurboJPEG decompressor or transformer instance.</param> /// <param name="jpegBuf">pointer to a buffer containing a JPEG image.</param> /// <param name="width">an integer variable that will receive the width (in pixels) of the JPEG image.</param> /// <param name="height">an integer variable that will receive the height (in pixels) of the JPEG image.</param> /// <param name="jpegSubsamp"> /// an integer variable that will receive the /// level of chrominance subsampling used when the JPEG image was compressed /// (see <see cref="ChrominanceSubsampling"/> .) /// </param> /// <param name="jpegColorspace"> /// an integer variable that will receive one /// of the JPEG colorspace constants, indicating the colorspace of the JPEG /// image (see <see cref="Colorspace"/>.) /// </param> /// <returns>0 if successful, or -1 if an error occurred (see <see cref="tjGetErrorStr"/>.)</returns> /// <remarks> /// Defined in turbojpeg.h as: /// /// DLLEXPORT int DLLCALL tjDecompressHeader3(tjhandle handle, /// const unsigned char* jpegBuf, unsigned long jpegSize, int* width, /// int* height, int* jpegSubsamp, int* jpegColorspace); /// </remarks> internal static void tjDecompressHeader3(IntPtr handle, byte [] jpegBuf, out int width, out int height, out ChrominanceSubsampling jpegSubsamp, out Colorspace jpegColorspace) { int retval; if (IsLP64) retval = tjDecompressHeader3_64 (handle, jpegBuf, (ulong)jpegBuf.Length, out width, out height, out jpegSubsamp, out jpegColorspace); else retval = tjDecompressHeader3_32 (handle, jpegBuf, (uint)jpegBuf.Length, out width, out height, out jpegSubsamp, out jpegColorspace); if (retval != 0) throw new TurboJPEGException (); }
private static extern int tjCompressFromYUV_64( IntPtr handle, byte [] srcBuf, int width, int pad, int height, ChrominanceSubsampling subsamp, ref IntPtr jpegBuf, ref ulong jpegSize, int jpegQual, FunctionFlags flags);
private static extern int tjCompressFromYUVPlanes_32( IntPtr handle, byte [,] srcPlanes, int width, int [] strides, int height, ChrominanceSubsampling subsamp, ref IntPtr jpegBuf, ref uint jpegSize, int jpegQual, FunctionFlags flags);
private static extern int tjCompress2_64(IntPtr handle, byte [] srcBuf, int width, int pitch, int height, PixelFormat pixelFormat, ref IntPtr jpegBuf, ref ulong jpegSize, ChrominanceSubsampling jpegSubsamp, int jpegQual, FunctionFlags flags);
private static extern ulong tjBufSize_64(int width, int height, ChrominanceSubsampling jpegSubsamp);
private static extern ulong tjBufSizeYUV2_64(int width, int pad, int height, ChrominanceSubsampling subsamp);
/// <summary> /// Retrieve information about a JPEG image without decompressing it. /// </summary> /// <param name="jpegBuf">A buffer containing a JPEG image.</param> /// <param name="width">An output variable that will receive the width (in pixels) of the JPEG image.</param> /// <param name="height">An output variable that will receive the height (in pixels) of the JPEG image.</param> /// <param name="subsamp">An output variable that will receive the the level of chrominance subsampling used when compressing the JPEG image.</param> /// <param name="colorspace">An output variable that will receive one of the JPEG <see cref="Colorspace"/> constants, indicating the colorspace of the JPEG image.</param> public void DecompressHeader(byte[] jpegBuf, out int width, out int height, out ChrominanceSubsampling subsamp, out Colorspace colorspace) { if (jpegBuf == null) throw new ArgumentNullException(nameof (jpegBuf)); Library.tjDecompressHeader3(_handle, jpegBuf, out width, out height, out subsamp, out colorspace); }
/// <summary> /// Compress an RGB, grayscale, or CMYK image into a JPEG image. /// </summary> /// <returns>A byte array containing the compressed JPEG result.</returns> /// <param name="srcBuf">An image buffer containing RGB, grayscale, or CMYK pixels to be compressed.</param> /// <param name="width">Width (in pixels) of the source image.</param> /// <param name="pitch"> /// Bytes per line of the source image. Normally, this should be /// <c>width * format.GetPixelSize()</c> if the image is unpadded, /// or <c><see cref="Library.TJPAD"/>(width * format.GetPixelSize())</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 * format.GetPixelSize()</c>. /// </param> /// <param name="height">Height (in pixels) of the source image.</param> /// <param name="format">Pixel format of the source image.</param> /// <param name="jpegQual">The image quality of the generated JPEG image (1 = worst, 100 = best).</param> /// <param name="jpegSubsamp">The level of chrominance subsampling to be used when generating the JPEG image.</param> /// <param name="bottomUp">If true, then the uncompressed source image is stored in bottom-up (Windows, OpenGL) order, not top-down (X11) order.</param> public byte[] Compress(byte[] srcBuf, int width, int pitch, int height, PixelFormat format, int jpegQual, ChrominanceSubsampling jpegSubsamp = ChrominanceSubsampling.SAMP_420, bool bottomUp = false) { if (srcBuf == null) throw new ArgumentNullException(nameof (srcBuf)); IntPtr jpegBuf = IntPtr.Zero; byte[] output; FunctionFlags flags = FunctionFlags.NoRealloc; if (bottomUp) flags |= FunctionFlags.BottomUp; try { // Although tjBufSize almost always returns a bigger buffer than we need, // it's better to have extra and only allocate once, instead of incurring // the cost of realloc and a mid compress buffer copy. uint jpegSize = Library.tjBufSize(width, height, jpegSubsamp); if (jpegSize == uint.MaxValue) throw new Exception(Library.tjGetErrorStr()); jpegBuf = Library.tjAlloc((int)jpegSize); if (jpegBuf == IntPtr.Zero) throw new Exception(String.Format("tjAlloc failed to allocate {0} bytes", jpegSize)); Library.tjCompress2(_handle, srcBuf, width, pitch, height, format, ref jpegBuf, ref jpegSize, jpegSubsamp, jpegQual, flags); output = new byte[jpegSize]; Marshal.Copy(jpegBuf, output, 0, output.Length); } finally { if (jpegBuf != IntPtr.Zero) Library.tjFree(jpegBuf); } return output; }
/// <summary> /// Compress a set of Y, U (Cb), and V (Cr) image planes into a JPEG image. /// </summary> /// <param name="handle">a handle to a TurboJPEG compressor or transformer instance</param> /// <param name="srcPlanes"> /// an array of pointers to Y, U (Cb), and V (Cr) image planes /// (or just a Y plane, if compressing a grayscale image) that contain a YUV /// image to be compressed. These planes can be contiguous or non-contiguous in /// memory. The size of each plane should match the value returned by /// <see cref="tjPlaneSizeYUV"/> for the given image width, height, strides, and level of /// chrominance subsampling. Refer to @ref YUVnotes "YUV Image Format Notes" /// for more details. /// </param> /// <param name="width"> /// width (in pixels) of the source image. If the width is not an /// even multiple of the MCU block width (see <see cref="ChrominanceSubsamplingExtensions.GetMCUWidth"/>), then an intermediate /// buffer copy will be performed within TurboJPEG. /// </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 /// @ref YUVnotes "YUV Image Format Notes".) If <c>strides</c> is 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 create a JPEG image from a subregion of a larger /// YUV planar image. /// </param> /// <param name="height"> /// height (in pixels) of the source image. If the height is not /// an even multiple of the MCU block height (see <see cref="ChrominanceSubsamplingExtensions.GetMCUHeight"/>), then an /// intermediate buffer copy will be performed within TurboJPEG. /// </param> /// <param name="subsamp"> /// the level of chrominance subsampling used in the source /// image (see <see cref="ChrominanceSubsampling"/>.) /// </param> /// <param name="jpegBuf"> /// address of a pointer to an image buffer that will receive the /// JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to /// accommodate the size of the JPEG image. Thus, you can choose to: /// <list type="bullet"> /// <item> /// <description> /// pre-allocate the JPEG buffer with an arbitrary size using /// <see cref="tjAlloc"/> and let TurboJPEG grow the buffer as needed, /// </description> /// </item> /// <item> /// <description> /// set <paramref name="jpegBuf"/> to NULL to tell TurboJPEG to allocate the buffer /// for you, or /// </description> /// </item> /// <item> /// <description> /// pre-allocate the buffer to a "worst case" size determined by calling /// <see cref="tjBufSize"/>. This should ensure that the buffer never has to be /// re-allocated (setting <see cref="FunctionFlags.NoRealloc"/> guarantees this.) /// </description> /// </item> /// </list> /// If you choose option 1, <paramref name="jpegSize"/> should be set to the size of your /// pre-allocated buffer. In any case, unless you have set <see cref="FunctionFlags.NoRealloc"/>, /// you should always check <c>jpegBuf</c> upon return from this function, as /// it may have changed. /// </param> /// <param name="jpegSize"> /// Pointer to an unsigned long variable that holds the size of /// the JPEG image buffer. If <paramref name="jpegBuf"/> points to a pre-allocated /// buffer, then <c>jpegSize</c> should be set to the size of the buffer. /// Upon return, <c>jpegSize</c> will contain the size of the JPEG image (in /// bytes.) If <paramref name="jpegBuf"/> points to a JPEG image buffer that is being /// reused from a previous call to one of the JPEG compression functions, then /// <c>jpegSize</c> is ignored. /// </param> /// <param name="jpegQual">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="FunctionFlags"/>.</param> /// <exception cref="TurboJPEGException">Thrown if an error occured.</exception> /// <remarks> /// Defined in turbojpeg.h as: /// /// DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle, /// const unsigned char** srcPlanes, int width, const int* strides, int height, /// int subsamp, unsigned char** jpegBuf, unsigned long* jpegSize, int jpegQual, /// int flags); /// </remarks> internal static void tjCompressFromYUVPlanes( IntPtr handle, byte [,] srcPlanes, int width, int [] strides, int height, ChrominanceSubsampling subsamp, ref IntPtr jpegBuf, ref uint jpegSize, int jpegQual, FunctionFlags flags) { int retval; if (IsLP64) { ulong jpegSize64 = jpegSize; retval = tjCompressFromYUVPlanes_64(handle, srcPlanes, width, strides, height, subsamp, ref jpegBuf, ref jpegSize64, jpegQual, flags); jpegSize = (uint)jpegSize64; } else retval = tjCompressFromYUVPlanes_32(handle, srcPlanes, width, strides, height, subsamp, ref jpegBuf, ref jpegSize, jpegQual, flags); if (retval != 0) throw new TurboJPEGException (); }
internal static extern int tjDecodeYUVPlanes( IntPtr handle, byte[,] srcPlanes, int[] strides, ChrominanceSubsampling subsamp, byte[] dstBuf, int width, int pitch, int height, PixelFormat pixelFormat, FunctionFlags flags);
private static extern int tjDecompressHeader3_64(IntPtr handle, byte [] jpegBuf, ulong jpegSize, out int width, out int height, out ChrominanceSubsampling jpegSubsamp, out Colorspace jpegColorspace);
internal static extern int tjEncodeYUV3(IntPtr handle, byte[] srcBuf, int width, int pitch, int height, PixelFormat pixelFormat, IntPtr dstBuf, int pad, ChrominanceSubsampling subsamp, FunctionFlags flags);
private static extern ulong tjPlaneSizeYUV_64( int componentID, int width, int stride, int height, ChrominanceSubsampling subsamp);
/// <summary> /// Gets the MCU block height for a given level of chrominance subsampling. /// </summary> /// <returns>The MCU block height, in pixels.</returns> /// <param name="samp">A subsampling level.</param> /// <remarks> /// MCU block sizes: /// * - 8x8 for no subsampling or grayscale /// * - 16x8 for 4:2:2 /// * - 8x16 for 4:4:0 /// * - 16x16 for 4:2:0 /// * - 32x8 for 4:1:1 /// </remarks> public static int GetMCUHeight(this ChrominanceSubsampling samp) { return(MCUHeight[(int)samp]); }
/// <summary> /// The size of the buffer (in bytes) required to hold a YUV planar image with /// the given parameters. /// </summary> /// <param name="width">width (in pixels) of the image</param> /// <param name="pad"> /// the width of each line in each plane of the image is padded to /// the nearest multiple of this number of bytes (must be a power of 2.) /// </param> /// <param name="height">height (in pixels) of the image</param> /// <param name="subsamp"> /// level of chrominance subsampling in the image (see /// <see cref="ChrominanceSubsampling"/>.) /// </param> /// <returns>the size of the buffer (in bytes) required to hold the image</returns> /// <exception cref="ArgumentOutOfRangeException">Thrown if one of the arguments is out of bounds.</exception> /// <remarks> /// Defined in turbojpeg.h as: /// /// DLLEXPORT unsigned long DLLCALL tjBufSizeYUV2(int width, int pad, int height, /// int subsamp); /// </remarks> public static uint tjBufSizeYUV2(int width, int pad, int height, ChrominanceSubsampling subsamp) { if (IsLP64) { ulong retval = tjBufSizeYUV2_64 (width, pad, height, subsamp); if (retval == ulong.MaxValue) throw new ArgumentOutOfRangeException (); return (uint)retval; } else { uint retval = tjBufSizeYUV2_32 (width, pad, height, subsamp); if (retval == uint.MaxValue) throw new ArgumentOutOfRangeException (); return retval; } }