Ejemplo n.º 1
0
        /// <summary>
        /// Compresses input image to the jpeg format with specified quality
        /// </summary>
        /// <param name="srcImage"> Source image to be converted </param>
        /// <param name="subSamp">
        /// The level of chrominance subsampling to be used when
        /// generating the JPEG image (see <see cref="TJSubsamplingOptions"/> "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>
        /// <remarks>Only <see cref="PixelFormat.Format24bppRgb"/>, <see cref="PixelFormat.Format32bppArgb"/>, <see cref="PixelFormat.Format8bppIndexed"/> pixel formats are supported</remarks>
        /// <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="TJSubsamplingOptions.TJSAMP_GRAY"/> and pixel format <see cref="TJPixelFormats.TJPF_GRAY"/></description></item>
        /// </list>
        /// </exception>
        public byte[] Compress(Bitmap srcImage, TJSubsamplingOptions subSamp, int quality, TJFlags flags)
        {
            if (_isDisposed)
                throw new ObjectDisposedException("this");

            var pixelFormat = srcImage.PixelFormat;

            var width = srcImage.Width;
            var height = srcImage.Height;
            // ReSharper disable once ExceptionNotDocumented
            var srcData = srcImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, pixelFormat);

            var stride = srcData.Stride;
            var srcPtr = srcData.Scan0;

            try
            {
                return Compress(srcPtr, stride, width, height, pixelFormat, subSamp, quality, flags);

            }
            finally
            {
                // ReSharper disable once ExceptionNotDocumented
                srcImage.UnlockBits(srcData);
            }
        }
Ejemplo n.º 2
0
        /// <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="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="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 static byte[] Compress(this TJCompressor @this, IntPtr srcPtr, int stride, int width, int height, PixelFormat pixelFormat,
                                      TJSubsamplingOption subSamp, int quality, TJFlags flags)
        {
            _ = @this ?? throw new ArgumentNullException(nameof(@this));
            var tjPixelFormat = TJGdiPlusUtils.ConvertPixelFormat(pixelFormat);

            return(@this.Compress(srcPtr, stride, width, height, tjPixelFormat, subSamp, quality, flags));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Compress a set of Y, U (Cb), and V (Cr) image planes into a JPEG 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="width">
        /// The width (in pixels) of the source image. If the width is not an even multiple of the MCU block width (see tjMCUWidth), 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 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="height">
        /// The height (in pixels) of the source image. If the height is not an even multiple of the MCU block height (see tjMCUHeight), 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 Chrominance subsampling options.)
        /// </param>
        /// <param name="jpegBuf">
        /// 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="number">
        ///   <item>
        ///      pre-allocate the JPEG buffer with an arbitrary size using <see cref="TJUtils.Alloc"/> and let TurboJPEG grow the buffer as needed,
        ///   </item>
        ///   <item>
        ///     set* jpegBuf to NULL to tell TurboJPEG to allocate the buffer for you, or
        ///   </item>
        ///   <item>
        ///     pre-allocate the buffer to a "worst case" size determined by calling tjBufSize(). This should ensure that the buffer never has to be re-allocated(setting TJFLAG_NOREALLOC guarantees that it won't be.)
        ///   </item>
        /// </list>
        /// If you choose option 1, * jpegSize should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check *jpegBuf upon return from this function, as it may have changed.
        /// </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 flags.
        /// </param>
        /// <returns>
        /// A <see cref="Span{byte}"/> which holds the compressed image.
        /// </returns>
        public unsafe Span <byte> CompressFromYUVPlanes(
            Span <byte> yPlane,
            Span <byte> uPlane,
            Span <byte> vPlane,
            int width,
            int[] strides,
            int height,
            TJSubsamplingOption subsamp,
            Span <byte> jpegBuf,
            int jpegQual,
            TJFlags flags)
        {
            if (this.isDisposed)
            {
                throw new ObjectDisposedException(nameof(TJCompressor));
            }

            uint   destBufSize = (uint)jpegBuf.Length;
            IntPtr jpegBufPtr2 = IntPtr.Zero;

            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 *jpegBufPtr = jpegBuf)
                fixed(byte **planesPtr = planes)
                {
                    jpegBufPtr2 = (IntPtr)jpegBufPtr;

                    var result = TurboJpegImport.TjCompressFromYUVPlanes(
                        this.compressorHandle,
                        planesPtr,
                        width,
                        stridesPtr,
                        height,
                        (int)subsamp,
                        ref jpegBufPtr2,
                        ref destBufSize,
                        jpegQual,
                        (int)flags);

                    if (result == -1)
                    {
                        TJUtils.GetErrorAndThrow();
                    }
                }
            }

            return(new Span <byte>(jpegBufPtr2.ToPointer(), (int)destBufSize));
        }
