Ejemplo n.º 1
0
        public void CompressBitmap(
            [Values
                 (TJSubsamplingOptions.TJSAMP_GRAY,
                 TJSubsamplingOptions.TJSAMP_411,
                 TJSubsamplingOptions.TJSAMP_420,
                 TJSubsamplingOptions.TJSAMP_440,
                 TJSubsamplingOptions.TJSAMP_422,
                 TJSubsamplingOptions.TJSAMP_444)] TJSubsamplingOptions options,
            [Values(1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)] int quality)
        {
            var imageidx = 0;

            foreach (var bitmap in TestUtils.GetTestImages("*.bmp"))
            {
                try
                {
                    Trace.WriteLine($"Options: {options}; Quality: {quality}");
                    Assert.DoesNotThrow(() =>
                    {
                        var result = _compressor.Compress(bitmap, options, quality, TJFlags.NONE);

                        Assert.NotNull(result);

                        var file = Path.Combine(OutDirectory, $"{imageidx}_{quality}_{options}.jpg");
                        File.WriteAllBytes(file, result);
                    });
                }
                finally
                {
                    bitmap.Dispose();
                }
                imageidx++;
            }
        }
Ejemplo n.º 2
0
        public void CompressIntPtr(
            [Values
                 (TJSubsamplingOptions.TJSAMP_GRAY,
                 TJSubsamplingOptions.TJSAMP_411,
                 TJSubsamplingOptions.TJSAMP_420,
                 TJSubsamplingOptions.TJSAMP_440,
                 TJSubsamplingOptions.TJSAMP_422,
                 TJSubsamplingOptions.TJSAMP_444)] TJSubsamplingOptions options,
            [Values(1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)] int quality)
        {
            foreach (var bitmap in TestUtils.GetTestImages("*.bmp"))
            {
                BitmapData data = null;
                try
                {
                    data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly,
                                           bitmap.PixelFormat);

                    Trace.WriteLine($"Options: {options}; Quality: {quality}");
                    Assert.DoesNotThrow(() =>
                    {
                        var result = _compressor.Compress(data.Scan0, data.Stride, data.Width, data.Height, TestUtils.ConvertPixelFormat(data.PixelFormat), options, quality, TJFlags.NONE);
                        Assert.NotNull(result);
                    });
                }
                finally
                {
                    if (data != null)
                    {
                        bitmap.UnlockBits(data);
                    }
                    bitmap.Dispose();
                }
            }
        }
        /// <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.º 4
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);
            }
        }
 private static void CheckOptionsCompatibilityAndThrow(TJSubsamplingOptions subSamp, TJPixelFormats srcFormat)
 {
     if (srcFormat == TJPixelFormats.TJPF_GRAY && subSamp != TJSubsamplingOptions.TJSAMP_GRAY)
     {
         throw new NotSupportedException(
                   $"Subsampling differ from {TJSubsamplingOptions.TJSAMP_GRAY} for pixel format {TJPixelFormats.TJPF_GRAY} is not supported");
     }
 }
