/// <summary> /// Decompress a JPEG 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="SKColorType"/> "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 SKBitmap Decompress(this TJDecompressor @this, IntPtr jpegBuf, ulong jpegBufSize, SKColorType destPixelFormat, TJFlags flags) { _ = @this ?? throw new ArgumentNullException(nameof(@this)); var targetFormat = TJSkiaUtils.ConvertPixelFormat(destPixelFormat); @this.GetImageInfo(jpegBuf, jpegBufSize, targetFormat, out var width, out var height, out var stride, out var outBufSize); var info = new SKImageInfo(width, height, destPixelFormat); if (info.RowBytes != stride) { throw new NotSupportedException($"Skia expected the RowBytes/stride to be {info.RowBytes} for the given parameters but MozJPEG returns {stride}. Those values need to be equal."); } if (info.BytesSize != outBufSize) { throw new NotSupportedException($"Skia expected the BytesSize/number of bytes required to store the bitmap data to be {info.BytesSize} for the given parameters but MozJPEG returns {outBufSize}. Those values need to be equal."); } var dst = new SKBitmap(info); var dstPtr = dst.GetPixels(); @this.Decompress(jpegBuf, jpegBufSize, dstPtr, outBufSize, targetFormat, flags, out _, out _, out _); return(dst); }
/// <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)); } }
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); }
/// <summary> /// Decompress a JPEG 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="SKColorType"/> "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 SKBitmap Decompress(this TJDecompressor @this, ReadOnlySpan <byte> jpegBuf, SKColorType destPixelFormat, TJFlags flags) { _ = @this ?? throw new ArgumentNullException(nameof(@this)); // see https://stackoverflow.com/questions/537573/how-to-get-intptr-from-byte-in-c-sharp var pinnedArray = GCHandle.Alloc(jpegBuf.GetPinnableReference(), GCHandleType.Pinned); try { IntPtr pointer = pinnedArray.AddrOfPinnedObject(); var jpegBufSize = (ulong)jpegBuf.Length; return(@this.Decompress(pointer, jpegBufSize, destPixelFormat, flags)); } finally { pinnedArray.Free(); } }
/// <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); }