Ejemplo n.º 4
0
        /// <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 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>
        /// <exception cref="NotSupportedException">Convertion to the requested pixel format can not be performed</exception>
        public unsafe Bitmap Decompress(byte[] jpegBuf, PixelFormat destPixelFormat, TJFlags flags)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("this");
            }

            var jpegBufSize = (ulong)jpegBuf.Length;

            fixed(byte *jpegPtr = jpegBuf)
            {
                return(Decompress((IntPtr)jpegPtr, jpegBufSize, destPixelFormat, flags));
            }
        }
        /// <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="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>
        /// <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, TJPixelFormats 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;
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Compress a set of Y, U (Cb), and V (Cr) image planes into a JPEG 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 <see cref="PlaneSizeYUV"/> 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 <see cref="PlaneSizeYUV"/> 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 <see cref="PlaneSizeYUV"/> for the given image width, height, strides, and level of chrominance subsampling.
        /// </param>
        /// <param name="width">
        /// The width (in pixels) of the source image. If the width is not an even multiple of the MCU block width (see tjMCUWidth), 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 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="height">
        /// The height (in pixels) of the source image. If the height is not an even multiple of the MCU block height (see tjMCUHeight), 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 Chrominance subsampling options.)
        /// </param>
        /// <param name="jpegBuf">
        /// 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="number">
        ///   <item>
        ///      pre-allocate the JPEG buffer with an arbitrary size using <see cref="TurboJpegImport.TjAlloc"/> and let TurboJPEG grow the buffer as needed,
        ///   </item>
        ///   <item>
        ///     set* jpegBuf to NULL to tell TurboJPEG to allocate the buffer for you, or
        ///   </item>
        ///   <item>
        ///     pre-allocate the buffer to a "worst case" size determined by calling tjBufSize(). This should ensure that the buffer never has to be re-allocated(setting TJFLAG_NOREALLOC guarantees that it won't be.)
        ///   </item>
        /// </list>
        /// If you choose option 1, * jpegSize should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check *jpegBuf upon return from this function, as it may have changed.
        /// </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 flags.
        /// </param>
        /// <returns>
        /// A <see cref="Span{T}"/> which holds the compressed image.
        /// </returns>
        public unsafe Span <byte> CompressFromYUVPlanes(
            Span <byte> yPlane,
            Span <byte> uPlane,
            Span <byte> vPlane,
            int width,
            int[] strides,
            int height,
            TJSubsamplingOption subsamp,
            Span <byte> jpegBuf,
            int jpegQual,
            TJFlags flags)
        {
            Verify.NotDisposed(this);

            nuint  destBufSize = (nuint)jpegBuf.Length;
            IntPtr jpegBufPtr2 = IntPtr.Zero;

            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 *jpegBufPtr = jpegBuf)
                fixed(byte **planesPtr = planes)
                {
                    jpegBufPtr2 = (IntPtr)jpegBufPtr;

                    var result = TurboJpegImport.TjCompressFromYUVPlanes(
                        this.compressorHandle,
                        planesPtr,
                        width,
                        stridesPtr,
                        height,
                        (int)subsamp,
                        ref jpegBufPtr2,
                        ref destBufSize,
                        jpegQual,
                        (int)flags);

                    TJUtils.ThrowOnError(result);
                }
            }

            return(new Span <byte>(jpegBufPtr2.ToPointer(), (int)destBufSize));
        }
Ejemplo n.º 7
0
        /// <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();
                    }
                }
            }
        }
Ejemplo n.º 8
0
        public static byte[] Recompress(
            ReadOnlySpan <byte> jpegBytes,
            int quality = 70,
            TJSubsamplingOption subsampling = TJSubsamplingOption.Chrominance420,
            TJFlags flags = TJFlags.None)
        {
            var pixelFormat = TJPixelFormat.BGRA;

            using var decr = new TJDecompressor();
            var raw = decr.Decompress(jpegBytes, pixelFormat, flags, out var width, out var height, out var stride);

            decr.Dispose();

            using var compr = new TJCompressor();
            var compressed = compr.Compress(raw, stride, width, height, pixelFormat, subsampling, quality, flags);

            return(compressed);
        }
