Ejemplo n.º 1
0
 private void ReleaseUnmanagedResources()
 {
     if (_decompressorHandle != IntPtr.Zero)
     {
         TurboJpeg.DestroyInstance(_decompressorHandle);
         _decompressorHandle = IntPtr.Zero;
     }
 }
Ejemplo n.º 2
0
        private void Initialize()
        {
            if (_decompressorHandle != IntPtr.Zero)
            {
                return;
            }

            _decompressorHandle = TurboJpeg.InitDecompressorInstance();
            if (_decompressorHandle == IntPtr.Zero)
            {
                throw new RfbProtocolException($"Initializing TurboJPEG decompressor instance failed: {TurboJpeg.GetLastError()}");
            }
        }
Ejemplo n.º 3
0
        public unsafe void DecodeJpegTo32Bit(Span <byte> jpegBuffer, Span <byte> pixelsBuffer, int expectedWidth, int expectedHeight, PixelFormat preferredPixelFormat,
                                             out PixelFormat usedPixelFormat, CancellationToken cancellationToken = default)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(nameof(TurboJpegDecoder));
            }

            if (!TurboJpeg.IsAvailable)
            {
                throw new InvalidOperationException("The TurboJPEG decoder is unavailable on the current system.");
            }

            // Initialize on first use
            if (_decompressorHandle == IntPtr.Zero)
            {
                Initialize();
            }

            cancellationToken.ThrowIfCancellationRequested();

            int jpegBufferLength   = jpegBuffer.Length;
            int pixelsBufferLength = pixelsBuffer.Length;

            // NOTE: We only use 32bit pixel formats, so we don't have to deal with padding here.

            // Find a fitting pixel format that requires the least conversion later
            var tjPixelFormat = TurboJpegPixelFormat.RGBA;

            usedPixelFormat = RgbaCompatiblePixelFormat;
            if (BgraCompatiblePixelFormat.IsBinaryCompatibleTo(preferredPixelFormat))
            {
                tjPixelFormat   = TurboJpegPixelFormat.BGRA;
                usedPixelFormat = BgraCompatiblePixelFormat;
            }
            else if (ArgbCompatiblePixelFormat.IsBinaryCompatibleTo(preferredPixelFormat))
            {
                tjPixelFormat   = TurboJpegPixelFormat.ARGB;
                usedPixelFormat = ArgbCompatiblePixelFormat;
            }
            else if (AbgrCompatiblePixelFormat.IsBinaryCompatibleTo(preferredPixelFormat))
            {
                tjPixelFormat   = TurboJpegPixelFormat.ABGR;
                usedPixelFormat = AbgrCompatiblePixelFormat;
            }

            fixed(byte *jpegBufferPtr = jpegBuffer)
            fixed(byte *pixelsBufferPtr = pixelsBuffer)
            {
                // Retrieve the JPEG header information so we can make sure, that our buffer is large enough
                if (TurboJpeg.DecompressHeader(_decompressorHandle, (IntPtr)jpegBufferPtr, (ulong)jpegBufferLength, out int width, out int height, out _, out _) == -1)
                {
                    throw new RfbProtocolException($"Decompressiong JPEG header failed: {TurboJpeg.GetLastError()}");
                }

                // Validate the image size
                if (width != expectedWidth || height != expectedHeight)
                {
                    throw new RfbProtocolException(
                              $"Cannot decode JPEG image because it's size of {width}x{height} does not match the expected size {expectedWidth}x{expectedHeight}.");
                }

                // Validate the buffer size
                int stride = width * 4;
                int requiredBufferLength = stride * height;

                if (pixelsBufferLength < requiredBufferLength)
                {
                    throw new RfbProtocolException(
                              $"Cannot decode JPEG image ({width}x{height}) because it's size of {requiredBufferLength} bytes would exceed the pixels buffer size of {pixelsBufferLength} when decompressing. ");
                }

                Debug.Assert(pixelsBufferLength == requiredBufferLength, "pixelsBufferLength == requiredBufferLength");

                // Decompress the image to the pixels buffer
                if (TurboJpeg.Decompress(_decompressorHandle, (IntPtr)jpegBufferPtr, (ulong)jpegBufferLength, (IntPtr)pixelsBufferPtr, width, stride, height, (int)tjPixelFormat,
                                         (int)(TurboJpegFlags.FastUpsample | TurboJpegFlags.FastDct | TurboJpegFlags.NoRealloc)) == -1)
                {
                    throw new RfbProtocolException($"Decompressiong JPEG image failed: {TurboJpeg.GetLastError()}");
                }
            }
        }