2023-12-28 16:15:19 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Wrapper for WebP format in C#. (MIT) Jose M. Piñeiro
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Decode Functions:
/// Bitmap Load(string pathFileName) - Load a WebP file in bitmap.
/// Bitmap Decode(byte[] rawWebP) - Decode WebP data (rawWebP) to bitmap.
/// Bitmap Decode(byte[] rawWebP, WebPDecoderOptions options) - Decode WebP data (rawWebP) to bitmap using 'options'.
/// Bitmap GetThumbnailFast(byte[] rawWebP, int width, int height) - Get a thumbnail from WebP data (rawWebP) with dimensions 'width x height'. Fast mode.
/// Bitmap GetThumbnailQuality(byte[] rawWebP, int width, int height) - Fast get a thumbnail from WebP data (rawWebP) with dimensions 'width x height'. Quality mode.
///
/// Encode Functions:
/// Save(Bitmap bmp, string pathFileName, int quality) - Save bitmap with quality lost to WebP file. Opcionally select 'quality'.
/// byte[] EncodeLossy(Bitmap bmp, int quality) - Encode bitmap with quality lost to WebP byte array. Opcionally select 'quality'.
/// byte[] EncodeLossy(Bitmap bmp, int quality, int speed, bool info) - Encode bitmap with quality lost to WebP byte array. Select 'quality', 'speed' and optionally select 'info'.
/// byte[] EncodeLossless(Bitmap bmp) - Encode bitmap without quality lost to WebP byte array.
/// byte[] EncodeLossless(Bitmap bmp, int speed, bool info = false) - Encode bitmap without quality lost to WebP byte array. Select 'speed'.
/// byte[] EncodeNearLossless(Bitmap bmp, int quality, int speed = 9, bool info = false) - Encode bitmap with a near lossless method to WebP byte array. Select 'quality', 'speed' and optionally select 'info'.
///
/// Another functions:
/// string GetVersion() - Get the library version
/// GetInfo(byte[] rawWebP, out int width, out int height, out bool has_alpha, out bool has_animation, out string format) - Get information of WEBP data
/// float[] PictureDistortion(Bitmap source, Bitmap reference, int metric_type) - Get PSNR, SSIM or LSIM distortion metric between two pictures
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
using System ;
using System.Drawing ;
using System.Drawing.Imaging ;
using System.IO ;
using System.Runtime.InteropServices ;
using System.Security ;
using System.Windows.Forms ;
namespace Wabbajack
{
public sealed class WebP : IDisposable
{
private const int WEBP_MAX_DIMENSION = 16383 ;
#region | Public Decode Functions |
/// <summary>Read a WebP file</summary>
/// <param name="pathFileName">WebP file to load</param>
/// <returns>Bitmap with the WebP image</returns>
public Bitmap Load ( string pathFileName )
{
try
{
byte [ ] rawWebP = File . ReadAllBytes ( pathFileName ) ;
return Decode ( rawWebP ) ;
}
catch ( Exception ex ) { throw new Exception ( ex . Message + "\r\nIn WebP.Load" ) ; }
}
/// <summary>Decode a WebP image</summary>
/// <param name="rawWebP">The data to uncompress</param>
/// <returns>Bitmap with the WebP image</returns>
public Bitmap Decode ( byte [ ] rawWebP )
{
Bitmap bmp = null ;
BitmapData bmpData = null ;
GCHandle pinnedWebP = GCHandle . Alloc ( rawWebP , GCHandleType . Pinned ) ;
try
{
//Get image width and height
GetInfo ( rawWebP , out int imgWidth , out int imgHeight , out bool hasAlpha , out bool hasAnimation , out string format ) ;
//Create a BitmapData and Lock all pixels to be written
if ( hasAlpha )
bmp = new Bitmap ( imgWidth , imgHeight , PixelFormat . Format32bppArgb ) ;
else
bmp = new Bitmap ( imgWidth , imgHeight , PixelFormat . Format24bppRgb ) ;
bmpData = bmp . LockBits ( new Rectangle ( 0 , 0 , imgWidth , imgHeight ) , ImageLockMode . WriteOnly , bmp . PixelFormat ) ;
//Uncompress the image
int outputSize = bmpData . Stride * imgHeight ;
IntPtr ptrData = pinnedWebP . AddrOfPinnedObject ( ) ;
if ( bmp . PixelFormat = = PixelFormat . Format24bppRgb )
UnsafeNativeMethods . WebPDecodeBGRInto ( ptrData , rawWebP . Length , bmpData . Scan0 , outputSize , bmpData . Stride ) ;
else
UnsafeNativeMethods . WebPDecodeBGRAInto ( ptrData , rawWebP . Length , bmpData . Scan0 , outputSize , bmpData . Stride ) ;
return bmp ;
}
catch ( Exception ) { throw ; }
finally
{
//Unlock the pixels
if ( bmpData ! = null )
bmp . UnlockBits ( bmpData ) ;
//Free memory
if ( pinnedWebP . IsAllocated )
pinnedWebP . Free ( ) ;
}
}
/// <summary>Decode a WebP image</summary>
/// <param name="rawWebP">the data to uncompress</param>
/// <param name="options">Options for advanced decode</param>
/// <returns>Bitmap with the WebP image</returns>
public Bitmap Decode ( byte [ ] rawWebP , WebPDecoderOptions options , PixelFormat pixelFormat = PixelFormat . DontCare )
{
GCHandle pinnedWebP = GCHandle . Alloc ( rawWebP , GCHandleType . Pinned ) ;
Bitmap bmp = null ;
BitmapData bmpData = null ;
VP8StatusCode result ;
try
{
WebPDecoderConfig config = new WebPDecoderConfig ( ) ;
if ( UnsafeNativeMethods . WebPInitDecoderConfig ( ref config ) = = 0 )
{
throw new Exception ( "WebPInitDecoderConfig failed. Wrong version?" ) ;
}
// Read the .webp input file information
IntPtr ptrRawWebP = pinnedWebP . AddrOfPinnedObject ( ) ;
int height ;
int width ;
if ( options . use_scaling = = 0 )
{
result = UnsafeNativeMethods . WebPGetFeatures ( ptrRawWebP , rawWebP . Length , ref config . input ) ;
if ( result ! = VP8StatusCode . VP8_STATUS_OK )
throw new Exception ( "Failed WebPGetFeatures with error " + result ) ;
//Test cropping values
if ( options . use_cropping = = 1 )
{
if ( options . crop_left + options . crop_width > config . input . Width | | options . crop_top + options . crop_height > config . input . Height )
throw new Exception ( "Crop options exceeded WebP image dimensions" ) ;
width = options . crop_width ;
height = options . crop_height ;
}
}
else
{
width = options . scaled_width ;
height = options . scaled_height ;
}
config . options . bypass_filtering = options . bypass_filtering ;
config . options . no_fancy_upsampling = options . no_fancy_upsampling ;
config . options . use_cropping = options . use_cropping ;
config . options . crop_left = options . crop_left ;
config . options . crop_top = options . crop_top ;
config . options . crop_width = options . crop_width ;
config . options . crop_height = options . crop_height ;
config . options . use_scaling = options . use_scaling ;
config . options . scaled_width = options . scaled_width ;
config . options . scaled_height = options . scaled_height ;
config . options . use_threads = options . use_threads ;
config . options . dithering_strength = options . dithering_strength ;
config . options . flip = options . flip ;
config . options . alpha_dithering_strength = options . alpha_dithering_strength ;
//Create a BitmapData and Lock all pixels to be written
if ( config . input . Has_alpha = = 1 )
{
config . output . colorspace = WEBP_CSP_MODE . MODE_bgrA ;
bmp = new Bitmap ( config . input . Width , config . input . Height , PixelFormat . Format32bppArgb ) ;
}
else
{
config . output . colorspace = WEBP_CSP_MODE . MODE_BGR ;
bmp = new Bitmap ( config . input . Width , config . input . Height , PixelFormat . Format24bppRgb ) ;
}
bmpData = bmp . LockBits ( new Rectangle ( 0 , 0 , bmp . Width , bmp . Height ) , ImageLockMode . WriteOnly , bmp . PixelFormat ) ;
// Specify the output format
config . output . u . RGBA . rgba = bmpData . Scan0 ;
config . output . u . RGBA . stride = bmpData . Stride ;
config . output . u . RGBA . size = ( UIntPtr ) ( bmp . Height * bmpData . Stride ) ;
config . output . height = bmp . Height ;
config . output . width = bmp . Width ;
config . output . is_external_memory = 1 ;
// Decode
result = UnsafeNativeMethods . WebPDecode ( ptrRawWebP , rawWebP . Length , ref config ) ;
if ( result ! = VP8StatusCode . VP8_STATUS_OK )
{
throw new Exception ( "Failed WebPDecode with error " + result ) ;
}
UnsafeNativeMethods . WebPFreeDecBuffer ( ref config . output ) ;
return bmp ;
}
catch ( Exception ex ) { throw new Exception ( ex . Message + "\r\nIn WebP.Decode" ) ; }
finally
{
//Unlock the pixels
if ( bmpData ! = null )
bmp . UnlockBits ( bmpData ) ;
//Free memory
if ( pinnedWebP . IsAllocated )
pinnedWebP . Free ( ) ;
}
}
/// <summary>Get Thumbnail from webP in mode faster/low quality</summary>
/// <param name="rawWebP">The data to uncompress</param>
/// <param name="width">Wanted width of thumbnail</param>
/// <param name="height">Wanted height of thumbnail</param>
/// <returns>Bitmap with the WebP thumbnail in 24bpp</returns>
public Bitmap GetThumbnailFast ( byte [ ] rawWebP , int width , int height )
{
GCHandle pinnedWebP = GCHandle . Alloc ( rawWebP , GCHandleType . Pinned ) ;
Bitmap bmp = null ;
BitmapData bmpData = null ;
try
{
WebPDecoderConfig config = new WebPDecoderConfig ( ) ;
if ( UnsafeNativeMethods . WebPInitDecoderConfig ( ref config ) = = 0 )
throw new Exception ( "WebPInitDecoderConfig failed. Wrong version?" ) ;
// Set up decode options
config . options . bypass_filtering = 1 ;
config . options . no_fancy_upsampling = 1 ;
config . options . use_threads = 1 ;
config . options . use_scaling = 1 ;
config . options . scaled_width = width ;
config . options . scaled_height = height ;
// Create a BitmapData and Lock all pixels to be written
bmp = new Bitmap ( width , height , PixelFormat . Format24bppRgb ) ;
bmpData = bmp . LockBits ( new Rectangle ( 0 , 0 , width , height ) , ImageLockMode . WriteOnly , bmp . PixelFormat ) ;
// Specify the output format
config . output . colorspace = WEBP_CSP_MODE . MODE_BGR ;
config . output . u . RGBA . rgba = bmpData . Scan0 ;
config . output . u . RGBA . stride = bmpData . Stride ;
config . output . u . RGBA . size = ( UIntPtr ) ( height * bmpData . Stride ) ;
config . output . height = height ;
config . output . width = width ;
config . output . is_external_memory = 1 ;
// Decode
IntPtr ptrRawWebP = pinnedWebP . AddrOfPinnedObject ( ) ;
VP8StatusCode result = UnsafeNativeMethods . WebPDecode ( ptrRawWebP , rawWebP . Length , ref config ) ;
if ( result ! = VP8StatusCode . VP8_STATUS_OK )
throw new Exception ( "Failed WebPDecode with error " + result ) ;
UnsafeNativeMethods . WebPFreeDecBuffer ( ref config . output ) ;
return bmp ;
}
catch ( Exception ex ) { throw new Exception ( ex . Message + "\r\nIn WebP.Thumbnail" ) ; }
finally
{
//Unlock the pixels
if ( bmpData ! = null )
bmp . UnlockBits ( bmpData ) ;
//Free memory
if ( pinnedWebP . IsAllocated )
pinnedWebP . Free ( ) ;
}
}
/// <summary>Thumbnail from webP in mode slow/high quality</summary>
/// <param name="rawWebP">The data to uncompress</param>
/// <param name="width">Wanted width of thumbnail</param>
/// <param name="height">Wanted height of thumbnail</param>
/// <returns>Bitmap with the WebP thumbnail</returns>
public Bitmap GetThumbnailQuality ( byte [ ] rawWebP , int width , int height )
{
GCHandle pinnedWebP = GCHandle . Alloc ( rawWebP , GCHandleType . Pinned ) ;
Bitmap bmp = null ;
BitmapData bmpData = null ;
try
{
WebPDecoderConfig config = new WebPDecoderConfig ( ) ;
if ( UnsafeNativeMethods . WebPInitDecoderConfig ( ref config ) = = 0 )
throw new Exception ( "WebPInitDecoderConfig failed. Wrong version?" ) ;
IntPtr ptrRawWebP = pinnedWebP . AddrOfPinnedObject ( ) ;
VP8StatusCode result = UnsafeNativeMethods . WebPGetFeatures ( ptrRawWebP , rawWebP . Length , ref config . input ) ;
if ( result ! = VP8StatusCode . VP8_STATUS_OK )
throw new Exception ( "Failed WebPGetFeatures with error " + result ) ;
// Set up decode options
config . options . bypass_filtering = 0 ;
config . options . no_fancy_upsampling = 0 ;
config . options . use_threads = 1 ;
config . options . use_scaling = 1 ;
config . options . scaled_width = width ;
config . options . scaled_height = height ;
//Create a BitmapData and Lock all pixels to be written
if ( config . input . Has_alpha = = 1 )
{
config . output . colorspace = WEBP_CSP_MODE . MODE_bgrA ;
bmp = new Bitmap ( width , height , PixelFormat . Format32bppArgb ) ;
}
else
{
config . output . colorspace = WEBP_CSP_MODE . MODE_BGR ;
bmp = new Bitmap ( width , height , PixelFormat . Format24bppRgb ) ;
}
bmpData = bmp . LockBits ( new Rectangle ( 0 , 0 , width , height ) , ImageLockMode . WriteOnly , bmp . PixelFormat ) ;
// Specify the output format
config . output . u . RGBA . rgba = bmpData . Scan0 ;
config . output . u . RGBA . stride = bmpData . Stride ;
config . output . u . RGBA . size = ( UIntPtr ) ( height * bmpData . Stride ) ;
config . output . height = height ;
config . output . width = width ;
config . output . is_external_memory = 1 ;
// Decode
result = UnsafeNativeMethods . WebPDecode ( ptrRawWebP , rawWebP . Length , ref config ) ;
if ( result ! = VP8StatusCode . VP8_STATUS_OK )
throw new Exception ( "Failed WebPDecode with error " + result ) ;
UnsafeNativeMethods . WebPFreeDecBuffer ( ref config . output ) ;
return bmp ;
}
catch ( Exception ex ) { throw new Exception ( ex . Message + "\r\nIn WebP.Thumbnail" ) ; }
finally
{
//Unlock the pixels
if ( bmpData ! = null )
bmp . UnlockBits ( bmpData ) ;
//Free memory
if ( pinnedWebP . IsAllocated )
pinnedWebP . Free ( ) ;
}
}
#endregion
#region | Public Encode Functions |
/// <summary>Save bitmap to file in WebP format</summary>
/// <param name="bmp">Bitmap with the WebP image</param>
/// <param name="pathFileName">The file to write</param>
/// <param name="quality">Between 0 (lower quality, lowest file size) and 100 (highest quality, higher file size)</param>
public void Save ( Bitmap bmp , string pathFileName , int quality = 75 )
{
byte [ ] rawWebP ;
try
{
//Encode in webP format
rawWebP = EncodeLossy ( bmp , quality ) ;
//Write webP file
File . WriteAllBytes ( pathFileName , rawWebP ) ;
}
catch ( Exception ex ) { throw new Exception ( ex . Message + "\r\nIn WebP.Save" ) ; }
}
/// <summary>Lossy encoding bitmap to WebP (Simple encoding API)</summary>
/// <param name="bmp">Bitmap with the image</param>
/// <param name="quality">Between 0 (lower quality, lowest file size) and 100 (highest quality, higher file size)</param>
/// <returns>Compressed data</returns>
public byte [ ] EncodeLossy ( Bitmap bmp , int quality = 75 )
{
//test bmp
if ( bmp . Width = = 0 | | bmp . Height = = 0 )
throw new ArgumentException ( "Bitmap contains no data." , "bmp" ) ;
if ( bmp . Width > WEBP_MAX_DIMENSION | | bmp . Height > WEBP_MAX_DIMENSION )
throw new NotSupportedException ( "Bitmap's dimension is too large. Max is " + WEBP_MAX_DIMENSION + "x" + WEBP_MAX_DIMENSION + " pixels." ) ;
if ( bmp . PixelFormat ! = PixelFormat . Format24bppRgb & & bmp . PixelFormat ! = PixelFormat . Format32bppArgb )
throw new NotSupportedException ( "Only support Format24bppRgb and Format32bppArgb pixelFormat." ) ;
BitmapData bmpData = null ;
IntPtr unmanagedData = IntPtr . Zero ;
try
{
int size ;
//Get bmp data
bmpData = bmp . LockBits ( new Rectangle ( 0 , 0 , bmp . Width , bmp . Height ) , ImageLockMode . ReadOnly , bmp . PixelFormat ) ;
//Compress the bmp data
if ( bmp . PixelFormat = = PixelFormat . Format24bppRgb )
size = UnsafeNativeMethods . WebPEncodeBGR ( bmpData . Scan0 , bmp . Width , bmp . Height , bmpData . Stride , quality , out unmanagedData ) ;
else
size = UnsafeNativeMethods . WebPEncodeBGRA ( bmpData . Scan0 , bmp . Width , bmp . Height , bmpData . Stride , quality , out unmanagedData ) ;
if ( size = = 0 )
throw new Exception ( "Can´ t encode WebP" ) ;
//Copy image compress data to output array
byte [ ] rawWebP = new byte [ size ] ;
Marshal . Copy ( unmanagedData , rawWebP , 0 , size ) ;
return rawWebP ;
}
catch ( Exception ex ) { throw new Exception ( ex . Message + "\r\nIn WebP.EncodeLossly" ) ; }
finally
{
//Unlock the pixels
if ( bmpData ! = null )
bmp . UnlockBits ( bmpData ) ;
//Free memory
if ( unmanagedData ! = IntPtr . Zero )
UnsafeNativeMethods . WebPFree ( unmanagedData ) ;
}
}
/// <summary>Lossy encoding bitmap to WebP (Advanced encoding API)</summary>
/// <param name="bmp">Bitmap with the image</param>
/// <param name="quality">Between 0 (lower quality, lowest file size) and 100 (highest quality, higher file size)</param>
/// <param name="speed">Between 0 (fastest, lowest compression) and 9 (slower, best compression)</param>
/// <returns>Compressed data</returns>
public byte [ ] EncodeLossy ( Bitmap bmp , int quality , int speed , bool info = false )
{
//Initialize configuration structure
WebPConfig config = new WebPConfig ( ) ;
//Set compression parameters
if ( UnsafeNativeMethods . WebPConfigInit ( ref config , WebPPreset . WEBP_PRESET_DEFAULT , 75 ) = = 0 )
throw new Exception ( "Can´ t configure preset" ) ;
// Add additional tuning:
config . method = speed ;
if ( config . method > 6 )
config . method = 6 ;
config . quality = quality ;
config . autofilter = 1 ;
config . pass = speed + 1 ;
config . segments = 4 ;
config . partitions = 3 ;
config . thread_level = 1 ;
config . alpha_quality = quality ;
config . alpha_filtering = 2 ;
config . use_sharp_yuv = 1 ;
if ( UnsafeNativeMethods . WebPGetDecoderVersion ( ) > 1082 ) //Old version does not support preprocessing 4
{
config . preprocessing = 4 ;
config . use_sharp_yuv = 1 ;
}
else
config . preprocessing = 3 ;
return AdvancedEncode ( bmp , config , info ) ;
}
/// <summary>Lossless encoding bitmap to WebP (Simple encoding API)</summary>
/// <param name="bmp">Bitmap with the image</param>
/// <returns>Compressed data</returns>
public byte [ ] EncodeLossless ( Bitmap bmp )
{
//test bmp
if ( bmp . Width = = 0 | | bmp . Height = = 0 )
throw new ArgumentException ( "Bitmap contains no data." , "bmp" ) ;
if ( bmp . Width > WEBP_MAX_DIMENSION | | bmp . Height > WEBP_MAX_DIMENSION )
throw new NotSupportedException ( "Bitmap's dimension is too large. Max is " + WEBP_MAX_DIMENSION + "x" + WEBP_MAX_DIMENSION + " pixels." ) ;
if ( bmp . PixelFormat ! = PixelFormat . Format24bppRgb & & bmp . PixelFormat ! = PixelFormat . Format32bppArgb )
throw new NotSupportedException ( "Only support Format24bppRgb and Format32bppArgb pixelFormat." ) ;
BitmapData bmpData = null ;
IntPtr unmanagedData = IntPtr . Zero ;
try
{
//Get bmp data
bmpData = bmp . LockBits ( new Rectangle ( 0 , 0 , bmp . Width , bmp . Height ) , ImageLockMode . ReadOnly , bmp . PixelFormat ) ;
//Compress the bmp data
int size ;
if ( bmp . PixelFormat = = PixelFormat . Format24bppRgb )
size = UnsafeNativeMethods . WebPEncodeLosslessBGR ( bmpData . Scan0 , bmp . Width , bmp . Height , bmpData . Stride , out unmanagedData ) ;
else
size = UnsafeNativeMethods . WebPEncodeLosslessBGRA ( bmpData . Scan0 , bmp . Width , bmp . Height , bmpData . Stride , out unmanagedData ) ;
//Copy image compress data to output array
byte [ ] rawWebP = new byte [ size ] ;
Marshal . Copy ( unmanagedData , rawWebP , 0 , size ) ;
return rawWebP ;
}
catch ( Exception ex ) { throw new Exception ( ex . Message + "\r\nIn WebP.EncodeLossless (Simple)" ) ; }
finally
{
//Unlock the pixels
if ( bmpData ! = null )
bmp . UnlockBits ( bmpData ) ;
//Free memory
if ( unmanagedData ! = IntPtr . Zero )
UnsafeNativeMethods . WebPFree ( unmanagedData ) ;
}
}
/// <summary>Lossless encoding image in bitmap (Advanced encoding API)</summary>
/// <param name="bmp">Bitmap with the image</param>
/// <param name="speed">Between 0 (fastest, lowest compression) and 9 (slower, best compression)</param>
/// <returns>Compressed data</returns>
public byte [ ] EncodeLossless ( Bitmap bmp , int speed )
{
//Initialize configuration structure
WebPConfig config = new WebPConfig ( ) ;
//Set compression parameters
if ( UnsafeNativeMethods . WebPConfigInit ( ref config , WebPPreset . WEBP_PRESET_DEFAULT , ( speed + 1 ) * 10 ) = = 0 )
throw new Exception ( "Can´ t config preset" ) ;
//Old version of DLL does not support info and WebPConfigLosslessPreset
if ( UnsafeNativeMethods . WebPGetDecoderVersion ( ) > 1082 )
{
if ( UnsafeNativeMethods . WebPConfigLosslessPreset ( ref config , speed ) = = 0 )
throw new Exception ( "Can´ t configure lossless preset" ) ;
}
else
{
config . lossless = 1 ;
config . method = speed ;
if ( config . method > 6 )
config . method = 6 ;
config . quality = ( speed + 1 ) * 10 ;
}
config . pass = speed + 1 ;
config . thread_level = 1 ;
config . alpha_filtering = 2 ;
config . use_sharp_yuv = 1 ;
config . exact = 0 ;
return AdvancedEncode ( bmp , config , false ) ;
}
/// <summary>Near lossless encoding image in bitmap</summary>
/// <param name="bmp">Bitmap with the image</param>
/// <param name="quality">Between 0 (lower quality, lowest file size) and 100 (highest quality, higher file size)</param>
/// <param name="speed">Between 0 (fastest, lowest compression) and 9 (slower, best compression)</param>
/// <returns>Compress data</returns>
public byte [ ] EncodeNearLossless ( Bitmap bmp , int quality , int speed = 9 )
{
//test DLL version
if ( UnsafeNativeMethods . WebPGetDecoderVersion ( ) < = 1082 )
throw new Exception ( "This DLL version not support EncodeNearLossless" ) ;
//Inicialize config struct
WebPConfig config = new WebPConfig ( ) ;
//Set compression parameters
if ( UnsafeNativeMethods . WebPConfigInit ( ref config , WebPPreset . WEBP_PRESET_DEFAULT , ( speed + 1 ) * 10 ) = = 0 )
throw new Exception ( "Can´ t configure preset" ) ;
if ( UnsafeNativeMethods . WebPConfigLosslessPreset ( ref config , speed ) = = 0 )
throw new Exception ( "Can´ t configure lossless preset" ) ;
config . pass = speed + 1 ;
config . near_lossless = quality ;
config . thread_level = 1 ;
config . alpha_filtering = 2 ;
config . use_sharp_yuv = 1 ;
config . exact = 0 ;
return AdvancedEncode ( bmp , config , false ) ;
}
#endregion
#region | Another Public Functions |
/// <summary>Get the libwebp version</summary>
/// <returns>Version of library</returns>
public string GetVersion ( )
{
try
{
uint v = ( uint ) UnsafeNativeMethods . WebPGetDecoderVersion ( ) ;
var revision = v % 256 ;
var minor = ( v > > 8 ) % 256 ;
var major = ( v > > 16 ) % 256 ;
return major + "." + minor + "." + revision ;
}
catch ( Exception ex ) { throw new Exception ( ex . Message + "\r\nIn WebP.GetVersion" ) ; }
}
/// <summary>Get info of WEBP data</summary>
/// <param name="rawWebP">The data of WebP</param>
/// <param name="width">width of image</param>
/// <param name="height">height of image</param>
/// <param name="has_alpha">Image has alpha channel</param>
/// <param name="has_animation">Image is a animation</param>
/// <param name="format">Format of image: 0 = undefined (/mixed), 1 = lossy, 2 = lossless</param>
public void GetInfo ( byte [ ] rawWebP , out int width , out int height , out bool has_alpha , out bool has_animation , out string format )
{
VP8StatusCode result ;
GCHandle pinnedWebP = GCHandle . Alloc ( rawWebP , GCHandleType . Pinned ) ;
try
{
IntPtr ptrRawWebP = pinnedWebP . AddrOfPinnedObject ( ) ;
WebPBitstreamFeatures features = new WebPBitstreamFeatures ( ) ;
result = UnsafeNativeMethods . WebPGetFeatures ( ptrRawWebP , rawWebP . Length , ref features ) ;
if ( result ! = 0 )
throw new Exception ( result . ToString ( ) ) ;
width = features . Width ;
height = features . Height ;
if ( features . Has_alpha = = 1 ) has_alpha = true ; else has_alpha = false ;
if ( features . Has_animation = = 1 ) has_animation = true ; else has_animation = false ;
switch ( features . Format )
{
case 1 :
format = "lossy" ;
break ;
case 2 :
format = "lossless" ;
break ;
default :
format = "undefined" ;
break ;
}
}
catch ( Exception ex ) { throw new Exception ( ex . Message + "\r\nIn WebP.GetInfo" ) ; }
finally
{
//Free memory
if ( pinnedWebP . IsAllocated )
pinnedWebP . Free ( ) ;
}
}
/// <summary>Compute PSNR, SSIM or LSIM distortion metric between two pictures. Warning: this function is rather CPU-intensive</summary>
/// <param name="source">Picture to measure</param>
/// <param name="reference">Reference picture</param>
/// <param name="metric_type">0 = PSNR, 1 = SSIM, 2 = LSIM</param>
/// <returns>dB in the Y/U/V/Alpha/All order</returns>
public float [ ] GetPictureDistortion ( Bitmap source , Bitmap reference , int metric_type )
{
WebPPicture wpicSource = new WebPPicture ( ) ;
WebPPicture wpicReference = new WebPPicture ( ) ;
BitmapData sourceBmpData = null ;
BitmapData referenceBmpData = null ;
float [ ] result = new float [ 5 ] ;
GCHandle pinnedResult = GCHandle . Alloc ( result , GCHandleType . Pinned ) ;
try
{
if ( source = = null )
throw new Exception ( "Source picture is void" ) ;
if ( reference = = null )
throw new Exception ( "Reference picture is void" ) ;
if ( metric_type > 2 )
throw new Exception ( "Bad metric_type. Use 0 = PSNR, 1 = SSIM, 2 = LSIM" ) ;
if ( source . Width ! = reference . Width | | source . Height ! = reference . Height )
throw new Exception ( "Source and Reference pictures have different dimensions" ) ;
// Setup the source picture data, allocating the bitmap, width and height
sourceBmpData = source . LockBits ( new Rectangle ( 0 , 0 , source . Width , source . Height ) , ImageLockMode . ReadOnly , source . PixelFormat ) ;
wpicSource = new WebPPicture ( ) ;
if ( UnsafeNativeMethods . WebPPictureInitInternal ( ref wpicSource ) ! = 1 )
throw new Exception ( "Can´ t initialize WebPPictureInit" ) ;
wpicSource . width = ( int ) source . Width ;
wpicSource . height = ( int ) source . Height ;
//Put the source bitmap componets in wpic
if ( sourceBmpData . PixelFormat = = PixelFormat . Format32bppArgb )
{
wpicSource . use_argb = 1 ;
if ( UnsafeNativeMethods . WebPPictureImportBGRA ( ref wpicSource , sourceBmpData . Scan0 , sourceBmpData . Stride ) ! = 1 )
throw new Exception ( "Can´ t allocate memory in WebPPictureImportBGR" ) ;
}
else
{
wpicSource . use_argb = 0 ;
if ( UnsafeNativeMethods . WebPPictureImportBGR ( ref wpicSource , sourceBmpData . Scan0 , sourceBmpData . Stride ) ! = 1 )
throw new Exception ( "Can´ t allocate memory in WebPPictureImportBGR" ) ;
}
// Setup the reference picture data, allocating the bitmap, width and height
referenceBmpData = reference . LockBits ( new Rectangle ( 0 , 0 , reference . Width , reference . Height ) , ImageLockMode . ReadOnly , reference . PixelFormat ) ;
wpicReference = new WebPPicture ( ) ;
if ( UnsafeNativeMethods . WebPPictureInitInternal ( ref wpicReference ) ! = 1 )
throw new Exception ( "Can´ t initialize WebPPictureInit" ) ;
wpicReference . width = ( int ) reference . Width ;
wpicReference . height = ( int ) reference . Height ;
wpicReference . use_argb = 1 ;
//Put the source bitmap contents in WebPPicture instance
if ( sourceBmpData . PixelFormat = = PixelFormat . Format32bppArgb )
{
wpicSource . use_argb = 1 ;
if ( UnsafeNativeMethods . WebPPictureImportBGRA ( ref wpicReference , referenceBmpData . Scan0 , referenceBmpData . Stride ) ! = 1 )
throw new Exception ( "Can´ t allocate memory in WebPPictureImportBGR" ) ;
}
else
{
wpicSource . use_argb = 0 ;
if ( UnsafeNativeMethods . WebPPictureImportBGR ( ref wpicReference , referenceBmpData . Scan0 , referenceBmpData . Stride ) ! = 1 )
throw new Exception ( "Can´ t allocate memory in WebPPictureImportBGR" ) ;
}
//Measure
IntPtr ptrResult = pinnedResult . AddrOfPinnedObject ( ) ;
if ( UnsafeNativeMethods . WebPPictureDistortion ( ref wpicSource , ref wpicReference , metric_type , ptrResult ) ! = 1 )
throw new Exception ( "Can´ t measure." ) ;
return result ;
}
catch ( Exception ex ) { throw new Exception ( ex . Message + "\r\nIn WebP.GetPictureDistortion" ) ; }
finally
{
//Unlock the pixels
if ( sourceBmpData ! = null )
source . UnlockBits ( sourceBmpData ) ;
if ( referenceBmpData ! = null )
reference . UnlockBits ( referenceBmpData ) ;
//Free memory
if ( wpicSource . argb ! = IntPtr . Zero )
UnsafeNativeMethods . WebPPictureFree ( ref wpicSource ) ;
if ( wpicReference . argb ! = IntPtr . Zero )
UnsafeNativeMethods . WebPPictureFree ( ref wpicReference ) ;
//Free memory
if ( pinnedResult . IsAllocated )
pinnedResult . Free ( ) ;
}
}
#endregion
#region | Private Methods |
/// <summary>Encoding image using Advanced encoding API</summary>
/// <param name="bmp">Bitmap with the image</param>
/// <param name="config">Configuration for encode</param>
/// <param name="info">True if need encode info.</param>
/// <returns>Compressed data</returns>
private byte [ ] AdvancedEncode ( Bitmap bmp , WebPConfig config , bool info )
{
byte [ ] rawWebP = null ;
byte [ ] dataWebp = null ;
WebPPicture wpic = new WebPPicture ( ) ;
BitmapData bmpData = null ;
WebPAuxStats stats = new WebPAuxStats ( ) ;
IntPtr ptrStats = IntPtr . Zero ;
GCHandle pinnedArrayHandle = new GCHandle ( ) ;
int dataWebpSize ;
try
{
//Validate the configuration
if ( UnsafeNativeMethods . WebPValidateConfig ( ref config ) ! = 1 )
throw new Exception ( "Bad configuration parameters" ) ;
//test bmp
if ( bmp . Width = = 0 | | bmp . Height = = 0 )
throw new ArgumentException ( "Bitmap contains no data." , "bmp" ) ;
if ( bmp . Width > WEBP_MAX_DIMENSION | | bmp . Height > WEBP_MAX_DIMENSION )
throw new NotSupportedException ( "Bitmap's dimension is too large. Max is " + WEBP_MAX_DIMENSION + "x" + WEBP_MAX_DIMENSION + " pixels." ) ;
if ( bmp . PixelFormat ! = PixelFormat . Format24bppRgb & & bmp . PixelFormat ! = PixelFormat . Format32bppArgb )
throw new NotSupportedException ( "Only support Format24bppRgb and Format32bppArgb pixelFormat." ) ;
// Setup the input data, allocating a the bitmap, width and height
bmpData = bmp . LockBits ( new Rectangle ( 0 , 0 , bmp . Width , bmp . Height ) , ImageLockMode . ReadOnly , bmp . PixelFormat ) ;
if ( UnsafeNativeMethods . WebPPictureInitInternal ( ref wpic ) ! = 1 )
throw new Exception ( "Can´ t initialize WebPPictureInit" ) ;
wpic . width = ( int ) bmp . Width ;
wpic . height = ( int ) bmp . Height ;
wpic . use_argb = 1 ;
if ( bmp . PixelFormat = = PixelFormat . Format32bppArgb )
{
//Put the bitmap componets in wpic
int result = UnsafeNativeMethods . WebPPictureImportBGRA ( ref wpic , bmpData . Scan0 , bmpData . Stride ) ;
if ( result ! = 1 )
throw new Exception ( "Can´ t allocate memory in WebPPictureImportBGRA" ) ;
wpic . colorspace = ( uint ) WEBP_CSP_MODE . MODE_bgrA ;
dataWebpSize = bmp . Width * bmp . Height * 32 ;
dataWebp = new byte [ bmp . Width * bmp . Height * 32 ] ; //Memory for WebP output
}
else
{
//Put the bitmap contents in WebPPicture instance
int result = UnsafeNativeMethods . WebPPictureImportBGR ( ref wpic , bmpData . Scan0 , bmpData . Stride ) ;
if ( result ! = 1 )
throw new Exception ( "Can´ t allocate memory in WebPPictureImportBGR" ) ;
dataWebpSize = bmp . Width * bmp . Height * 24 ;
}
//Set up statistics of compression
if ( info )
{
stats = new WebPAuxStats ( ) ;
ptrStats = Marshal . AllocHGlobal ( Marshal . SizeOf ( stats ) ) ;
Marshal . StructureToPtr ( stats , ptrStats , false ) ;
wpic . stats = ptrStats ;
}
//Memory for WebP output
if ( dataWebpSize > 2147483591 )
dataWebpSize = 2147483591 ;
dataWebp = new byte [ bmp . Width * bmp . Height * 32 ] ;
pinnedArrayHandle = GCHandle . Alloc ( dataWebp , GCHandleType . Pinned ) ;
IntPtr initPtr = pinnedArrayHandle . AddrOfPinnedObject ( ) ;
wpic . custom_ptr = initPtr ;
//Set up a byte-writing method (write-to-memory, in this case)
UnsafeNativeMethods . OnCallback = new UnsafeNativeMethods . WebPMemoryWrite ( MyWriter ) ;
wpic . writer = Marshal . GetFunctionPointerForDelegate ( UnsafeNativeMethods . OnCallback ) ;
//compress the input samples
if ( UnsafeNativeMethods . WebPEncode ( ref config , ref wpic ) ! = 1 )
throw new Exception ( "Encoding error: " + ( ( WebPEncodingError ) wpic . error_code ) . ToString ( ) ) ;
//Remove OnCallback
UnsafeNativeMethods . OnCallback = null ;
//Unlock the pixels
bmp . UnlockBits ( bmpData ) ;
bmpData = null ;
//Copy webpData to rawWebP
int size = ( int ) ( ( long ) wpic . custom_ptr - ( long ) initPtr ) ;
rawWebP = new byte [ size ] ;
Array . Copy ( dataWebp , rawWebP , size ) ;
//Remove compression data
pinnedArrayHandle . Free ( ) ;
dataWebp = null ;
//Show statistics
if ( info )
{
stats = ( WebPAuxStats ) Marshal . PtrToStructure ( ptrStats , typeof ( WebPAuxStats ) ) ;
MessageBox . Show ( "Dimension: " + wpic . width + " x " + wpic . height + " pixels\n" +
"Output: " + stats . coded_size + " bytes\n" +
"PSNR Y: " + stats . PSNRY + " db\n" +
"PSNR u: " + stats . PSNRU + " db\n" +
"PSNR v: " + stats . PSNRV + " db\n" +
"PSNR ALL: " + stats . PSNRALL + " db\n" +
"Block intra4: " + stats . block_count_intra4 + "\n" +
"Block intra16: " + stats . block_count_intra16 + "\n" +
"Block skipped: " + stats . block_count_skipped + "\n" +
"Header size: " + stats . header_bytes + " bytes\n" +
"Mode-partition: " + stats . mode_partition_0 + " bytes\n" +
"Macro-blocks 0: " + stats . segment_size_segments0 + " residuals bytes\n" +
"Macro-blocks 1: " + stats . segment_size_segments1 + " residuals bytes\n" +
"Macro-blocks 2: " + stats . segment_size_segments2 + " residuals bytes\n" +
"Macro-blocks 3: " + stats . segment_size_segments3 + " residuals bytes\n" +
"Quantizer 0: " + stats . segment_quant_segments0 + " residuals bytes\n" +
"Quantizer 1: " + stats . segment_quant_segments1 + " residuals bytes\n" +
"Quantizer 2: " + stats . segment_quant_segments2 + " residuals bytes\n" +
"Quantizer 3: " + stats . segment_quant_segments3 + " residuals bytes\n" +
"Filter level 0: " + stats . segment_level_segments0 + " residuals bytes\n" +
"Filter level 1: " + stats . segment_level_segments1 + " residuals bytes\n" +
"Filter level 2: " + stats . segment_level_segments2 + " residuals bytes\n" +
"Filter level 3: " + stats . segment_level_segments3 + " residuals bytes\n" , "Compression statistics" ) ;
}
return rawWebP ;
}
catch ( Exception ex ) { throw new Exception ( ex . Message + "\r\nIn WebP.AdvancedEncode" ) ; }
finally
{
//Free temporal compress memory
if ( pinnedArrayHandle . IsAllocated )
{
pinnedArrayHandle . Free ( ) ;
}
//Free statistics memory
if ( ptrStats ! = IntPtr . Zero )
{
Marshal . FreeHGlobal ( ptrStats ) ;
}
//Unlock the pixels
if ( bmpData ! = null )
{
bmp . UnlockBits ( bmpData ) ;
}
//Free memory
if ( wpic . argb ! = IntPtr . Zero )
{
UnsafeNativeMethods . WebPPictureFree ( ref wpic ) ;
}
}
}
private int MyWriter ( [ InAttribute ( ) ] IntPtr data , UIntPtr data_size , ref WebPPicture picture )
{
UnsafeNativeMethods . CopyMemory ( picture . custom_ptr , data , ( uint ) data_size ) ;
//picture.custom_ptr = IntPtr.Add(picture.custom_ptr, (int)data_size); //Only in .NET > 4.0
picture . custom_ptr = new IntPtr ( picture . custom_ptr . ToInt64 ( ) + ( int ) data_size ) ;
return 1 ;
}
private delegate int MyWriterDelegate ( [ InAttribute ( ) ] IntPtr data , UIntPtr data_size , ref WebPPicture picture ) ;
#endregion
#region | Destruction |
/// <summary>Free memory</summary>
public void Dispose ( )
{
GC . SuppressFinalize ( this ) ;
}
#endregion
}
#region | Import libwebp functions |
[SuppressUnmanagedCodeSecurityAttribute]
internal sealed partial class UnsafeNativeMethods
{
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
internal static extern void CopyMemory ( IntPtr dest , IntPtr src , uint count ) ;
private static readonly int WEBP_DECODER_ABI_VERSION = 0x0208 ;
/// <summary>This function will initialize the configuration according to a predefined set of parameters (referred to by 'preset') and a given quality factor</summary>
/// <param name="config">The WebPConfig structure</param>
/// <param name="preset">Type of image</param>
/// <param name="quality">Quality of compression</param>
/// <returns>0 if error</returns>
internal static int WebPConfigInit ( ref WebPConfig config , WebPPreset preset , float quality )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPConfigInitInternal_x86 ( ref config , preset , quality , WEBP_DECODER_ABI_VERSION ) ;
case 8 :
return WebPConfigInitInternal_x64 ( ref config , preset , quality , WEBP_DECODER_ABI_VERSION ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigInitInternal")]
2023-12-28 16:15:19 +00:00
private static extern int WebPConfigInitInternal_x86 ( ref WebPConfig config , WebPPreset preset , float quality , int WEBP_DECODER_ABI_VERSION ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigInitInternal")]
2023-12-28 16:15:19 +00:00
private static extern int WebPConfigInitInternal_x64 ( ref WebPConfig config , WebPPreset preset , float quality , int WEBP_DECODER_ABI_VERSION ) ;
/// <summary>Get info of WepP image</summary>
/// <param name="rawWebP">Bytes[] of WebP image</param>
/// <param name="data_size">Size of rawWebP</param>
/// <param name="features">Features of WebP image</param>
/// <returns>VP8StatusCode</returns>
internal static VP8StatusCode WebPGetFeatures ( IntPtr rawWebP , int data_size , ref WebPBitstreamFeatures features )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPGetFeaturesInternal_x86 ( rawWebP , ( UIntPtr ) data_size , ref features , WEBP_DECODER_ABI_VERSION ) ;
case 8 :
return WebPGetFeaturesInternal_x64 ( rawWebP , ( UIntPtr ) data_size , ref features , WEBP_DECODER_ABI_VERSION ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetFeaturesInternal")]
2023-12-28 16:15:19 +00:00
private static extern VP8StatusCode WebPGetFeaturesInternal_x86 ( [ InAttribute ( ) ] IntPtr rawWebP , UIntPtr data_size , ref WebPBitstreamFeatures features , int WEBP_DECODER_ABI_VERSION ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetFeaturesInternal")]
2023-12-28 16:15:19 +00:00
private static extern VP8StatusCode WebPGetFeaturesInternal_x64 ( [ InAttribute ( ) ] IntPtr rawWebP , UIntPtr data_size , ref WebPBitstreamFeatures features , int WEBP_DECODER_ABI_VERSION ) ;
/// <summary>Activate the lossless compression mode with the desired efficiency</summary>
/// <param name="config">The WebPConfig struct</param>
/// <param name="level">between 0 (fastest, lowest compression) and 9 (slower, best compression)</param>
/// <returns>0 in case of parameter error</returns>
internal static int WebPConfigLosslessPreset ( ref WebPConfig config , int level )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPConfigLosslessPreset_x86 ( ref config , level ) ;
case 8 :
return WebPConfigLosslessPreset_x64 ( ref config , level ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigLosslessPreset")]
2023-12-28 16:15:19 +00:00
private static extern int WebPConfigLosslessPreset_x86 ( ref WebPConfig config , int level ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigLosslessPreset")]
2023-12-28 16:15:19 +00:00
private static extern int WebPConfigLosslessPreset_x64 ( ref WebPConfig config , int level ) ;
/// <summary>Check that configuration is non-NULL and all configuration parameters are within their valid ranges</summary>
/// <param name="config">The WebPConfig structure</param>
/// <returns>1 if configuration is OK</returns>
internal static int WebPValidateConfig ( ref WebPConfig config )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPValidateConfig_x86 ( ref config ) ;
case 8 :
return WebPValidateConfig_x64 ( ref config ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPValidateConfig")]
2023-12-28 16:15:19 +00:00
private static extern int WebPValidateConfig_x86 ( ref WebPConfig config ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPValidateConfig")]
2023-12-28 16:15:19 +00:00
private static extern int WebPValidateConfig_x64 ( ref WebPConfig config ) ;
/// <summary>Initialize the WebPPicture structure checking the DLL version</summary>
/// <param name="wpic">The WebPPicture structure</param>
/// <returns>1 if not error</returns>
internal static int WebPPictureInitInternal ( ref WebPPicture wpic )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPPictureInitInternal_x86 ( ref wpic , WEBP_DECODER_ABI_VERSION ) ;
case 8 :
return WebPPictureInitInternal_x64 ( ref wpic , WEBP_DECODER_ABI_VERSION ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureInitInternal")]
2023-12-28 16:15:19 +00:00
private static extern int WebPPictureInitInternal_x86 ( ref WebPPicture wpic , int WEBP_DECODER_ABI_VERSION ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureInitInternal")]
2023-12-28 16:15:19 +00:00
private static extern int WebPPictureInitInternal_x64 ( ref WebPPicture wpic , int WEBP_DECODER_ABI_VERSION ) ;
/// <summary>Colorspace conversion function to import RGB samples</summary>
/// <param name="wpic">The WebPPicture structure</param>
/// <param name="bgr">Point to BGR data</param>
/// <param name="stride">stride of BGR data</param>
/// <returns>Returns 0 in case of memory error.</returns>
internal static int WebPPictureImportBGR ( ref WebPPicture wpic , IntPtr bgr , int stride )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPPictureImportBGR_x86 ( ref wpic , bgr , stride ) ;
case 8 :
return WebPPictureImportBGR_x64 ( ref wpic , bgr , stride ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGR")]
2023-12-28 16:15:19 +00:00
private static extern int WebPPictureImportBGR_x86 ( ref WebPPicture wpic , IntPtr bgr , int stride ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGR")]
2023-12-28 16:15:19 +00:00
private static extern int WebPPictureImportBGR_x64 ( ref WebPPicture wpic , IntPtr bgr , int stride ) ;
/// <summary>Color-space conversion function to import RGB samples</summary>
/// <param name="wpic">The WebPPicture structure</param>
/// <param name="bgra">Point to BGRA data</param>
/// <param name="stride">stride of BGRA data</param>
/// <returns>Returns 0 in case of memory error.</returns>
internal static int WebPPictureImportBGRA ( ref WebPPicture wpic , IntPtr bgra , int stride )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPPictureImportBGRA_x86 ( ref wpic , bgra , stride ) ;
case 8 :
return WebPPictureImportBGRA_x64 ( ref wpic , bgra , stride ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRA")]
2023-12-28 16:15:19 +00:00
private static extern int WebPPictureImportBGRA_x86 ( ref WebPPicture wpic , IntPtr bgra , int stride ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRA")]
2023-12-28 16:15:19 +00:00
private static extern int WebPPictureImportBGRA_x64 ( ref WebPPicture wpic , IntPtr bgra , int stride ) ;
/// <summary>Color-space conversion function to import RGB samples</summary>
/// <param name="wpic">The WebPPicture structure</param>
/// <param name="bgr">Point to BGR data</param>
/// <param name="stride">stride of BGR data</param>
/// <returns>Returns 0 in case of memory error.</returns>
internal static int WebPPictureImportBGRX ( ref WebPPicture wpic , IntPtr bgr , int stride )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPPictureImportBGRX_x86 ( ref wpic , bgr , stride ) ;
case 8 :
return WebPPictureImportBGRX_x64 ( ref wpic , bgr , stride ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRX")]
2023-12-28 16:15:19 +00:00
private static extern int WebPPictureImportBGRX_x86 ( ref WebPPicture wpic , IntPtr bgr , int stride ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRX")]
2023-12-28 16:15:19 +00:00
private static extern int WebPPictureImportBGRX_x64 ( ref WebPPicture wpic , IntPtr bgr , int stride ) ;
/// <summary>The writer type for output compress data</summary>
/// <param name="data">Data returned</param>
/// <param name="data_size">Size of data returned</param>
/// <param name="wpic">Picture structure</param>
/// <returns></returns>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate int WebPMemoryWrite ( [ In ( ) ] IntPtr data , UIntPtr data_size , ref WebPPicture wpic ) ;
internal static WebPMemoryWrite OnCallback ;
/// <summary>Compress to WebP format</summary>
/// <param name="config">The configuration structure for compression parameters</param>
/// <param name="picture">'picture' hold the source samples in both YUV(A) or ARGB input</param>
/// <returns>Returns 0 in case of error, 1 otherwise. In case of error, picture->error_code is updated accordingly.</returns>
internal static int WebPEncode ( ref WebPConfig config , ref WebPPicture picture )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPEncode_x86 ( ref config , ref picture ) ;
case 8 :
return WebPEncode_x64 ( ref config , ref picture ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncode")]
2023-12-28 16:15:19 +00:00
private static extern int WebPEncode_x86 ( ref WebPConfig config , ref WebPPicture picture ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncode")]
2023-12-28 16:15:19 +00:00
private static extern int WebPEncode_x64 ( ref WebPConfig config , ref WebPPicture picture ) ;
/// <summary>Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*()
/// Note that this function does _not_ free the memory used by the 'picture' object itself.
/// Besides memory (which is reclaimed) all other fields of 'picture' are preserved</summary>
/// <param name="picture">Picture structure</param>
internal static void WebPPictureFree ( ref WebPPicture picture )
{
switch ( IntPtr . Size )
{
case 4 :
WebPPictureFree_x86 ( ref picture ) ;
break ;
case 8 :
WebPPictureFree_x64 ( ref picture ) ;
break ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureFree")]
2023-12-28 16:15:19 +00:00
private static extern void WebPPictureFree_x86 ( ref WebPPicture wpic ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureFree")]
2023-12-28 16:15:19 +00:00
private static extern void WebPPictureFree_x64 ( ref WebPPicture wpic ) ;
/// <summary>Validate the WebP image header and retrieve the image height and width. Pointers *width and *height can be passed NULL if deemed irrelevant</summary>
/// <param name="data">Pointer to WebP image data</param>
/// <param name="data_size">This is the size of the memory block pointed to by data containing the image data</param>
/// <param name="width">The range is limited currently from 1 to 16383</param>
/// <param name="height">The range is limited currently from 1 to 16383</param>
/// <returns>1 if success, otherwise error code returned in the case of (a) formatting error(s).</returns>
internal static int WebPGetInfo ( IntPtr data , int data_size , out int width , out int height )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPGetInfo_x86 ( data , ( UIntPtr ) data_size , out width , out height ) ;
case 8 :
return WebPGetInfo_x64 ( data , ( UIntPtr ) data_size , out width , out height ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetInfo")]
2023-12-28 16:15:19 +00:00
private static extern int WebPGetInfo_x86 ( [ InAttribute ( ) ] IntPtr data , UIntPtr data_size , out int width , out int height ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetInfo")]
2023-12-28 16:15:19 +00:00
private static extern int WebPGetInfo_x64 ( [ InAttribute ( ) ] IntPtr data , UIntPtr data_size , out int width , out int height ) ;
/// <summary>Decode WEBP image pointed to by *data and returns BGR samples into a preallocated buffer</summary>
/// <param name="data">Pointer to WebP image data</param>
/// <param name="data_size">This is the size of the memory block pointed to by data containing the image data</param>
/// <param name="output_buffer">Pointer to decoded WebP image</param>
/// <param name="output_buffer_size">Size of allocated buffer</param>
/// <param name="output_stride">Specifies the distance between scan lines</param>
internal static void WebPDecodeBGRInto ( IntPtr data , int data_size , IntPtr output_buffer , int output_buffer_size , int output_stride )
{
switch ( IntPtr . Size )
{
case 4 :
if ( WebPDecodeBGRInto_x86 ( data , ( UIntPtr ) data_size , output_buffer , output_buffer_size , output_stride ) = = null )
throw new InvalidOperationException ( "Can not decode WebP" ) ;
break ;
case 8 :
if ( WebPDecodeBGRInto_x64 ( data , ( UIntPtr ) data_size , output_buffer , output_buffer_size , output_stride ) = = null )
throw new InvalidOperationException ( "Can not decode WebP" ) ;
break ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRInto")]
2023-12-28 16:15:19 +00:00
private static extern IntPtr WebPDecodeBGRInto_x86 ( [ InAttribute ( ) ] IntPtr data , UIntPtr data_size , IntPtr output_buffer , int output_buffer_size , int output_stride ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRInto")]
2023-12-28 16:15:19 +00:00
private static extern IntPtr WebPDecodeBGRInto_x64 ( [ InAttribute ( ) ] IntPtr data , UIntPtr data_size , IntPtr output_buffer , int output_buffer_size , int output_stride ) ;
/// <summary>Decode WEBP image pointed to by *data and returns BGRA samples into a preallocated buffer</summary>
/// <param name="data">Pointer to WebP image data</param>
/// <param name="data_size">This is the size of the memory block pointed to by data containing the image data</param>
/// <param name="output_buffer">Pointer to decoded WebP image</param>
/// <param name="output_buffer_size">Size of allocated buffer</param>
/// <param name="output_stride">Specifies the distance between scan lines</param>
internal static void WebPDecodeBGRAInto ( IntPtr data , int data_size , IntPtr output_buffer , int output_buffer_size , int output_stride )
{
switch ( IntPtr . Size )
{
case 4 :
if ( WebPDecodeBGRAInto_x86 ( data , ( UIntPtr ) data_size , output_buffer , output_buffer_size , output_stride ) = = null )
throw new InvalidOperationException ( "Can not decode WebP" ) ;
break ;
case 8 :
if ( WebPDecodeBGRAInto_x64 ( data , ( UIntPtr ) data_size , output_buffer , output_buffer_size , output_stride ) = = null )
throw new InvalidOperationException ( "Can not decode WebP" ) ;
break ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRAInto")]
2023-12-28 16:15:19 +00:00
private static extern IntPtr WebPDecodeBGRAInto_x86 ( [ InAttribute ( ) ] IntPtr data , UIntPtr data_size , IntPtr output_buffer , int output_buffer_size , int output_stride ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRAInto")]
2023-12-28 16:15:19 +00:00
private static extern IntPtr WebPDecodeBGRAInto_x64 ( [ InAttribute ( ) ] IntPtr data , UIntPtr data_size , IntPtr output_buffer , int output_buffer_size , int output_stride ) ;
/// <summary>Decode WEBP image pointed to by *data and returns ARGB samples into a preallocated buffer</summary>
/// <param name="data">Pointer to WebP image data</param>
/// <param name="data_size">This is the size of the memory block pointed to by data containing the image data</param>
/// <param name="output_buffer">Pointer to decoded WebP image</param>
/// <param name="output_buffer_size">Size of allocated buffer</param>
/// <param name="output_stride">Specifies the distance between scan lines</param>
internal static void WebPDecodeARGBInto ( IntPtr data , int data_size , IntPtr output_buffer , int output_buffer_size , int output_stride )
{
switch ( IntPtr . Size )
{
case 4 :
if ( WebPDecodeARGBInto_x86 ( data , ( UIntPtr ) data_size , output_buffer , output_buffer_size , output_stride ) = = null )
throw new InvalidOperationException ( "Can not decode WebP" ) ;
break ;
case 8 :
if ( WebPDecodeARGBInto_x64 ( data , ( UIntPtr ) data_size , output_buffer , output_buffer_size , output_stride ) = = null )
throw new InvalidOperationException ( "Can not decode WebP" ) ;
break ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeARGBInto")]
2023-12-28 16:15:19 +00:00
private static extern IntPtr WebPDecodeARGBInto_x86 ( [ InAttribute ( ) ] IntPtr data , UIntPtr data_size , IntPtr output_buffer , int output_buffer_size , int output_stride ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeARGBInto")]
2023-12-28 16:15:19 +00:00
private static extern IntPtr WebPDecodeARGBInto_x64 ( [ InAttribute ( ) ] IntPtr data , UIntPtr data_size , IntPtr output_buffer , int output_buffer_size , int output_stride ) ;
/// <summary>Initialize the configuration as empty. This function must always be called first, unless WebPGetFeatures() is to be called</summary>
/// <param name="webPDecoderConfig">Configuration structure</param>
/// <returns>False in case of mismatched version.</returns>
internal static int WebPInitDecoderConfig ( ref WebPDecoderConfig webPDecoderConfig )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPInitDecoderConfigInternal_x86 ( ref webPDecoderConfig , WEBP_DECODER_ABI_VERSION ) ;
case 8 :
return WebPInitDecoderConfigInternal_x64 ( ref webPDecoderConfig , WEBP_DECODER_ABI_VERSION ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPInitDecoderConfigInternal")]
2023-12-28 16:15:19 +00:00
private static extern int WebPInitDecoderConfigInternal_x86 ( ref WebPDecoderConfig webPDecoderConfig , int WEBP_DECODER_ABI_VERSION ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPInitDecoderConfigInternal")]
2023-12-28 16:15:19 +00:00
private static extern int WebPInitDecoderConfigInternal_x64 ( ref WebPDecoderConfig webPDecoderConfig , int WEBP_DECODER_ABI_VERSION ) ;
/// <summary>Decodes the full data at once, taking configuration into account</summary>
/// <param name="data">WebP raw data to decode</param>
/// <param name="data_size">Size of WebP data </param>
/// <param name="webPDecoderConfig">Configuration structure</param>
/// <returns>VP8_STATUS_OK if the decoding was successful</returns>
internal static VP8StatusCode WebPDecode ( IntPtr data , int data_size , ref WebPDecoderConfig webPDecoderConfig )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPDecode_x86 ( data , ( UIntPtr ) data_size , ref webPDecoderConfig ) ;
case 8 :
return WebPDecode_x64 ( data , ( UIntPtr ) data_size , ref webPDecoderConfig ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecode")]
2023-12-28 16:15:19 +00:00
private static extern VP8StatusCode WebPDecode_x86 ( IntPtr data , UIntPtr data_size , ref WebPDecoderConfig config ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecode")]
2023-12-28 16:15:19 +00:00
private static extern VP8StatusCode WebPDecode_x64 ( IntPtr data , UIntPtr data_size , ref WebPDecoderConfig config ) ;
/// <summary>Free any memory associated with the buffer. Must always be called last. Doesn't free the 'buffer' structure itself</summary>
/// <param name="buffer">WebPDecBuffer</param>
internal static void WebPFreeDecBuffer ( ref WebPDecBuffer buffer )
{
switch ( IntPtr . Size )
{
case 4 :
WebPFreeDecBuffer_x86 ( ref buffer ) ;
break ;
case 8 :
WebPFreeDecBuffer_x64 ( ref buffer ) ;
break ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFreeDecBuffer")]
2023-12-28 16:15:19 +00:00
private static extern void WebPFreeDecBuffer_x86 ( ref WebPDecBuffer buffer ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFreeDecBuffer")]
2023-12-28 16:15:19 +00:00
private static extern void WebPFreeDecBuffer_x64 ( ref WebPDecBuffer buffer ) ;
/// <summary>Lossy encoding images</summary>
/// <param name="bgr">Pointer to BGR image data</param>
/// <param name="width">The range is limited currently from 1 to 16383</param>
/// <param name="height">The range is limited currently from 1 to 16383</param>
/// <param name="stride">Specifies the distance between scanlines</param>
/// <param name="quality_factor">Ranges from 0 (lower quality) to 100 (highest quality). Controls the loss and quality during compression</param>
/// <param name="output">output_buffer with WebP image</param>
/// <returns>Size of WebP Image or 0 if an error occurred</returns>
internal static int WebPEncodeBGR ( IntPtr bgr , int width , int height , int stride , float quality_factor , out IntPtr output )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPEncodeBGR_x86 ( bgr , width , height , stride , quality_factor , out output ) ;
case 8 :
return WebPEncodeBGR_x64 ( bgr , width , height , stride , quality_factor , out output ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGR")]
2023-12-28 16:15:19 +00:00
private static extern int WebPEncodeBGR_x86 ( [ InAttribute ( ) ] IntPtr bgr , int width , int height , int stride , float quality_factor , out IntPtr output ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGR")]
2023-12-28 16:15:19 +00:00
private static extern int WebPEncodeBGR_x64 ( [ InAttribute ( ) ] IntPtr bgr , int width , int height , int stride , float quality_factor , out IntPtr output ) ;
/// <summary>Lossy encoding images</summary>
/// <param name="bgr">Pointer to BGRA image data</param>
/// <param name="width">The range is limited currently from 1 to 16383</param>
/// <param name="height">The range is limited currently from 1 to 16383</param>
/// <param name="stride">Specifies the distance between scan lines</param>
/// <param name="quality_factor">Ranges from 0 (lower quality) to 100 (highest quality). Controls the loss and quality during compression</param>
/// <param name="output">output_buffer with WebP image</param>
/// <returns>Size of WebP Image or 0 if an error occurred</returns>
internal static int WebPEncodeBGRA ( IntPtr bgra , int width , int height , int stride , float quality_factor , out IntPtr output )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPEncodeBGRA_x86 ( bgra , width , height , stride , quality_factor , out output ) ;
case 8 :
return WebPEncodeBGRA_x64 ( bgra , width , height , stride , quality_factor , out output ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGRA")]
2023-12-28 16:15:19 +00:00
private static extern int WebPEncodeBGRA_x86 ( [ InAttribute ( ) ] IntPtr bgra , int width , int height , int stride , float quality_factor , out IntPtr output ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGRA")]
2023-12-28 16:15:19 +00:00
private static extern int WebPEncodeBGRA_x64 ( [ InAttribute ( ) ] IntPtr bgra , int width , int height , int stride , float quality_factor , out IntPtr output ) ;
/// <summary>Lossless encoding images pointed to by *data in WebP format</summary>
/// <param name="bgr">Pointer to BGR image data</param>
/// <param name="width">The range is limited currently from 1 to 16383</param>
/// <param name="height">The range is limited currently from 1 to 16383</param>
/// <param name="stride">Specifies the distance between scan lines</param>
/// <param name="output">output_buffer with WebP image</param>
/// <returns>Size of WebP Image or 0 if an error occurred</returns>
internal static int WebPEncodeLosslessBGR ( IntPtr bgr , int width , int height , int stride , out IntPtr output )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPEncodeLosslessBGR_x86 ( bgr , width , height , stride , out output ) ;
case 8 :
return WebPEncodeLosslessBGR_x64 ( bgr , width , height , stride , out output ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGR")]
2023-12-28 16:15:19 +00:00
private static extern int WebPEncodeLosslessBGR_x86 ( [ InAttribute ( ) ] IntPtr bgr , int width , int height , int stride , out IntPtr output ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGR")]
2023-12-28 16:15:19 +00:00
private static extern int WebPEncodeLosslessBGR_x64 ( [ InAttribute ( ) ] IntPtr bgr , int width , int height , int stride , out IntPtr output ) ;
/// <summary>Lossless encoding images pointed to by *data in WebP format</summary>
/// <param name="bgra">Pointer to BGRA image data</param>
/// <param name="width">The range is limited currently from 1 to 16383</param>
/// <param name="height">The range is limited currently from 1 to 16383</param>
/// <param name="stride">Specifies the distance between scan lines</param>
/// <param name="output">output_buffer with WebP image</param>
/// <returns>Size of WebP Image or 0 if an error occurred</returns>
internal static int WebPEncodeLosslessBGRA ( IntPtr bgra , int width , int height , int stride , out IntPtr output )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPEncodeLosslessBGRA_x86 ( bgra , width , height , stride , out output ) ;
case 8 :
return WebPEncodeLosslessBGRA_x64 ( bgra , width , height , stride , out output ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGRA")]
2023-12-28 16:15:19 +00:00
private static extern int WebPEncodeLosslessBGRA_x86 ( [ InAttribute ( ) ] IntPtr bgra , int width , int height , int stride , out IntPtr output ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGRA")]
2023-12-28 16:15:19 +00:00
private static extern int WebPEncodeLosslessBGRA_x64 ( [ InAttribute ( ) ] IntPtr bgra , int width , int height , int stride , out IntPtr output ) ;
/// <summary>Releases memory returned by the WebPEncode</summary>
/// <param name="p">Pointer to memory</param>
internal static void WebPFree ( IntPtr p )
{
switch ( IntPtr . Size )
{
case 4 :
WebPFree_x86 ( p ) ;
break ;
case 8 :
WebPFree_x64 ( p ) ;
break ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFree")]
2023-12-28 16:15:19 +00:00
private static extern void WebPFree_x86 ( IntPtr p ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFree")]
2023-12-28 16:15:19 +00:00
private static extern void WebPFree_x64 ( IntPtr p ) ;
/// <summary>Get the WebP version library</summary>
/// <returns>8bits for each of major/minor/revision packet in integer. E.g: v2.5.7 is 0x020507</returns>
internal static int WebPGetDecoderVersion ( )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPGetDecoderVersion_x86 ( ) ;
case 8 :
return WebPGetDecoderVersion_x64 ( ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetDecoderVersion")]
2023-12-28 16:15:19 +00:00
private static extern int WebPGetDecoderVersion_x86 ( ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetDecoderVersion")]
2023-12-28 16:15:19 +00:00
private static extern int WebPGetDecoderVersion_x64 ( ) ;
/// <summary>Compute PSNR, SSIM or LSIM distortion metric between two pictures</summary>
/// <param name="srcPicture">Picture to measure</param>
/// <param name="refPicture">Reference picture</param>
/// <param name="metric_type">0 = PSNR, 1 = SSIM, 2 = LSIM</param>
/// <param name="pResult">dB in the Y/U/V/Alpha/All order</param>
/// <returns>False in case of error (the two pictures don't have same dimension, ...)</returns>
internal static int WebPPictureDistortion ( ref WebPPicture srcPicture , ref WebPPicture refPicture , int metric_type , IntPtr pResult )
{
switch ( IntPtr . Size )
{
case 4 :
return WebPPictureDistortion_x86 ( ref srcPicture , ref refPicture , metric_type , pResult ) ;
case 8 :
return WebPPictureDistortion_x64 ( ref srcPicture , ref refPicture , metric_type , pResult ) ;
default :
throw new InvalidOperationException ( "Invalid platform. Can not find proper function" ) ;
}
}
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureDistortion")]
2023-12-28 16:15:19 +00:00
private static extern int WebPPictureDistortion_x86 ( ref WebPPicture srcPicture , ref WebPPicture refPicture , int metric_type , IntPtr pResult ) ;
2023-12-28 16:28:12 +00:00
[DllImport("Resources/libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureDistortion")]
2023-12-28 16:15:19 +00:00
private static extern int WebPPictureDistortion_x64 ( ref WebPPicture srcPicture , ref WebPPicture refPicture , int metric_type , IntPtr pResult ) ;
}
#endregion
#region | Predefined |
/// <summary>Enumerate some predefined settings for WebPConfig, depending on the type of source picture. These presets are used when calling WebPConfigPreset()</summary>
internal enum WebPPreset
{
/// <summary>Default preset</summary>
WEBP_PRESET_DEFAULT = 0 ,
/// <summary>Digital picture, like portrait, inner shot</summary>
WEBP_PRESET_PICTURE ,
/// <summary>Outdoor photograph, with natural lighting</summary>
WEBP_PRESET_PHOTO ,
/// <summary>Hand or line drawing, with high-contrast details</summary>
WEBP_PRESET_DRAWING ,
/// <summary>Small-sized colorful images</summary>
WEBP_PRESET_ICON ,
/// <summary>Text-like</summary>
WEBP_PRESET_TEXT
} ;
/// <summary>Encoding error conditions</summary>
internal enum WebPEncodingError
{
/// <summary>No error</summary>
VP8_ENC_OK = 0 ,
/// <summary>Memory error allocating objects</summary>
VP8_ENC_ERROR_OUT_OF_MEMORY ,
/// <summary>Memory error while flushing bits</summary>
VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY ,
/// <summary>A pointer parameter is NULL</summary>
VP8_ENC_ERROR_NULL_PARAMETER ,
/// <summary>Configuration is invalid</summary>
VP8_ENC_ERROR_INVALID_CONFIGURATION ,
/// <summary>Picture has invalid width/height</summary>
VP8_ENC_ERROR_BAD_DIMENSION ,
/// <summary>Partition is bigger than 512k</summary>
VP8_ENC_ERROR_PARTITION0_OVERFLOW ,
/// <summary>Partition is bigger than 16M</summary>
VP8_ENC_ERROR_PARTITION_OVERFLOW ,
/// <summary>Error while flushing bytes</summary>
VP8_ENC_ERROR_BAD_WRITE ,
/// <summary>File is bigger than 4G</summary>
VP8_ENC_ERROR_FILE_TOO_BIG ,
/// <summary>Abort request by user</summary>
VP8_ENC_ERROR_USER_ABORT ,
/// <summary>List terminator. Always last</summary>
VP8_ENC_ERROR_LAST ,
}
/// <summary>Enumeration of the status codes</summary>
internal enum VP8StatusCode
{
/// <summary>No error</summary>
VP8_STATUS_OK = 0 ,
/// <summary>Memory error allocating objects</summary>
VP8_STATUS_OUT_OF_MEMORY ,
/// <summary>Configuration is invalid</summary>
VP8_STATUS_INVALID_PARAM ,
VP8_STATUS_BITSTREAM_ERROR ,
/// <summary>Configuration is invalid</summary>
VP8_STATUS_UNSUPPORTED_FEATURE ,
VP8_STATUS_SUSPENDED ,
/// <summary>Abort request by user</summary>
VP8_STATUS_USER_ABORT ,
VP8_STATUS_NOT_ENOUGH_DATA ,
}
/// <summary>Image characteristics hint for the underlying encoder</summary>
internal enum WebPImageHint
{
/// <summary>Default preset</summary>
WEBP_HINT_DEFAULT = 0 ,
/// <summary>Digital picture, like portrait, inner shot</summary>
WEBP_HINT_PICTURE ,
/// <summary>Outdoor photograph, with natural lighting</summary>
WEBP_HINT_PHOTO ,
/// <summary>Discrete tone image (graph, map-tile etc)</summary>
WEBP_HINT_GRAPH ,
/// <summary>List terminator. Always last</summary>
WEBP_HINT_LAST
} ;
/// <summary>Describes the byte-ordering of packed samples in memory</summary>
internal enum WEBP_CSP_MODE
{
/// <summary>Byte-order: R,G,B,R,G,B,..</summary>
MODE_RGB = 0 ,
/// <summary>Byte-order: R,G,B,A,R,G,B,A,..</summary>
MODE_RGBA = 1 ,
/// <summary>Byte-order: B,G,R,B,G,R,..</summary>
MODE_BGR = 2 ,
/// <summary>Byte-order: B,G,R,A,B,G,R,A,..</summary>
MODE_BGRA = 3 ,
/// <summary>Byte-order: A,R,G,B,A,R,G,B,..</summary>
MODE_ARGB = 4 ,
/// <summary>Byte-order: RGB-565: [a4 a3 a2 a1 a0 r5 r4 r3], [r2 r1 r0 g4 g3 g2 g1 g0], ...
/// WEBP_SWAP_16BITS_CSP is defined,
/// Byte-order: RGB-565: [a4 a3 a2 a1 a0 b5 b4 b3], [b2 b1 b0 g4 g3 g2 g1 g0], ..</summary>
MODE_RGBA_4444 = 5 ,
/// <summary>Byte-order: RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ...
/// WEBP_SWAP_16BITS_CSP is defined,
/// Byte-order: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ..</summary>
MODE_RGB_565 = 6 ,
/// <summary>RGB-premultiplied transparent modes (alpha value is preserved)</summary>
MODE_rgbA = 7 ,
/// <summary>RGB-premultiplied transparent modes (alpha value is preserved)</summary>
MODE_bgrA = 8 ,
/// <summary>RGB-premultiplied transparent modes (alpha value is preserved)</summary>
MODE_Argb = 9 ,
/// <summary>RGB-premultiplied transparent modes (alpha value is preserved)</summary>
MODE_rgbA_4444 = 10 ,
/// <summary>YUV 4:2:0</summary>
MODE_YUV = 11 ,
/// <summary>YUV 4:2:0</summary>
MODE_YUVA = 12 ,
/// <summary>MODE_LAST -> 13</summary>
MODE_LAST = 13 ,
}
/// <summary>
/// Decoding states. State normally flows as:
/// WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and
/// WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image.
/// If there is any error the decoder goes into state ERROR.
/// </summary>
internal enum DecState
{
STATE_WEBP_HEADER , // All the data before that of the VP8/VP8L chunk.
STATE_VP8_HEADER , // The VP8 Frame header (within the VP8 chunk).
STATE_VP8_PARTS0 ,
STATE_VP8_DATA ,
STATE_VP8L_HEADER ,
STATE_VP8L_DATA ,
STATE_DONE ,
STATE_ERROR
} ;
#endregion
#region | libwebp structs |
/// <summary>Features gathered from the bit stream</summary>
[StructLayoutAttribute(LayoutKind.Sequential)]
internal struct WebPBitstreamFeatures
{
/// <summary>Width in pixels, as read from the bit stream</summary>
public int Width ;
/// <summary>Height in pixels, as read from the bit stream</summary>
public int Height ;
/// <summary>True if the bit stream contains an alpha channel</summary>
public int Has_alpha ;
/// <summary>True if the bit stream is an animation</summary>
public int Has_animation ;
/// <summary>0 = undefined (/mixed), 1 = lossy, 2 = lossless</summary>
public int Format ;
/// <summary>Padding for later use</summary>
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.U4)]
private readonly uint [ ] pad ;
} ;
/// <summary>Compression parameters</summary>
[StructLayoutAttribute(LayoutKind.Sequential)]
internal struct WebPConfig
{
/// <summary>Lossless encoding (0=lossy(default), 1=lossless)</summary>
public int lossless ;
/// <summary>Between 0 (smallest file) and 100 (biggest)</summary>
public float quality ;
/// <summary>Quality/speed trade-off (0=fast, 6=slower-better)</summary>
public int method ;
/// <summary>Hint for image type (lossless only for now)</summary>
public WebPImageHint image_hint ;
/// <summary>If non-zero, set the desired target size in bytes. Takes precedence over the 'compression' parameter</summary>
public int target_size ;
/// <summary>If non-zero, specifies the minimal distortion to try to achieve. Takes precedence over target_size</summary>
public float target_PSNR ;
/// <summary>Maximum number of segments to use, in [1..4]</summary>
public int segments ;
/// <summary>Spatial Noise Shaping. 0=off, 100=maximum</summary>
public int sns_strength ;
/// <summary>Range: [0 = off .. 100 = strongest]</summary>
public int filter_strength ;
/// <summary>Range: [0 = off .. 7 = least sharp]</summary>
public int filter_sharpness ;
/// <summary>Filtering type: 0 = simple, 1 = strong (only used if filter_strength > 0 or auto-filter > 0)</summary>
public int filter_type ;
/// <summary>Auto adjust filter's strength [0 = off, 1 = on]</summary>
public int autofilter ;
/// <summary>Algorithm for encoding the alpha plane (0 = none, 1 = compressed with WebP lossless). Default is 1</summary>
public int alpha_compression ;
/// <summary>Predictive filtering method for alpha plane. 0: none, 1: fast, 2: best. Default if 1</summary>
public int alpha_filtering ;
/// <summary>Between 0 (smallest size) and 100 (lossless). Default is 100</summary>
public int alpha_quality ;
/// <summary>Number of entropy-analysis passes (in [1..10])</summary>
public int pass ;
/// <summary>If true, export the compressed picture back. In-loop filtering is not applied</summary>
public int show_compressed ;
/// <summary>Preprocessing filter (0=none, 1=segment-smooth, 2=pseudo-random dithering)</summary>
public int preprocessing ;
/// <summary>Log2(number of token partitions) in [0..3] Default is set to 0 for easier progressive decoding</summary>
public int partitions ;
/// <summary>Quality degradation allowed to fit the 512k limit on prediction modes coding (0: no degradation, 100: maximum possible degradation)</summary>
public int partition_limit ;
/// <summary>If true, compression parameters will be remapped to better match the expected output size from JPEG compression. Generally, the output size will be similar but the degradation will be lower</summary>
public int emulate_jpeg_size ;
/// <summary>If non-zero, try and use multi-threaded encoding</summary>
public int thread_level ;
/// <summary>If set, reduce memory usage (but increase CPU use)</summary>
public int low_memory ;
/// <summary>Near lossless encoding [0 = max loss .. 100 = off (default)]</summary>
public int near_lossless ;
/// <summary>If non-zero, preserve the exact RGB values under transparent area. Otherwise, discard this invisible RGB information for better compression. The default value is 0</summary>
public int exact ;
/// <summary>Reserved for future lossless feature</summary>
public int delta_palettization ;
/// <summary>If needed, use sharp (and slow) RGB->YUV conversion</summary>
public int use_sharp_yuv ;
/// <summary>Padding for later use</summary>
private readonly int pad1 ;
private readonly int pad2 ;
} ;
/// <summary>Main exchange structure (input samples, output bytes, statistics)</summary>
[StructLayoutAttribute(LayoutKind.Sequential)]
internal struct WebPPicture
{
/// <summary>Main flag for encoder selecting between ARGB or YUV input. Recommended to use ARGB input (*argb, argb_stride) for lossless, and YUV input (*y, *u, *v, etc.) for lossy</summary>
public int use_argb ;
/// <summary>Color-space: should be YUV420 for now (=Y'CbCr). Value = 0</summary>
public UInt32 colorspace ;
/// <summary>Width of picture (less or equal to WEBP_MAX_DIMENSION)</summary>
public int width ;
/// <summary>Height of picture (less or equal to WEBP_MAX_DIMENSION)</summary>
public int height ;
/// <summary>Pointer to luma plane</summary>
public IntPtr y ;
/// <summary>Pointer to chroma U plane</summary>
public IntPtr u ;
/// <summary>Pointer to chroma V plane</summary>
public IntPtr v ;
/// <summary>Luma stride</summary>
public int y_stride ;
/// <summary>Chroma stride</summary>
public int uv_stride ;
/// <summary>Pointer to the alpha plane</summary>
public IntPtr a ;
/// <summary>stride of the alpha plane</summary>
public int a_stride ;
/// <summary>Padding for later use</summary>
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
private readonly uint [ ] pad1 ;
/// <summary>Pointer to ARGB (32 bit) plane</summary>
public IntPtr argb ;
/// <summary>This is stride in pixels units, not bytes</summary>
public int argb_stride ;
/// <summary>Padding for later use</summary>
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U4)]
private readonly uint [ ] pad2 ;
/// <summary>Byte-emission hook, to store compressed bytes as they are ready</summary>
public IntPtr writer ;
/// <summary>Can be used by the writer</summary>
public IntPtr custom_ptr ;
// map for extra information (only for lossy compression mode)
/// <summary>1: intra type, 2: segment, 3: quant, 4: intra-16 prediction mode, 5: chroma prediction mode, 6: bit cost, 7: distortion</summary>
public int extra_info_type ;
/// <summary>If not NULL, points to an array of size ((width + 15) / 16) * ((height + 15) / 16) that will be filled with a macroblock map, depending on extra_info_type</summary>
public IntPtr extra_info ;
/// <summary>Pointer to side statistics (updated only if not NULL)</summary>
public IntPtr stats ;
/// <summary>Error code for the latest error encountered during encoding</summary>
public UInt32 error_code ;
/// <summary>If not NULL, report progress during encoding</summary>
public IntPtr progress_hook ;
/// <summary>This field is free to be set to any value and used during callbacks (like progress-report e.g.)</summary>
public IntPtr user_data ;
/// <summary>Padding for later use</summary>
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 13, ArraySubType = UnmanagedType.U4)]
private readonly uint [ ] pad3 ;
/// <summary>Row chunk of memory for YUVA planes</summary>
private readonly IntPtr memory_ ;
/// <summary>Row chunk of memory for ARGB planes</summary>
private readonly IntPtr memory_argb_ ;
/// <summary>Padding for later use</summary>
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
private readonly uint [ ] pad4 ;
} ;
/// <summary>Structure for storing auxiliary statistics (mostly for lossy encoding)</summary>
[StructLayoutAttribute(LayoutKind.Sequential)]
internal struct WebPAuxStats
{
/// <summary>Final size</summary>
public int coded_size ;
/// <summary>Peak-signal-to-noise ratio for Y</summary>
public float PSNRY ;
/// <summary>Peak-signal-to-noise ratio for U</summary>
public float PSNRU ;
/// <summary>Peak-signal-to-noise ratio for V</summary>
public float PSNRV ;
/// <summary>Peak-signal-to-noise ratio for All</summary>
public float PSNRALL ;
/// <summary>Peak-signal-to-noise ratio for Alpha</summary>
public float PSNRAlpha ;
/// <summary>Number of intra4</summary>
public int block_count_intra4 ;
/// <summary>Number of intra16</summary>
public int block_count_intra16 ;
/// <summary>Number of skipped macro-blocks</summary>
public int block_count_skipped ;
/// <summary>Approximate number of bytes spent for header</summary>
public int header_bytes ;
/// <summary>Approximate number of bytes spent for mode-partition #0</summary>
public int mode_partition_0 ;
/// <summary>Approximate number of bytes spent for DC coefficients for segment 0</summary>
public int residual_bytes_DC_segments0 ;
/// <summary>Approximate number of bytes spent for AC coefficients for segment 0</summary>
public int residual_bytes_AC_segments0 ;
/// <summary>Approximate number of bytes spent for UV coefficients for segment 0</summary>
public int residual_bytes_uv_segments0 ;
/// <summary>Approximate number of bytes spent for DC coefficients for segment 1</summary>
public int residual_bytes_DC_segments1 ;
/// <summary>Approximate number of bytes spent for AC coefficients for segment 1</summary>
public int residual_bytes_AC_segments1 ;
/// <summary>Approximate number of bytes spent for UV coefficients for segment 1</summary>
public int residual_bytes_uv_segments1 ;
/// <summary>Approximate number of bytes spent for DC coefficients for segment 2</summary>
public int residual_bytes_DC_segments2 ;
/// <summary>Approximate number of bytes spent for AC coefficients for segment 2</summary>
public int residual_bytes_AC_segments2 ;
/// <summary>Approximate number of bytes spent for UV coefficients for segment 2</summary>
public int residual_bytes_uv_segments2 ;
/// <summary>Approximate number of bytes spent for DC coefficients for segment 3</summary>
public int residual_bytes_DC_segments3 ;
/// <summary>Approximate number of bytes spent for AC coefficients for segment 3</summary>
public int residual_bytes_AC_segments3 ;
/// <summary>Approximate number of bytes spent for UV coefficients for segment 3</summary>
public int residual_bytes_uv_segments3 ;
/// <summary>Number of macro-blocks in segments 0</summary>
public int segment_size_segments0 ;
/// <summary>Number of macro-blocks in segments 1</summary>
public int segment_size_segments1 ;
/// <summary>Number of macro-blocks in segments 2</summary>
public int segment_size_segments2 ;
/// <summary>Number of macro-blocks in segments 3</summary>
public int segment_size_segments3 ;
/// <summary>Quantizer values for segment 0</summary>
public int segment_quant_segments0 ;
/// <summary>Quantizer values for segment 1</summary>
public int segment_quant_segments1 ;
/// <summary>Quantizer values for segment 2</summary>
public int segment_quant_segments2 ;
/// <summary>Quantizer values for segment 3</summary>
public int segment_quant_segments3 ;
/// <summary>Filtering strength for segment 0 [0..63]</summary>
public int segment_level_segments0 ;
/// <summary>Filtering strength for segment 1 [0..63]</summary>
public int segment_level_segments1 ;
/// <summary>Filtering strength for segment 2 [0..63]</summary>
public int segment_level_segments2 ;
/// <summary>Filtering strength for segment 3 [0..63]</summary>
public int segment_level_segments3 ;
/// <summary>Size of the transparency data</summary>
public int alpha_data_size ;
/// <summary>Size of the enhancement layer data</summary>
public int layer_data_size ;
// lossless encoder statistics
/// <summary>bit0:predictor bit1:cross-color transform bit2:subtract-green bit3:color indexing</summary>
public Int32 lossless_features ;
/// <summary>Number of precision bits of histogram</summary>
public int histogram_bits ;
/// <summary>Precision bits for transform</summary>
public int transform_bits ;
/// <summary>Number of bits for color cache lookup</summary>
public int cache_bits ;
/// <summary>Number of color in palette, if used</summary>
public int palette_size ;
/// <summary>Final lossless size</summary>
public int lossless_size ;
/// <summary>Lossless header (transform, Huffman, etc) size</summary>
public int lossless_hdr_size ;
/// <summary>Lossless image data size</summary>
public int lossless_data_size ;
/// <summary>Padding for later use</summary>
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
private readonly uint [ ] pad ;
} ;
[StructLayoutAttribute(LayoutKind.Sequential)]
internal struct WebPDecoderConfig
{
/// <summary>Immutable bit stream features (optional)</summary>
public WebPBitstreamFeatures input ;
/// <summary>Output buffer (can point to external memory)</summary>
public WebPDecBuffer output ;
/// <summary>Decoding options</summary>
public WebPDecoderOptions options ;
}
/// <summary>Output buffer</summary>
[StructLayoutAttribute(LayoutKind.Sequential)]
internal struct WebPDecBuffer
{
/// <summary>Color space</summary>
public WEBP_CSP_MODE colorspace ;
/// <summary>Width of image</summary>
public int width ;
/// <summary>Height of image</summary>
public int height ;
/// <summary>If non-zero, 'internal_memory' pointer is not used. If value is '2' or more, the external memory is considered 'slow' and multiple read/write will be avoided</summary>
public int is_external_memory ;
/// <summary>Output buffer parameters</summary>
public RGBA_YUVA_Buffer u ;
/// <summary>Padding for later use</summary>
private readonly UInt32 pad1 ;
/// <summary>Padding for later use</summary>
private readonly UInt32 pad2 ;
/// <summary>Padding for later use</summary>
private readonly UInt32 pad3 ;
/// <summary>Padding for later use</summary>
private readonly UInt32 pad4 ;
/// <summary>Internally allocated memory (only when is_external_memory is 0). Should not be used externally, but accessed via WebPRGBABuffer</summary>
public IntPtr private_memory ;
}
/// <summary>Union of buffer parameters</summary>
[StructLayoutAttribute(LayoutKind.Explicit)]
internal struct RGBA_YUVA_Buffer
{
[FieldOffsetAttribute(0)]
public WebPRGBABuffer RGBA ;
[FieldOffsetAttribute(0)]
public WebPYUVABuffer YUVA ;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
internal struct WebPYUVABuffer
{
/// <summary>Pointer to luma samples</summary>
public IntPtr y ;
/// <summary>Pointer to chroma U samples</summary>
public IntPtr u ;
/// <summary>Pointer to chroma V samples</summary>
public IntPtr v ;
/// <summary>Pointer to alpha samples</summary>
public IntPtr a ;
/// <summary>Luma stride</summary>
public int y_stride ;
/// <summary>Chroma U stride</summary>
public int u_stride ;
/// <summary>Chroma V stride</summary>
public int v_stride ;
/// <summary>Alpha stride</summary>
public int a_stride ;
/// <summary>Luma plane size</summary>
public UIntPtr y_size ;
/// <summary>Chroma plane U size</summary>
public UIntPtr u_size ;
/// <summary>Chroma plane V size</summary>
public UIntPtr v_size ;
/// <summary>Alpha plane size</summary>
public UIntPtr a_size ;
}
/// <summary>Generic structure for describing the output sample buffer</summary>
[StructLayoutAttribute(LayoutKind.Sequential)]
internal struct WebPRGBABuffer
{
/// <summary>Pointer to RGBA samples</summary>
public IntPtr rgba ;
/// <summary>Stride in bytes from one scanline to the next</summary>
public int stride ;
/// <summary>Total size of the RGBA buffer</summary>
public UIntPtr size ;
}
/// <summary>Decoding options</summary>
[StructLayout(LayoutKind.Sequential)]
public struct WebPDecoderOptions
{
/// <summary>If true, skip the in-loop filtering</summary>
public int bypass_filtering ;
/// <summary>If true, use faster point-wise up-sampler</summary>
public int no_fancy_upsampling ;
/// <summary>If true, cropping is applied _first_</summary>
public int use_cropping ;
/// <summary>Left position for cropping. Will be snapped to even values</summary>
public int crop_left ;
/// <summary>Top position for cropping. Will be snapped to even values</summary>
public int crop_top ;
/// <summary>Width of the cropping area</summary>
public int crop_width ;
/// <summary>Height of the cropping area</summary>
public int crop_height ;
/// <summary>If true, scaling is applied _afterward_</summary>
public int use_scaling ;
/// <summary>Final width</summary>
public int scaled_width ;
/// <summary>Final height</summary>
public int scaled_height ;
/// <summary>If true, use multi-threaded decoding</summary>
public int use_threads ;
/// <summary>Dithering strength (0=Off, 100=full)</summary>
public int dithering_strength ;
/// <summary>Flip output vertically</summary>
public int flip ;
/// <summary>Alpha dithering strength in [0..100]</summary>
public int alpha_dithering_strength ;
/// <summary>Padding for later use</summary>
private readonly UInt32 pad1 ;
/// <summary>Padding for later use</summary>
private readonly UInt32 pad2 ;
/// <summary>Padding for later use</summary>
private readonly UInt32 pad3 ;
/// <summary>Padding for later use</summary>
private readonly UInt32 pad4 ;
/// <summary>Padding for later use</summary>
private readonly UInt32 pad5 ;
} ;
#endregion
}