Ejemplo n.º 9
0
        /// <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));
                }
            }
        }
        public unsafe void Decompress(IntPtr jpegBuf, ulong jpegBufSize, IntPtr outBuf, int outBufSize, TJPixelFormats destPixelFormat, TJFlags flags, out int width, out int height, out int stride)
        {
            if (_isDisposed)
                throw new ObjectDisposedException("this");

            int subsampl;
            int colorspace;
            var funcResult = TurboJpegImport.tjDecompressHeader(_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(
                _decompressorHandle,
                jpegBuf,
                jpegBufSize,
                outBuf,
                width,
                stride,
                height,
                (int)targetFormat,
                (int)flags);

            if (funcResult == -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="jpegBufSize">Size of the JPEG image (in bytes)</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 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>
        /// <exception cref="NotSupportedException">Convertion to the requested pixel format can not be performed</exception>
        public unsafe Bitmap Decompress(IntPtr jpegBuf, ulong jpegBufSize, PixelFormat destPixelFormat, TJFlags flags)
        {
            if (_isDisposed)
                throw new ObjectDisposedException("this");

            var targetFormat = TJUtils.ConvertPixelFormat(destPixelFormat);
            int width;
            int height;
            int stride;
            var buffer = Decompress(jpegBuf, jpegBufSize, targetFormat, flags, out width, out height, out stride);
            Bitmap result;
            fixed (byte* bufferPtr = buffer)
            {
                result = new Bitmap(width, height, stride, destPixelFormat, (IntPtr)bufferPtr);
                if (destPixelFormat == PixelFormat.Format8bppIndexed)
                {
                    result.Palette = FixPaletteToGrayscale(result.Palette);
                }
            }
            return result;
        }
Ejemplo n.º 12
0
        /// <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="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>
        /// <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, TJPixelFormats 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);
        }
Ejemplo n.º 13
0
        /// <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="PixelFormat"/> "Pixel formats".)</param>
        /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags"</param>
        /// <returns>Decompressed image 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>
        /// <exception cref="NotSupportedException">Convertion to the requested pixel format can not be performed</exception>
        public unsafe Bitmap Decompress(IntPtr jpegBuf, ulong jpegBufSize, PixelFormat destPixelFormat, TJFlags flags)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("this");
            }

            var    targetFormat = TJUtils.ConvertPixelFormat(destPixelFormat);
            int    width;
            int    height;
            int    stride;
            var    buffer = Decompress(jpegBuf, jpegBufSize, targetFormat, flags, out width, out height, out stride);
            Bitmap result;

            fixed(byte *bufferPtr = buffer)
            {
                result = new Bitmap(width, height, stride, destPixelFormat, (IntPtr)bufferPtr);
                if (destPixelFormat == PixelFormat.Format8bppIndexed)
                {
                    result.Palette = FixPaletteToGrayscale(result.Palette);
                }
            }

            return(result);
        }
Ejemplo n.º 14
0
        /// <summary>Transforms input image into one or several destinations.</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="transforms">Array of transform descriptions to be applied to the source image. </param>
        /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param>
        /// <returns>Array of transformed jpeg images.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="transforms"/> is <see langword="null" />.</exception>
        /// <exception cref="ArgumentException">Transforms can not be empty.</exception>
        /// <exception cref="TJException"> Throws if low level turbo jpeg function fails. </exception>
        public byte[][] Transform(IntPtr jpegBuf, ulong jpegBufSize, TJTransformDescription[] transforms, TJFlags flags)
        {
            if (transforms == null)
            {
                throw new ArgumentNullException(nameof(transforms));
            }

            if (transforms.Length == 0)
            {
                throw new ArgumentException("Transforms can not be empty", nameof(transforms));
            }

            // ReSharper disable once ExceptionNotDocumented
            var count     = transforms.Length;
            var destBufs  = new IntPtr[count];
            var destSizes = new ulong[count];

            int subsampl;
            int colorspace;
            int width;
            int height;
            var funcResult = TurboJpegImport.TjDecompressHeader(
                this.transformHandle,
                jpegBuf,
                jpegBufSize,
                out width,
                out height,
                out subsampl,
                out colorspace);

            if (funcResult == -1)
            {
                TJUtils.GetErrorAndThrow();
            }

            TjSize tjSize;

            if (!TurboJpegImport.MCUSizes.TryGetValue((TJSubsamplingOption)subsampl, out tjSize))
            {
                throw new TJException("Unable to read Subsampling Options from jpeg header");
            }

            var tjTransforms = new TjTransform[count];

            for (var i = 0; i < count; i++)
            {
                var x = CorrectRegionCoordinate(transforms[i].Region.X, tjSize.Width);
                var y = CorrectRegionCoordinate(transforms[i].Region.Y, tjSize.Height);
                var w = CorrectRegionSize(transforms[i].Region.X, x, transforms[i].Region.W, width);
                var h = CorrectRegionSize(transforms[i].Region.Y, y, transforms[i].Region.H, height);

                tjTransforms[i] = new TjTransform
                {
                    Op      = (int)transforms[i].Operation,
                    Options = (int)transforms[i].Options,
                    R       = new TJRegion
                    {
                        X = x,
                        Y = y,
                        W = w,
                        H = h,
                    },
                    Data         = transforms[i].CallbackData,
                    CustomFilter = transforms[i].CustomFilter,
                };
            }

            var transformsPtr = TJUtils.StructArrayToIntPtr(tjTransforms);

            try
            {
                funcResult = TurboJpegImport.TjTransform(
                    this.transformHandle,
                    jpegBuf,
                    jpegBufSize,
                    count,
                    destBufs,
                    destSizes,
                    transformsPtr,
                    (int)flags);

                if (funcResult == -1)
                {
                    TJUtils.GetErrorAndThrow();
                }

                var result = new List <byte[]>();
                for (var i = 0; i < destBufs.Length; i++)
                {
                    var ptr  = destBufs[i];
                    var size = destSizes[i];
                    var item = new byte[size];
                    Marshal.Copy(ptr, item, 0, (int)size);
                    result.Add(item);

                    TurboJpegImport.TjFree(ptr);
                }

                return(result.ToArray());
            }
            finally
            {
                TJUtils.FreePtr(transformsPtr);
            }
        }
