예제 #1
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(Span <byte> jpegBuf, Span <byte> outBuf, TJPixelFormat destPixelFormat, TJFlags flags, out int width, out int height, out int stride)
        {
            Verify.NotDisposed(this);

            fixed(byte *jpegBufPtr = jpegBuf)
            fixed(byte *outBufPtr = outBuf)
            {
                int subsampl;
                int colorspace;
                var funcResult = TurboJpegImport.TjDecompressHeader(
                    this.decompressorHandle,
                    jpegBufPtr,
                    (nuint)jpegBuf.Length,
                    out width,
                    out height,
                    out subsampl,
                    out colorspace);

                TJUtils.ThrowOnError(funcResult);

                var targetFormat = destPixelFormat;

                stride = TurboJpegImport.TJPAD(width * TurboJpegImport.PixelSizes[targetFormat]);
                var bufSize = stride * height;

                if (outBuf.Length < bufSize)
                {
                    throw new ArgumentOutOfRangeException(nameof(outBuf));
                }

                funcResult = TurboJpegImport.TjDecompress(
                    this.decompressorHandle,
                    jpegBufPtr,
                    (nuint)jpegBuf.Length,
                    outBufPtr,
                    width,
                    stride,
                    height,
                    (int)targetFormat,
                    (int)flags);

                TJUtils.ThrowOnError(funcResult);
            }
        }
예제 #2
0
        /// <summary>
        /// Retrieve information about a JPEG image without decompressing it.
        /// </summary>
        /// <param name="jpegBuf">
        /// Pointer to a buffer containing a JPEG image.  This buffer is not modified.
        /// </param>
        /// <param name="destPixelFormat">
        /// The pixel format of the uncompressed image.
        /// </param>
        /// <param name="width">
        /// Pointer to an integer variable that will receive the width (in pixels) of the JPEG image.
        /// </param>
        /// <param name="height">
        /// Pointer to an integer variable that will receive the height (in pixels) of the JPEG image.
        /// </param>
        /// <param name="stride">
        /// Pointer to an integer variable that will receive the stride (in bytes) of the JPEG image.
        /// </param>
        /// <param name="bufSize">
        /// The size of a buffer that can receive the uncompressed JPEG image.
        /// </param>
        public void GetImageInfo(Span <byte> jpegBuf, TJPixelFormat destPixelFormat, out int width, out int height, out int stride, out int bufSize)
        {
            Verify.NotDisposed(this);

            int subsampl;
            int colorspace;

            fixed(byte *jpegBufPtr = jpegBuf)
            {
                var funcResult = TurboJpegImport.TjDecompressHeader(
                    this.decompressorHandle,
                    jpegBufPtr,
                    (nuint)jpegBuf.Length,
                    out width,
                    out height,
                    out subsampl,
                    out colorspace);

                stride  = TurboJpegImport.TJPAD(width * TurboJpegImport.PixelSizes[destPixelFormat]);
                bufSize = stride * height;
            }
        }
예제 #3
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="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(Span <byte> jpegBuf, TJTransformDescription[] transforms, TJFlags flags)
        {
            Verify.NotDisposed(this);

            if (transforms == null)
            {
                throw new ArgumentNullException(nameof(transforms));
            }

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

            fixed(byte *jpegBufPtr = jpegBuf)
            {
                var count     = transforms.Length;
                var destBufs  = new IntPtr[count];
                var destSizes = new uint[count];

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

                TJUtils.ThrowOnError(funcResult);

                Size mcuSize;

                if (!TurboJpegImport.MCUSizes.TryGetValue((TJSubsamplingOption)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(
                        this.transformHandle,
                        jpegBufPtr,
                        (nuint)jpegBuf.Length,
                        count,
                        destBufs,
                        destSizes,
                        transformsPtr,
                        (int)flags);

                    TJUtils.ThrowOnError(funcResult);

                    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);
                }
            }
        }