Ejemplo n.º 6
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.º 7
0
        public async void CompressAsync(
            [Values
                 (TJSubsamplingOptions.TJSAMP_GRAY,
                 TJSubsamplingOptions.TJSAMP_411,
                 TJSubsamplingOptions.TJSAMP_420,
                 TJSubsamplingOptions.TJSAMP_440,
                 TJSubsamplingOptions.TJSAMP_422,
                 TJSubsamplingOptions.TJSAMP_444)] TJSubsamplingOptions options,
            [Values(1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)] int quality)
        {
            foreach (var bitmap in TestUtils.GetTestImages("*.bmp"))
            {
                var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly,
                                           bitmap.PixelFormat);
                try
                {
                    var stride      = data.Stride;
                    var width       = data.Width;
                    var height      = data.Height;
                    var pixelFormat = TestUtils.ConvertPixelFormat(data.PixelFormat);

                    var buf = new byte[stride * height];
                    Marshal.Copy(data.Scan0, buf, 0, buf.Length);

                    Trace.WriteLine($"Options: {options}; Quality: {quality}");
                    CancellationTokenSource cancellation = new CancellationTokenSource();

                    await _compressor.CompressAsync(data.Scan0, stride, width, height, pixelFormat, options, quality, TJFlags.NONE,
                                                    async (ptr, size, state, token) =>
                    {
                        await Task.Delay(10, token);

                        Assert.IsTrue(ptr != IntPtr.Zero, "ptr != IntPtr.Zero");
                        Assert.IsTrue(size > 0, "size > 0");
                        Assert.IsNull(state, "state != null");
                    }, null, cancellation.Token);
                }
                finally
                {
                    bitmap.UnlockBits(data);
                    bitmap.Dispose();
                }
            }
        }
Ejemplo n.º 8
0
        public void CompressByteArray(
            [Values
                 (TJSubsamplingOptions.TJSAMP_GRAY,
                 TJSubsamplingOptions.TJSAMP_411,
                 TJSubsamplingOptions.TJSAMP_420,
                 TJSubsamplingOptions.TJSAMP_440,
                 TJSubsamplingOptions.TJSAMP_422,
                 TJSubsamplingOptions.TJSAMP_444)] TJSubsamplingOptions options,
            [Values(1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)] int quality)
        {
            foreach (var bitmap in TestUtils.GetTestImages("*.bmp"))
            {
                try
                {
                    var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly,
                                               bitmap.PixelFormat);

                    var stride      = data.Stride;
                    var width       = data.Width;
                    var height      = data.Height;
                    var pixelFormat = TestUtils.ConvertPixelFormat(data.PixelFormat);


                    var buf = new byte[stride * height];
                    Marshal.Copy(data.Scan0, buf, 0, buf.Length);
                    bitmap.UnlockBits(data);

                    Trace.WriteLine($"Options: {options}; Quality: {quality}");
                    Assert.DoesNotThrow(() =>
                    {
                        var result = _compressor.Compress(buf, stride, width, height, pixelFormat, options, quality, TJFlags.NONE);
                        Assert.NotNull(result);
                    });
                }
                finally
                {
                    bitmap.Dispose();
                }
            }
        }
Ejemplo n.º 9
0
        public JpegFrame(JpegCompressor compressor, int width, int height, TJSubsamplingOptions subSampling)
        {
            _compressor = compressor;

            checked
            {
                Width         = width;
                Height        = height;
                SubSampling   = subSampling;
                MaxBufferSize = (int)JpegLibrary.tjBufSize(width, height, (int)subSampling);
            }

            var bufferHandle = JpegLibrary.tjAlloc(MaxBufferSize);

            if (bufferHandle == IntPtr.Zero)
            {
                throw new OutOfMemoryException(
                          $"Failed to allocate TurboJPEG buffer of size {width}x{height}, subSampling {subSampling}");
            }

            SetResourceHandle(bufferHandle);
        }
        /// <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);
            }
        }
 public JpegFrame CreateFrameBuffer(int maxWidth, int maxHeight, TJSubsamplingOptions subSampling)
 {
     return(new JpegFrame(this, maxWidth, maxHeight, subSampling));
 }
Ejemplo n.º 12
0
 private static void CheckOptionsCompatibilityAndThrow(TJSubsamplingOptions subSamp, TJPixelFormats srcFormat)
 {
     if (srcFormat == TJPixelFormats.TJPF_GRAY && subSamp != TJSubsamplingOptions.TJSAMP_GRAY)
         throw new NotSupportedException(
             $"Subsampling differ from {TJSubsamplingOptions.TJSAMP_GRAY} for pixel format {TJPixelFormats.TJPF_GRAY} is not supported");
 }
Ejemplo n.º 13
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>
        /// 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);
            }
        }