Ejemplo n.º 15
0
        /// <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));
        }
        /// <summary>Transforms input image into one or several destinations</summary>
        /// <param name="jpegBuf">A buffer containing the JPEG image to decompress. This buffer is not modified</param>
        /// <param name="transforms">Array of transform descriptions to be applied to the source image </param>
        /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags"</param>
        /// <returns>Array of transformed jpeg images</returns>
        /// <exception cref="ArgumentNullException"><paramref name="transforms"/> is <see langword="null" />.</exception>
        /// <exception cref="ArgumentException">Transforms can not be empty</exception>
        /// <exception cref="TJException"> Throws if low level turbo jpeg function fails </exception>
        public unsafe byte[][] Transform(byte[] jpegBuf, TJTransformDescription[] transforms, TJFlags flags)
        {
            if (transforms == null)
                throw new ArgumentNullException("transforms");
            if (transforms.Length == 0)
                throw new ArgumentException("Transforms can not be empty", "transforms");

            fixed (byte* jpegPtr = jpegBuf)
            {
                return Transform((IntPtr)jpegPtr, (ulong)jpegBuf.Length, transforms, flags);
            }
        }
Ejemplo n.º 17
0
        /// <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 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>
        /// <exception cref="NotSupportedException">Convertion to the requested pixel format can not be performed.</exception>
        public static unsafe Bitmap Decompress(this TJDecompressor @this, byte[] jpegBuf, PixelFormat destPixelFormat, TJFlags flags)
        {
            var jpegBufSize = (ulong)jpegBuf.Length;

            fixed(byte *jpegPtr = jpegBuf)
            {
                return(@this.Decompress((IntPtr)jpegPtr, jpegBufSize, destPixelFormat, flags));
            }
        }
Ejemplo n.º 18
0
        /// <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="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="TJSubsamplingOptions"/> "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>
        /// <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="TJSubsamplingOptions.TJSAMP_GRAY"/> and pixel format <see cref="TJPixelFormats.TJPF_GRAY"/></description></item>
        /// </list>
        /// </exception>
        public unsafe byte[] Compress(byte[] srcBuf, int stride, int width, int height, PixelFormat pixelFormat, TJSubsamplingOptions subSamp, int quality, TJFlags flags)
        {
            if (_isDisposed)
                throw new ObjectDisposedException("this");

            var tjPixelFormat = TJUtils.ConvertPixelFormat(pixelFormat);
            CheckOptionsCompatibilityAndThrow(subSamp, tjPixelFormat);
            
            var buf = IntPtr.Zero;
            ulong bufSize = 0;
            try
            {
                fixed (byte* srcBufPtr = srcBuf)
                {
                    var result = TurboJpegImport.tjCompress2(
                        _compressorHandle,
                        (IntPtr)srcBufPtr,
                        width,
                        stride,
                        height,
                        (int)tjPixelFormat,
                        ref buf,
                        ref bufSize,
                        (int)subSamp,
                        quality,
                        (int)flags);
                    if (result == -1)
                    {
                        TJUtils.GetErrorAndThrow();
                    }
                }

                var jpegBuf = new byte[bufSize];
                // ReSharper disable once ExceptionNotDocumentedOptional
                Marshal.Copy(buf, jpegBuf, 0, (int)bufSize);
                return jpegBuf;
            }
            finally
            {
                TurboJpegImport.tjFree(buf);
            }
        }
        /// <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>
        /// <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, TJPixelFormats destPixelFormat, TJFlags flags, out int width, out int height, out int stride)
        {
            if (_isDisposed)
                throw new ObjectDisposedException("this");

            var jpegBufSize = (ulong)jpegBuf.Length;
            fixed (byte* jpegPtr = jpegBuf)
            {
                return Decompress((IntPtr)jpegPtr, jpegBufSize, destPixelFormat, flags, out width, out height, out stride);
            }
        }
Ejemplo n.º 20
0
        /// <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));
        }
Ejemplo n.º 21
0
        /// <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, PixelFormat pixelFormat, TJSubsamplingOption subSamp, int quality, TJFlags flags)
        {
            var tjPixelFormat = TJUtils.ConvertPixelFormat(pixelFormat);

            return(this.Compress(srcBuf, destBuf, stride, width, height, tjPixelFormat, subSamp, quality, flags));
        }
Ejemplo n.º 22
0
 /// <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>
 /// The size of the JPEG image (in bytes).
 /// </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 int Compress(byte[] srcBuf, byte[] destBuf, int stride, int width, int height, PixelFormat pixelFormat, TJSubsamplingOption subSamp, int quality, TJFlags flags)
 {
     return(this.Compress(srcBuf.AsSpan(), destBuf.AsSpan(), stride, width, height, pixelFormat, subSamp, quality, flags).Length);
 }
Ejemplo n.º 23
0
        /// <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="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="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, PixelFormat pixelFormat, TJSubsamplingOption subSamp, int quality, TJFlags flags)
        {
            if (this.isDisposed)
            {
                throw new ObjectDisposedException("this");
            }

            var tjPixelFormat = TJUtils.ConvertPixelFormat(pixelFormat);

            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);
            }
        }
Ejemplo n.º 24
0
        /// <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 static unsafe Span <byte> Compress(this TJCompressor @this, ReadOnlySpan <byte> srcBuf, Span <byte> destBuf, int stride, int width, int height, PixelFormat pixelFormat, TJSubsamplingOption subSamp, int quality, TJFlags flags)
        {
            _ = @this ?? throw new ArgumentNullException(nameof(@this));
            var tjPixelFormat = TJGdiPlusUtils.ConvertPixelFormat(pixelFormat);

            return(@this.Compress(srcBuf, destBuf, stride, width, height, tjPixelFormat, subSamp, quality, flags));
        }
Ejemplo n.º 25
0
        /// <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="TJPixelFormats"/> "Pixel formats")</param>
        /// <param name="subSamp">
        /// The level of chrominance subsampling to be used when
        /// generating the JPEG image (see <see cref="TJSubsamplingOptions"/> "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>
        /// <param name="onAsyncCompressionCompleted">Method to process compressed data</param>
        /// <param name="state">User-defined state passed to <paramref name="onAsyncCompressionCompleted"/> method</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <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="TJSubsamplingOptions.TJSAMP_GRAY"/> and pixel format <see cref="TJPixelFormats.TJPF_GRAY"/></description></item>
        /// </list>
        /// </exception>
        /// <returns>
        /// </returns>
        public async Task CompressAsync(IntPtr srcPtr, int stride, int width, int height,
                                        TJPixelFormats tjPixelFormat, TJSubsamplingOptions subSamp, int quality, TJFlags flags,
                                        TJAsyncCompressionComplete onAsyncCompressionCompleted, object state, CancellationToken cancellationToken)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("this");
            }
            if (onAsyncCompressionCompleted == null)
            {
                throw new ArgumentNullException(nameof(onAsyncCompressionCompleted));
            }

            CheckOptionsCompatibilityAndThrow(subSamp, tjPixelFormat);

            var   buf     = IntPtr.Zero;
            ulong bufSize = 0;

            try
            {
                var result = TurboJpegImport.tjCompress2(
                    _compressorHandle,
                    srcPtr,
                    width,
                    stride,
                    height,
                    (int)tjPixelFormat,
                    ref buf,
                    ref bufSize,
                    (int)subSamp,
                    quality,
                    (int)flags);

                if (result == -1)
                {
                    TJUtils.GetErrorAndThrow();
                }

                await onAsyncCompressionCompleted(buf, (int)bufSize, state, cancellationToken);
            }
            finally
            {
                TurboJpegImport.tjFree(buf);
            }
        }
Ejemplo n.º 26
0
        /// <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="PixelFormat"/> "Pixel formats".)</param>
        /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param>
        /// <returns>Decompressed image 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>
        /// <exception cref="NotSupportedException">Convertion to the requested pixel format can not be performed.</exception>
        public static unsafe Bitmap Decompress(this TJDecompressor @this, IntPtr jpegBuf, ulong jpegBufSize, PixelFormat destPixelFormat, TJFlags flags)
        {
            var    targetFormat = TJGdiPlusUtils.ConvertPixelFormat(destPixelFormat);
            int    width;
            int    height;
            int    stride;
            var    buffer = @this.Decompress(jpegBuf, jpegBufSize, targetFormat, flags, out width, out height, out stride);
            Bitmap result;

            fixed(byte *bufferPtr = buffer)
            {
                result = new Bitmap(width, height, stride, destPixelFormat, (IntPtr)bufferPtr);
                if (destPixelFormat == PixelFormat.Format8bppIndexed)
                {
                    result.Palette = TJGdiPlusUtils.FixPaletteToGrayscale(result.Palette);
                }
            }

            return(result);
        }
        /// <summary>Transforms input image into one or several destinations</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="transforms">Array of transform descriptions to be applied to the source image </param>
        /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags"</param>
        /// <returns>Array of transformed jpeg images</returns>
        /// <exception cref="ArgumentNullException"><paramref name="transforms"/> is <see langword="null" />.</exception>
        /// <exception cref="ArgumentException">Transforms can not be empty</exception>
        /// <exception cref="TJException"> Throws if low level turbo jpeg function fails </exception>
        public byte[][] Transform(IntPtr jpegBuf, ulong jpegBufSize, TJTransformDescription[] transforms, TJFlags flags)
        {
            if (transforms == null)
                throw new ArgumentNullException("transforms");
            if (transforms.Length == 0)
                throw new ArgumentException("Transforms can not be empty", "transforms");

            // ReSharper disable once ExceptionNotDocumented
            var count = transforms.Length;
            var destBufs = new IntPtr[count];
            var destSizes = new ulong[count];


            int subsampl;
            int colorspace;
            int width;
            int height;
            var funcResult = TurboJpegImport.tjDecompressHeader(_transformHandle, jpegBuf, jpegBufSize,
                out width, out height, out subsampl, out colorspace);

            if (funcResult == -1)
            {
                TJUtils.GetErrorAndThrow();
            }

            Size mcuSize;
            if (!TurboJpegImport.MCUSizes.TryGetValue((TJSubsamplingOptions)subsampl, out mcuSize))
            {
                throw new TJException("Unable to read Subsampling Options from jpeg header");
            }



            var tjTransforms = new tjtransform[count];
            for (var i = 0; i < count; i++)
            {
                var x = CorrectRegionCoordinate(transforms[i].Region.X, mcuSize.Width);
                var y = CorrectRegionCoordinate(transforms[i].Region.Y, mcuSize.Height);
                var w = CorrectRegionSize(transforms[i].Region.X, x, transforms[i].Region.W, width);
                var h = CorrectRegionSize(transforms[i].Region.Y, y, transforms[i].Region.H, height);


                tjTransforms[i] = new tjtransform
                {
                    op = (int)transforms[i].Operation,
                    options = (int)transforms[i].Options,
                    r = new TJRegion
                    {
                        X = x,
                        Y = y,
                        W = w,
                        H = h
                    },
                    data = transforms[i].CallbackData,
                    customFilter = transforms[i].CustomFilter
                };
            }
            var transformsPtr =  TJUtils.StructArrayToIntPtr(tjTransforms);
            try
            {
                funcResult = TurboJpegImport.tjTransform(_transformHandle, jpegBuf, jpegBufSize, count, destBufs,
                    destSizes, transformsPtr, (int)flags);
                if (funcResult == -1)
                {
                    TJUtils.GetErrorAndThrow();
                }

                var result = new List<byte[]>();
                for (var i = 0; i < destBufs.Length; i++)
                {
                    var ptr = destBufs[i];
                    var size = destSizes[i];
                    var item = new byte[size];
                    Marshal.Copy(ptr, item, 0, (int)size);
                    result.Add(item);

                    TurboJpegImport.tjFree(ptr);
                }
                return result.ToArray();

            }
            finally
            {
                TJUtils.FreePtr(transformsPtr);
            }
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Compresses input image to the jpeg format with specified quality.
        /// </summary>
        /// <param name="srcImage"> Source image to be converted. </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>
        /// <remarks>Only <see cref="PixelFormat.Format24bppRgb"/>, <see cref="PixelFormat.Format32bppArgb"/>, <see cref="PixelFormat.Format8bppIndexed"/> pixel formats are supported.</remarks>
        /// <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 static byte[] Compress(this TJCompressor @this, Bitmap srcImage, TJSubsamplingOption subSamp, int quality, TJFlags flags)
        {
            _ = @this ?? throw new ArgumentNullException(nameof(@this));
            var pixelFormat = srcImage.PixelFormat;

            var width   = srcImage.Width;
            var height  = srcImage.Height;
            var srcData = srcImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, pixelFormat);

            var stride = srcData.Stride;
            var srcPtr = srcData.Scan0;

            try
            {
                return(@this.Compress(srcPtr, stride, width, height, pixelFormat, subSamp, quality, flags));
            }
            finally
            {
                srcImage.UnlockBits(srcData);
            }
        }
Ejemplo n.º 29
0
 /// <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(ReadOnlySpan <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>
        /// 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="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="TJSubsamplingOptions"/> "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>
        /// <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="TJSubsamplingOptions.TJSAMP_GRAY"/> and pixel format <see cref="TJPixelFormats.TJPF_GRAY"/></description></item>
        /// </list>
        /// </exception>
        public byte[] Compress(IntPtr srcPtr, int stride, int width, int height, PixelFormat pixelFormat = PixelFormat.Format32bppArgb, TJSubsamplingOptions subSamp = TJSubsamplingOptions.TJSAMP_420, int quality = 50, TJFlags flags = TJFlags.FASTDCT)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("this");
            }

            var tjPixelFormat = TJUtils.ConvertPixelFormat(pixelFormat);

            CheckOptionsCompatibilityAndThrow(subSamp, tjPixelFormat);
            TJDoCompDel compresscall = TurboJpegImport.tjCompress2;

            if (isXPlatform)
            {
                compresscall = TurboJpegImport_xplat.tjCompressX;
            }

            var   buf     = IntPtr.Zero;
            ulong bufSize = 0;

            try
            {
                var result = compresscall(
                    _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];
                // ReSharper disable once ExceptionNotDocumentedOptional
                Marshal.Copy(buf, jpegBuf, 0, (int)bufSize);
                return(jpegBuf);
            }
            finally
            {
                TurboJpegImport.tjFree(buf);
            }
        }
Ejemplo n.º 31
0
        /// <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);
        }
Ejemplo n.º 32
0
        /// <summary>Transforms input image into one or several destinations.</summary>
        /// <param name="jpegBuf">A buffer containing the JPEG image to decompress. This buffer is not modified.</param>
        /// <param name="transforms">Array of transform descriptions to be applied to the source image. </param>
        /// <param name="flags">The bitwise OR of one or more of the <see cref="TJFlags"/> "flags".</param>
        /// <returns>Array of transformed jpeg images.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="transforms"/> is <see langword="null" />.</exception>
        /// <exception cref="ArgumentException">Transforms can not be empty.</exception>
        /// <exception cref="TJException"> Throws if low level turbo jpeg function fails. </exception>
        public unsafe byte[][] Transform(byte[] jpegBuf, TJTransformDescription[] transforms, TJFlags flags)
        {
            if (transforms == null)
            {
                throw new ArgumentNullException(nameof(transforms));
            }

            if (transforms.Length == 0)
            {
                throw new ArgumentException("Transforms can not be empty", nameof(transforms));
            }

            fixed(byte *jpegPtr = jpegBuf)
            {
                return(this.Transform((IntPtr)jpegPtr, (ulong)jpegBuf.Length, transforms, flags));
            }
        }
        /// <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="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="TJSubsamplingOptions"/> "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>
        /// <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="TJSubsamplingOptions.TJSAMP_GRAY"/> and pixel format <see cref="TJPixelFormats.TJPF_GRAY"/></description></item>
        /// </list>
        /// </exception>
        public unsafe byte[] Compress(byte[] srcBuf, int stride, int width, int height, PixelFormat pixelFormat, TJSubsamplingOptions subSamp, int quality, TJFlags flags)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("this");
            }

            var tjPixelFormat = TJUtils.ConvertPixelFormat(pixelFormat);

            CheckOptionsCompatibilityAndThrow(subSamp, tjPixelFormat);

            var   buf     = IntPtr.Zero;
            ulong bufSize = 0;

            try
            {
                fixed(byte *srcBufPtr = srcBuf)
                {
                    var result = TurboJpegImport.tjCompress2(
                        _compressorHandle,
                        (IntPtr)srcBufPtr,
                        width,
                        stride,
                        height,
                        (int)tjPixelFormat,
                        ref buf,
                        ref bufSize,
                        (int)subSamp,
                        quality,
                        (int)flags);

                    if (result == -1)
                    {
                        TJUtils.GetErrorAndThrow();
                    }
                }

                var jpegBuf = new byte[bufSize];

                // ReSharper disable once ExceptionNotDocumentedOptional
                Marshal.Copy(buf, jpegBuf, 0, (int)bufSize);
                return(jpegBuf);
            }
            finally
            {
                TurboJpegImport.tjFree(buf);
            }
        }
Ejemplo n.º 34
0
        /// <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>
        /// <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, TJPixelFormats destPixelFormat, TJFlags flags, out int width, out int height, out int stride)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("this");
            }

            var jpegBufSize = (ulong)jpegBuf.Length;

            fixed(byte *jpegPtr = jpegBuf)
            {
                return(Decompress((IntPtr)jpegPtr, jpegBufSize, destPixelFormat, flags, out width, out height, out stride));
            }
        }
        /// <summary>
        /// Compresses input image to the jpeg format with specified quality
        /// </summary>
        /// <param name="srcImage"> Source image to be converted </param>
        /// <param name="subSamp">
        /// The level of chrominance subsampling to be used when
        /// generating the JPEG image (see <see cref="TJSubsamplingOptions"/> "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>
        /// <remarks>Only <see cref="PixelFormat.Format24bppRgb"/>, <see cref="PixelFormat.Format32bppArgb"/>, <see cref="PixelFormat.Format8bppIndexed"/> pixel formats are supported</remarks>
        /// <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="TJSubsamplingOptions.TJSAMP_GRAY"/> and pixel format <see cref="TJPixelFormats.TJPF_GRAY"/></description></item>
        /// </list>
        /// </exception>
        public byte[] Compress(Bitmap srcImage, TJSubsamplingOptions subSamp, int quality, TJFlags flags)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("this");
            }

            var pixelFormat = srcImage.PixelFormat;

            var width  = srcImage.Width;
            var height = srcImage.Height;
            // ReSharper disable once ExceptionNotDocumented
            var srcData = srcImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, pixelFormat);

            var stride = srcData.Stride;
            var srcPtr = srcData.Scan0;

            try
            {
                return(Compress(srcPtr, stride, width, height, pixelFormat, subSamp, quality, flags));
            }
            finally
            {
                // ReSharper disable once ExceptionNotDocumented
                srcImage.UnlockBits(srcData);
            }
        }
Ejemplo n.º 36
0
        /// <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));
            }
        }
Ejemplo n.º 37
0
 /// <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>
 /// The size of the JPEG image (in bytes).
 /// </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 static unsafe int Compress(this TJCompressor @this, byte[] srcBuf, byte[] destBuf, int stride, int width, int height, PixelFormat pixelFormat, TJSubsamplingOption subSamp, int quality, TJFlags flags)
 {
     _ = @this ?? throw new ArgumentNullException(nameof(@this));
     return(@this.Compress(srcBuf.AsSpan(), destBuf.AsSpan(), stride, width, height, pixelFormat, subSamp, quality, flags).Length);
 }
Ejemplo n.º 38
0
        public unsafe void Decompress(IntPtr jpegBuf, ulong jpegBufSize, IntPtr outBuf, int outBufSize, TJPixelFormats destPixelFormat, TJFlags flags, out int width, out int height, out int stride)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("this");
            }

            int subsampl;
            int colorspace;
            var funcResult = TurboJpegImport.tjDecompressHeader(_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(
                _decompressorHandle,
                jpegBuf,
                jpegBufSize,
                outBuf,
                width,
                stride,
                height,
                (int)targetFormat,
                (int)flags);

            if (funcResult == -1)
            {
                TJUtils.GetErrorAndThrow();
            }
        }
        /// <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 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>
        /// <exception cref="NotSupportedException">Convertion to the requested pixel format can not be performed</exception>
        public unsafe Bitmap Decompress(byte[] jpegBuf, PixelFormat destPixelFormat, TJFlags flags)
        {
            if (_isDisposed)
                throw new ObjectDisposedException("this");

            var jpegBufSize = (ulong)jpegBuf.Length;
            fixed (byte* jpegPtr = jpegBuf)
            {
                return Decompress((IntPtr)jpegPtr, jpegBufSize, destPixelFormat, flags);
            }
        }