첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
2.41MB

▶ DecodingState.cs

namespace TestProject
{
    /// <summary>
    /// 디코딩 상태
    /// </summary>
    public enum DecodingState
    {
        /// <summary>
        /// STATE_WEBP_HEADER
        /// </summary>
        STATE_WEBP_HEADER,

        /// <summary>
        /// STATE_VP8_HEADER
        /// </summary>
        STATE_VP8_HEADER,

        /// <summary>
        /// STATE_VP8_PARTS0
        /// </summary>
        STATE_VP8_PARTS0,

        /// <summary>
        /// STATE_VP8_DATA
        /// </summary>
        STATE_VP8_DATA,

        /// <summary>
        /// STATE_VP8L_HEADER
        /// </summary>
        STATE_VP8L_HEADER,

        /// <summary>
        /// STATE_VP8L_DATA
        /// </summary>
        STATE_VP8L_DATA,

        /// <summary>
        /// STATE_DONE
        /// </summary>
        STATE_DONE,

        /// <summary>
        /// STATE_ERROR
        /// </summary>
        STATE_ERROR
    };
}

 

728x90

 

▶ VP8StatusCode.cs

namespace TestProject
{
    /// <summary>
    /// VP8 상태 코드
    /// </summary>
    public enum VP8StatusCode
    {
        /// <summary>
        /// VP8_STATUS_OK
        /// </summary>
        VP8_STATUS_OK = 0,

        /// <summary>
        /// VP8_STATUS_OUT_OF_MEMORY
        /// </summary>
        VP8_STATUS_OUT_OF_MEMORY,

        /// <summary>
        /// VP8_STATUS_INVALID_PARAMETER
        /// </summary>
        VP8_STATUS_INVALID_PARAMETER,

        /// <summary>
        /// VP8_STATUS_BIT_STREAM_ERROR
        /// </summary>
        VP8_STATUS_BIT_STREAM_ERROR,

        /// <summary>
        /// VP8_STATUS_UNSUPPORTED_FEATURE
        /// </summary>
        VP8_STATUS_UNSUPPORTED_FEATURE,

        /// <summary>
        /// VP8_STATUS_SUSPENDED
        /// </summary>
        VP8_STATUS_SUSPENDED,

        /// <summary>
        /// VP8_STATUS_USER_ABORT
        /// </summary>
        VP8_STATUS_USER_ABORT,

        /// <summary>
        /// VP8_STATUS_NOT_ENOUGH_DATA
        /// </summary>
        VP8_STATUS_NOT_ENOUGH_DATA
    }
}

 

반응형

 

▶ WEBP_CSP_MODE.cs

namespace TestProject
{
    /// <summary>
    /// WEBP CSP 모드
    /// </summary>
    public enum WEBP_CSP_MODE
    {
        /// <summary>
        /// MODE_RGB
        /// </summary>
        MODE_RGB = 0,

        /// <summary>
        /// MODE_RGBA
        /// </summary>
        MODE_RGBA = 1,

        /// <summary>
        /// MODE_BGR
        /// </summary>
        MODE_BGR = 2,

        /// <summary>
        /// MODE_BGRA
        /// </summary>
        MODE_BGRA = 3,

        /// <summary>
        /// MODE_ARGB
        /// </summary>
        MODE_ARGB = 4,

        /// <summary>
        /// MODE_RGBA_4444
        /// </summary>
        MODE_RGBA_4444 = 5,

        /// <summary>
        /// MODE_RGB_565
        /// </summary>
        MODE_RGB_565 = 6,

        /// <summary>
        /// MODE_rgbA
        /// </summary>
        MODE_rgbA = 7,

        /// <summary>
        /// MODE_bgrA
        /// </summary>
        MODE_bgrA = 8,

        /// <summary>
        /// MODE_Argb
        /// </summary>
        MODE_Argb = 9,

        /// <summary>
        /// MODE_rgbA_4444
        /// </summary>
        MODE_rgbA_4444 = 10,

        /// <summary>
        /// MODE_YUV
        /// </summary>
        MODE_YUV = 11,

        /// <summary>
        /// MODE_YUVA
        /// </summary>
        MODE_YUVA = 12,

        /// <summary>
        /// MODE_LAST
        /// </summary>
        MODE_LAST = 13
    }
}

 

300x250

 

▶ WEBPEncodingError.cs

namespace TestProject
{
    /// <summary>
    /// WEBP 인코딩 에러
    /// </summary>
    public enum WEBPEncodingError
    {
        /// <summary>
        /// VP8_ENC_OK
        /// </summary>
        VP8_ENC_OK = 0,

        /// <summary>
        /// VP8_ENC_ERROR_OUT_OF_MEMORY
        /// </summary>
        VP8_ENC_ERROR_OUT_OF_MEMORY,

        /// <summary>
        /// VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY
        /// </summary>
        VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY,

        /// <summary>
        /// VP8_ENC_ERROR_NULL_PARAMETER
        /// </summary>
        VP8_ENC_ERROR_NULL_PARAMETER,

        /// <summary>
        /// VP8_ENC_ERROR_INVALID_CONFIGURATION
        /// </summary>
        VP8_ENC_ERROR_INVALID_CONFIGURATION,

        /// <summary>
        /// VP8_ENC_ERROR_BAD_DIMENSION
        /// </summary>
        VP8_ENC_ERROR_BAD_DIMENSION,

        /// <summary>
        /// VP8_ENC_ERROR_PARTITION0_OVERFLOW
        /// </summary>
        VP8_ENC_ERROR_PARTITION0_OVERFLOW,

        /// <summary>
        /// VP8_ENC_ERROR_PARTITION_OVERFLOW
        /// </summary>
        VP8_ENC_ERROR_PARTITION_OVERFLOW,

        /// <summary>
        /// VP8_ENC_ERROR_BAD_WRITE
        /// </summary>
        VP8_ENC_ERROR_BAD_WRITE,

        /// <summary>
        /// VP8_ENC_ERROR_FILE_TOO_BIG
        /// </summary>
        VP8_ENC_ERROR_FILE_TOO_BIG,

        /// <summary>
        /// VP8_ENC_ERROR_USER_ABORT
        /// </summary>
        VP8_ENC_ERROR_USER_ABORT,

        /// <summary>
        /// VP8_ENC_ERROR_LAST
        /// </summary>
        VP8_ENC_ERROR_LAST,
    }
}

 

▶ WEBPImageHint.cs

namespace TestProject
{
    /// <summary>
    /// WEBP 이미지 힌트
    /// </summary>
    public enum WEBPImageHint
    {
        /// <summary>
        /// WEBP_HINT_DEFAULT
        /// </summary>
        WEBP_HINT_DEFAULT = 0,

        /// <summary>
        /// WEBP_HINT_PICTURE
        /// </summary>
        WEBP_HINT_PICTURE,

        /// <summary>
        /// WEBP_HINT_PHOTO
        /// </summary>
        WEBP_HINT_PHOTO,

        /// <summary>
        /// WEBP_HINT_GRAPH
        /// </summary>
        WEBP_HINT_GRAPH,

        /// <summary>
        /// WEBP_HINT_LAST
        /// </summary>
        WEBP_HINT_LAST
    };
}

 

▶ WEBPPreset.cs

namespace TestProject
{
    /// <summary>
    /// WEBP 사전 세트
    /// </summary>
    public enum WEBPPreset
    {
        /// <summary>
        /// WEBP_PRESET_DEFAULT
        /// </summary>
        WEBP_PRESET_DEFAULT = 0,

        /// <summary>
        /// WEBP_PRESET_PICTURE
        /// </summary>
        WEBP_PRESET_PICTURE,

        /// <summary>
        /// WEBP_PRESET_PHOTO
        /// </summary>
        WEBP_PRESET_PHOTO,

        /// <summary>
        /// WEBP_PRESET_DRAWING
        /// </summary>
        WEBP_PRESET_DRAWING,

        /// <summary>
        /// WEBP_PRESET_ICON
        /// </summary>
        WEBP_PRESET_ICON,

        /// <summary>
        /// WEBP_PRESET_TEXT
        /// </summary>
        WEBP_PRESET_TEXT
    };
}

 

▶ RGBA_YUVA_Buffer.cs

using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// RGBA YUVA 버퍼
    /// </summary>
    /// <remarks>버퍼 매개변수의 합집합</remarks>
    [StructLayoutAttribute(LayoutKind.Explicit)]
    public struct RGBA_YUVA_Buffer
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// RGBA
        /// </summary>
        [FieldOffsetAttribute(0)]
        public WEBPRGBABuffer RGBA;

        /// <summary>
        /// YUVA
        /// </summary>
        [FieldOffsetAttribute(0)]
        public WEBPYUVABuffer YUVA;

        #endregion
    }
}

 

▶ WEBPAuxiliaryStatistics.cs

using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// WEBP 보조 통계
    /// </summary>
    /// <remarks>보조 통계를 저장하기 위한 구조(대부분 손실 인코딩용)</remarks>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct WEBPAuxiliaryStatistics
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 코드된 크기
        /// </summary>
        /// <remarks>최종 크기</remarks>
        public int CodedSize;

        /// <summary>PSNR Y</summary>
        /// <remarks>Y에 대한 피크 신호 대 잡음비</remarks>
        public float PSNRY;

        /// <summary>
        /// PSNR U
        /// </summary>
        /// <remarks>U의 피크 신호 대 잡음비</remarks>
        public float PSNRU;

        /// <summary>
        /// PSNR V
        /// </summary>
        /// <remarks>V에 대한 피크 신호 대 잡음비</remarks>
        public float PSNRV;

        /// <summary>PSNR ALL</summary>
        /// <remarks>모두에 대한 피크 신호 대 잡음비</remarks>
        public float PSNRALL;

        /// <summary>
        /// PSNR 알파
        /// </summary>
        /// <remarks>Alpha의 피크 신호 대 잡음비</remarks>
        public float PSNRAlpha;

        /// <summary>블럭 수 인트라 4</summary>
        /// <remarks>인트라 4의 수</remarks>
        public int BlockCountIntra4;

        /// <summary>블럭 수 인트라 16</summary>
        /// <remarks>인트라 16의 수</remarks>
        public int BlockCountIntra16;

        /// <summary>블럭 수 스킵</summary>
        /// <remarks>건너뛴 매크로 블록 수</remarks>
        public int BlockCountSkipped;

        /// <summary>
        /// 헤더 바이트 수
        /// </summary>
        /// <remarks>헤더에 소요된 대략적인 바이트 수</remarks>
        public int HeaderByteCount;

        /// <summary>
        /// 모드 파티션 #0
        /// </summary>
        /// <remarks>모드 파티션 #0에 소요된 대략적인 바이트 수</remarks>
        public int ModePartition0;

        /// <summary>
        /// DC 세그먼트 0 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 0의 DC 계수에 사용된 대략적인 바이트 수</remarks>
        public int ResidualByteCountDCSegments0;

        /// <summary>
        /// AC 세그먼트 0 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 0의 AC 계수에 소비된 대략적인 바이트 수</remarks>
        public int ResidualByteCountACSegments0;

        /// <summary>
        /// UV 세그먼트 0 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 0의 UV 계수에 소비된 대략적인 바이트 수</remarks>
        public int ResidualByteCountUVSegments0;

        /// <summary>
        /// DC 세그먼트 1 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 1의 DC 계수에 소비된 대략적인 바이트 수</remarks>
        public int ResidualByteCountDCSegments1;

        /// <summary>
        /// AC 세그먼트 1 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 1의 AC 계수에 소비된 대략적인 바이트 수</remarks>
        public int ResidualByteCountACSegments1;

        /// <summary>
        /// UV 세그먼트 1 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 1의 UV 계수에 소비된 대략적인 바이트 수</remarks>
        public int ResidualByteCountUVSegments1;

        /// <summary>
        /// DC 세그먼트 2 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 2의 DC 계수에 사용된 대략적인 바이트 수</remarks>
        public int ResidualByteCountDCSegments2;

        /// <summary>
        /// AC 세그먼트 2 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 2의 AC 계수에 사용된 대략적인 바이트 수</remarks>
        public int ResidualByteCountACSegments2;

        /// <summary>
        /// UV 세그먼트 2 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 2의 UV 계수에 소비된 대략적인 바이트 수</remarks>
        public int ResidualByteCountUVSegments2;

        /// <summary>
        /// DC 세그먼트 3 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 3의 DC 계수에 사용된 대략적인 바이트 수</remarks>
        public int ResidualByteCountDCSegments3;

        /// <summary>
        /// AC 세그먼트 3 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 3의 AC 계수에 사용된 대략적인 바이트 수</remarks>
        public int ResidualByteCountACSegments3;

        /// <summary>
        /// UV 세그먼트 3 잔여 바이트 수
        /// </summary>
        /// <remarks>세그먼트 3의 UV 계수에 소비된 대략적인 바이트 수</remarks>
        public int ResidualByteCountUVSegments3;

        /// <summary>
        /// 세그먼트 0 세그먼트 크기
        /// </summary>
        /// <remarks>세그먼트 0의 매크로 블록 수</remarks>
        public int SegmentSizeSegments0;

        /// <summary>
        /// 세그먼트 1 세그먼트 크기
        /// </summary>
        /// <remarks>세그먼트 1의 매크로 블록 수</remarks>
        public int SegmentSizeSegments1;

        /// <summary>
        /// 세그먼트 2 세그먼트 크기
        /// </summary>
        /// <remarks>세그먼트 2의 매크로 블록 수</remarks>
        public int SegmentSizeSegments2;

        /// <summary>
        /// 세그먼트 3 세그먼트 크기
        /// </summary>
        /// <remarks>세그먼트 3의 매크로 블록 수</remarks>
        public int SegmentSizeSegments3;

        /// <summary>
        /// 세그먼트 0 세그먼트 양자화
        /// </summary>
        /// <remarks>세그먼트 0의 양자화 값</remarks>
        public int SegmentQuantizerSegments0;

        /// <summary>
        /// 세그먼트 1 세그먼트 양자화
        /// </summary>
        /// <remarks>세그먼트 1의 양자화 값</remarks>
        public int SegmentQuantizerSegments1;

        /// <summary>
        /// 세그먼트 2 세그먼트 양자화
        /// </summary>
        /// <remarks>세그먼트 2의 양자화 값</remarks>
        public int SegmentQuantizerSegments2;

        /// <summary>
        /// 세그먼트 3 세그먼트 양자화
        /// </summary>
        /// <remarks>세그먼트 3의 양자화 값</remarks>
        public int SegmentQuantizerSegments3;

        /// <summary>
        /// 세그먼트 0 세그먼트 레벨
        /// </summary>
        /// <remarks>세그먼트 0의 필터링 강도 [0..63]</remarks>
        public int SegmentLevelSegments0;

        /// <summary>
        /// 세그먼트 1 세그먼트 레벨
        /// </summary>
        /// <remarks>세그먼트 1의 필터링 강도 [0..63]</remarks>
        public int SegmentLevelSegments1;

        /// <summary>
        /// 세그먼트 2 세그먼트 레벨
        /// </summary>
        /// <remarks>세그먼트 2의 필터링 강도 [0..63]</remarks>
        public int SegmentLevelSegments2;

        /// <summary>
        /// 세그먼트 3 세그먼트 레벨
        /// </summary>
        /// <remarks>세그먼트 3의 필터링 강도 [0..63]</remarks>
        public int SegmentLevelSegments3;

        /// <summary>
        /// 알파 데이터 크기
        /// </summary>
        /// <remarks>투명도 데이터의 크기</remarks>
        public int AlphaDataSize;

        /// <summary>
        /// 레이어 데이터 크기
        /// </summary>
        /// <remarks>향상 계층 데이터의 크기</remarks>
        public int LayerDataSize;

        /// <summary>
        /// 무손실 특징
        /// </summary>
        /// <remarks>
        /// 무손실 인코더 통계
        /// bit0 : predictor, bit1 : cross-color transform, bit2 : subtract-green, bit3 : color indexing
        /// </remarks>
        public int LosslessFeatures;

        /// <summary>
        /// 히스토그램 비트 수
        /// </summary>
        /// <remarks>히스토그램의 정밀도 비트 수</remarks>
        public int HistogramBitCount;

        /// <summary>
        /// 변환 비트 수
        /// </summary>
        /// <remarks>변환용 정밀도 비트 수</remarks>
        public int TransformBitCount;

        /// <summary>
        /// 캐시 비트 수
        /// </summary>
        /// <remarks>색상 캐시 조회를 위한 비트 수</remarks>
        public int CacheBitCount;

        /// <summary>
        /// 팔레트 크기
        /// </summary>
        /// <remarks>사용된 경우 팔레트의 색상 수</remarks>
        public int PaletteSize;

        /// <summary>
        /// 무손실 크기
        /// </summary>
        /// <remarks>최종 무손실 크기</remarks>
        public int LosslessSize;

        /// <summary>
        /// 무손실 HDR 크기
        /// </summary>
        /// <remarks>무손실 헤더(transform, Huffman 등) 크기</remarks>
        public int LosslessHDRSize;

        /// <summary>
        /// 무손실 데이터 크기
        /// </summary>
        /// <remarks>무손실 이미지 데이터 크기</remarks>
        public int LosslessDataSize;

        /// <summary>
        /// 패딩
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
        private readonly uint[] Padding;

        #endregion
    };
}

 

▶ WEBPBitStreamFeatures.cs

using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// WEBP 비트 스트림 특징
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct WEBPBitStreamFeatures
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 너비
        /// </summary>
        public int Width;

        /// <summary>
        /// 높이
        /// </summary>
        public int Height;

        /// <summary>
        /// 알파 여부
        /// </summary>
        public int HasAlpha;

        /// <summary>
        /// 애니메이션 여부
        /// </summary>
        public int HasAnimation;

        /// <summary>
        /// 포맷
        /// </summary>
        public int Format;

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 패딩
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.U4)]
        private readonly uint[] Padding;

        #endregion
    };
}

 

▶ WEBPConfiguration.cs

using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// WEBP 구성
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct WEBPConfiguration
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 무손실 인코딩
        /// </summary>
        /// <remarks>무손실 인코딩 (0 : 손실(디폴트), 1 : 무손실)</remarks>
        public int Lossless;

        /// <summary>
        /// 품질
        /// </summary>
        /// <remarks>0 (가장 작은 파일) ~ 100 (가장 큰 파일)</remarks>
        public float Quality;

        /// <summary>
        /// 메소드
        /// </summary>
        /// <remarks>Quality/speed trade-off (0=fast, 6=slower-better)</remarks>
        public int Method;

        /// <summary>
        /// 이미지 힌트
        /// </summary>
        public WEBPImageHint ImageHint;

        /// <summary>
        /// 타겟 크기
        /// </summary>
        /// <remarks>
        /// 0이 아닌 경우 원하는 대상 크기를 바이트 단위로 설정한다.
        /// '압축' 매개변수보다 우선한다.
        /// </remarks>
        public int TargetSize;

        /// <summary>
        /// 타겟 PSNR
        /// </summary>
        /// <remarks>
        /// 0이 아닌 경우 달성하려는 최소 왜곡을 지정한다.
        /// TargetSize보다 우선한다.
        /// </remarks>
        public float TargetPSNR;

        /// <summary>
        /// 세그먼트 수
        /// </summary>
        /// <remarks>[1..4]에서 사용할 최대 세그먼트 수</remarks>
        public int SegmentCount;

        /// <summary>
        /// 공간 노이즈 쉐이핑 강도
        /// </summary>
        /// <remarks>공간 노이즈 쉐이핑 : 0 = 해제, 100 = 최대</remarks>
        public int SpatialNoiseShapingStrength;

        /// <summary>
        /// 필터 강도
        /// </summary>
        /// <remarks>범위 : [0 = 꺼짐 .. 100 = 가장 강함]</remarks>
        public int FilterStrength;

        /// <summary>
        /// 필터 선명도
        /// </summary>
        /// <remarks>범위 : [0 = 꺼짐 .. 7 = 최소 선명도]</remarks>
        public int FilterSharpness;

        /// <summary>
        /// 필터 타입
        /// </summary>
        /// <remarks>필터링 타입 : 0 = 단순, 1 = 강력(filter_strength > 0 또는 자동 필터 > 0인 경우에만 사용됨)</remarks>
        public int FilterType;

        /// <summary>
        /// 자동 필터
        /// </summary>
        /// <remarks>필터 강도 자동 조정 [0 = 끄기, 1 = 켜기]</remarks>
        public int AutoFilter;

        /// <summary>
        /// 알파 압축
        /// </summary>
        /// <remarks>
        /// 알파 평면 인코딩 알고리즘 (0 = 없음, 1 = WebP 무손실 압축)
        /// 기본값은 1입니다.
        /// </remarks>
        public int AlphaCompression;

        /// <summary>
        /// 알파 필터링
        /// </summary>
        /// <remarks>
        /// 알파 평면에 대한 예측 필터링 방법
        /// 0 : 없음, 1 : 빠름, 2 : 최상
        /// 1인 경우 기본값
        /// </remarks>
        public int AlphaFiltering;

        /// <summary>
        /// 알파 품질
        /// </summary>
        /// <remarks>
        /// 0(가장 작은 크기)에서 100(무손실) 사이
        /// 기본값은 100입니다.
        /// </remarks>
        public int AlphaQuality;

        /// <summary>
        /// 패스
        /// </summary>
        /// <remarks>엔트로피 분석 패스 수([1..10])</remarks>
        public int Pass;

        /// <summary>
        /// 압푹 표시
        /// </summary>
        /// <remarks>
        /// true이면 압축된 그림을 다시 내보낸다.
        /// 인루프 필터링이 적용되지 않음
        /// </remarks>
        public int ShowCompressed;

        /// <summary>
        /// 사전 처리
        /// </summary>
        /// <remarks>전처리 필터 (0 = 없음, 1 = 세그먼트 스무드, 2 = 의사 무작위 디더링)</remarks>
        public int Preprocessing;

        /// <summary>
        /// 파티션
        /// </summary>
        /// <remarks>
        /// [0..3]의 Log2(토큰 파티션 수)는 보다 쉬운 점진적 디코딩을 위해 기본값이 0으로 설정된다.
        /// </remarks>
        public int Partitions;

        /// <summary>
        /// 파티션 제한
        /// </summary>
        /// <remarks>
        /// 예측 모드 코딩에 대한 512k 제한에 맞게 품질 저하 허용(0 : 저하 없음, 100 : 가능한 최대 저하)
        /// </remarks>
        public int PartitionLimit;

        /// <summary>
        /// JPEG 크기 에뮬레이트
        /// </summary>
        /// <remarks>
        /// true인 경우 JPEG 압축의 예상 출력 크기와 더 잘 일치하도록 압축 매개변수가 다시 매핑된다.
        /// 일반적으로 출력 크기는 비슷하지만 성능 저하가 더 낮다.
        /// </remarks>
        public int EmulateJPEGSize;

        /// <summary>
        /// 쓰레드 레벨
        /// </summary>
        /// <remarks>
        /// 0이 아닌 경우 다중 스레드 인코딩을 시도하고 사용한다.
        /// </remarks>
        public int ThreadLevel;

        /// <summary>
        /// 낮은 메모리
        /// </summary>
        /// <remarks>설정하면 메모리 사용량을 줄인다(그러나 CPU 사용량을 늘림).</remarks>
        public int LowMemory;

        /// <summary>
        /// 무손실 근접
        /// </summary>
        /// <remarks>
        /// 근접 무손실 인코딩 [0 = 최대 손실 .. 100 = 꺼짐(기본값)]
        /// </remarks>
        public int NearLossless;

        /// <summary>
        /// 정확도
        /// </summary>
        /// <remarks>
        /// 0이 아닌 경우 투명 영역에서 정확한 RGB 값을 유지한다.
        /// 그렇지 않으면 더 나은 압축을 위해 이 보이지 않는 RGB 정보를 버린다.
        /// 기본값은 0이다.
        /// </remarks>
        public int Exact;

        /// <summary>
        /// 델타 팔레트화
        /// </summary>
        /// <remarks>향후 무손실 기능을 위해 예약됨</remarks>
        public int DeltaPalettization;

        /// <summary>
        /// 선명한 YUV 사용 여부
        /// </summary>
        /// <remarks>필요한 경우 선명한(그리고 느린) RGB->YUV 변환을 사용한다.</remarks>
        public int UseSharpYUV;

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 패딩 1
        /// </summary>
        private readonly int Padding1;

        /// <summary>
        /// 패딩 2
        /// </summary>
        private readonly int Padding2;

        #endregion
    };
}

 

▶ WEBPDecoderBuffer.cs

using System;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// WEBP 디코더 버퍼
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct WEBPDecoderBuffer
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 색상 공간
        /// </summary>
        public WEBP_CSP_MODE ColorSpace;

        /// <summary>
        /// 너비
        /// </summary>
        public int Width;

        /// <summary>
        /// 높이
        /// </summary>
        public int Height;

        /// <summary>
        /// 외부 메모리 여부
        /// </summary>
        /// <remarks>
        /// 0이 아니면 'internal_memory' 포인터를 사용하지 않는다.
        /// 값이 '2' 이상이면 외부 메모리가 '느림'으로 간주되어 다중 읽기/쓰기가 방지된다.
        /// </remarks>
        public int IsExternalMemory;

        /// <summary>
        /// U
        /// </summary>
        /// <remarks>출력 버퍼 매개변수</remarks>
        public RGBA_YUVA_Buffer U;

        /// <summary>
        /// 패딩 1
        /// </summary>
        private readonly uint Padding1;

        /// <summary>
        /// 패딩 2
        /// </summary>
        private readonly uint Padding2;

        /// <summary>
        /// 패딩 3
        /// </summary>
        private readonly uint Padding3;

        /// <summary>
        /// 패딩 4
        /// </summary>
        private readonly uint Padding4;

        /// <summary>
        /// 전용 메모리
        /// </summary>
        /// <remarks>
        /// 내부적으로 할당된 메모리(is_external_memory가 0인 경우에만)
        /// 외부에서 사용해서는 안 되지만 WebPRGBABuffer를 통해 액세스해야 한다.
        /// </remarks>
        public IntPtr PrivateMemory;

        #endregion
    }
}

 

▶ WEBPDecoderConfiguration.cs

using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// WEBP 디코더 구성
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct WEBPDecoderConfiguration
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 입력
        /// </summary>
        /// <remarks>불변 비트 스트림 기능(선택 사항)</remarks>
        public WEBPBitStreamFeatures Input;

        /// <summary>
        /// 출력
        /// </summary>
        /// <remarks>출력 버퍼(외부 메모리를 가리킬 수 있음)</remarks>
        public WEBPDecoderBuffer Output;

        /// <summary>
        /// 디코딩 옵션
        /// </summary>
        public WEBPDecoderOptions Options;

        #endregion
    }
}

 

▶ WEBPDecoderOptions.cs

using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// WEBP 디코더 옵션
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct WEBPDecoderOptions
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 바이패스 필터링
        /// </summary>
        /// <remarks>
        /// true인 경우 루프 내 필터링을 건너뛴다.
        /// </remarks>
        public int BypassFiltering;

        /// <summary>
        /// 팬시 업샘플링 없음
        /// </summary>
        /// <remarks>true인 경우 더 빠른 포인트별 업샘플러를 사용한다.</remarks>
        public int NoFancyUpsampling;

        /// <summary>
        /// 잘라내기 사용 여부
        /// </summary>
        /// <remarks>true인 경우 자르기가 _first_ 적용된다.</remarks>
        public int UseCropping;

        /// <summary>
        /// 왼쪽 잘라내기
        /// </summary>
        /// <remarks>
        /// 자르기 위한 왼쪽 위치이다.
        /// 짝수 값으로 스냅된다.
        /// </remarks>
        public int CropLeft;

        /// <summary>
        /// 위쪽 잘라내기
        /// </summary>
        /// <remarks>
        /// 자르기의 최상위 위치이다.
        /// 짝수 값으로 스냅된다.
        /// </remarks>
        public int CropTop;

        /// <summary>
        /// 너비 잘라내기
        /// </summary>
        /// <remarks>자르기 영역의 너비</remarks>
        public int CropWidth;

        /// <summary>
        /// 높이 잘라내기
        /// </summary>
        /// <remarks>자르기 영역의 높이</remarks>
        public int CropHeight;

        /// <summary>
        /// 스케일링 사용 여부
        /// </summary>
        public int UseScaling;

        /// <summary>
        /// 스케일 너비
        /// </summary>
        /// <remarks>최종 너비</remarks>
        public int ScaledWidth;

        /// <summary>
        /// 스케일 높이
        /// </summary>
        /// <remarks>최종 높이</remarks>
        public int ScaledHeight;

        /// <summary>
        /// 쓰레드 사용 여부
        /// </summary>
        /// <remarks>true인 경우 다중 스레드 디코딩을 사용한다.</remarks>
        public int UseThreads;

        /// <summary>
        /// 디더링 강도
        /// </summary>
        /// <remarks>디더링 강도(0 = 끄기, 100 = 전체)</remarks>
        public int DitheringStrength;

        /// <summary>
        /// 플립
        /// </summary>
        /// <remarks>출력을 세로로 뒤집는다.</remarks>
        public int Flip;

        /// <summary>
        /// 알파 디더링 강도
        /// </summary>
        /// <remarks>[0..100]의 알파 디더링 강도</remarks>
        public int AlphaDitheringStrength;

        /// <summary>
        /// 패딩 1
        /// </summary>
        private readonly uint Padding1;

        /// <summary>
        /// 패딩 2
        /// </summary>
        private readonly uint Padding2;

        /// <summary>
        /// 패딩 3
        /// </summary>
        private readonly uint Padding3;

        /// <summary>
        /// 패딩 4
        /// </summary>
        private readonly uint Padding4;

        /// <summary>
        /// 패딩 5
        /// </summary>
        private readonly uint Padding5;

        #endregion
    };
}

 

▶ WEBPPicture.cs

using System;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// WEBP 픽처
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct WEBPPicture
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// ARGB 사용 여부
        /// </summary>
        /// <remarks>
        /// ARGB 또는 YUV 입력 중에서 인코더를 선택하기 위한 기본 플래그이다.
        /// 손실이 없는 경우에는 ARGB 입력(*argb, argb_stride)을 사용하고 손실이 없는 경우에는 YUV 입력(*y, *u, *v 등)을 사용하는 것이 좋다.
        /// </remarks>
        public int UseARGB;

        /// <summary>
        /// 색상 공간
        /// </summary>
        /// <remarks>
        /// 색 공간: 지금은 YUV420이어야 한다(=Y'CbCr).
        /// 값 = 0
        /// </remarks>
        public uint ColorSpace;

        /// <summary>
        /// 너비
        /// </summary>
        /// <remarks>그림 너비(WEBP_MAX_DIMENSION 이하)</remarks>
        public int Width;

        /// <summary>
        /// 높이
        /// </summary>
        /// <remarks>사진 높이(WEBP_MAX_DIMENSION 이하)</remarks>
        public int Height;

        /// <summary>
        /// Y
        /// </summary>
        /// <remarks>루마 평면에 대한 포인터</remarks>
        public IntPtr Y;

        /// <summary>
        /// U
        /// </summary>
        /// <remarks>크로마 U 평면에 대한 포인터</remarks>
        public IntPtr U;

        /// <summary>
        /// V
        /// </summary>
        /// <remarks>크로마 V 평면에 대한 포인터</remarks>
        public IntPtr V;

        /// <summary>
        /// Y 스트라이드
        /// </summary>
        /// <remarks>루마 스트라이드</remarks>
        public int YStride;

        /// <summary>
        /// UV 스트라이드
        /// </summary>
        /// <remarks>크로마 스트라이드</remarks>
        public int UVStride;

        /// <summary>
        /// A
        /// </summary>
        /// <remarks>알파 평면에 대한 포인터</remarks>
        public IntPtr A;

        /// <summary>
        /// A 스트라이드
        /// </summary>
        /// <remarks>알파 평면의 보폭</remarks>
        public int AStride;

        /// <summary>
        /// 패딩 1
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
        private readonly uint[] Padding1;

        /// <summary>
        /// ARGB
        /// </summary>
        /// <remarks>ARGB(32비트) 평면에 대한 포인터</remarks>
        public IntPtr ARGB;

        /// <summary>
        /// ARGB 스트라이드
        /// </summary>
        /// <remarks>이것은 바이트가 아닌 픽셀 단위의 스트라이드이다.</remarks>
        public int ARGBStride;

        /// <summary>
        /// 패딩 2
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U4)]
        private readonly uint[] Padding2;

        /// <summary>
        /// 작성자
        /// </summary>
        /// <remarks>압축된 바이트가 준비되면 저장하기 위한 바이트 방출 후크</remarks>
        public IntPtr Writer;

        /// <summary>
        /// 커스컴 포인터
        /// </summary>
        /// <remarks>작성자가 사용할 수 있다.</remarks>
        public IntPtr CustomPointer;

        /// <summary>
        /// 부가 정보 타입
        /// </summary>
        /// <remarks>
        /// 추가 정보를 위한 맵(손실 압축 모드에만 해당)
        /// 1 : intra type, 2 : segment, 3 : quant, 4 : intra-16 prediction mode, 5 : chroma prediction mode, 6 : bit cost, 7 : distortion
        /// </remarks>
        public int ExtraInformationType;

        /// <summary>
        /// 부가 정보
        /// </summary>
        /// <remarks>
        /// NULL이 아니면 ExtraInformationType에 따라 매크로 블록 맵으로 채워질 ((width + 15) / 16) * ((height + 15) / 16) 크기의 배열을 가리킨다.
        /// </remarks>
        public IntPtr ExtraInformation;

        /// <summary>
        /// 통계
        /// </summary>
        /// <remarks>
        /// 사이드 통계에 대한 포인터(NULL이 아닌 경우에만 업데이트됨)
        /// </remarks>
        public IntPtr Statistics;

        /// <summary>
        /// 에러 코드
        /// </summary>
        /// <remarks>
        /// 인코딩 중 발생한 최신 오류에 대한 오류 코드
        /// </remarks>
        public uint ErrorCode;

        /// <summary>
        /// 프로세스 후크
        /// </summary>
        /// <remarks>NULL이 아니면 인코딩 중 진행 상황 보고</remarks>
        public IntPtr ProgressHook;

        /// <summary>
        /// 사용자 데이터
        /// </summary>
        /// <remarks>이 필드는 임의의 값으로 자유롭게 설정할 수 있으며 콜백 중에 사용된다(예 : 진행 보고서).</remarks>
        public IntPtr UserData;

        /// <summary>
        /// 패딩 3
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 13, ArraySubType = UnmanagedType.U4)]
        private readonly uint[] Padding3;

        /// <summary>
        /// 메모리 YUVA
        /// </summary>
        /// <remarks>
        /// YUVA 평면에 대한 메모리 행 청크
        /// </remarks>
        private readonly IntPtr MemoryYUVA;

        /// <summary>
        /// 메모리 ARGB
        /// </summary>
        /// <remarks>
        /// ARGB 평면에 대한 메모리 행 청크
        /// </remarks>
        private readonly IntPtr MemoryARGB;

        /// <summary>
        /// 패딩 4
        /// </summary>
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
        private readonly uint[] Padding4;

        #endregion
    };
}

 

▶ WEBPRGBABuffer.cs

using System;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// WEBP RGB 버퍼
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct WEBPRGBABuffer
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// RGBA
        /// </summary>
        /// <remarks>RGBA 샘플에 대한 포인터</remarks>
        public IntPtr RGBA;

        /// <summary>
        /// 스트라이드
        /// </summary>
        /// <remarks>한 스캔라인에서 다음 스캔라인으로 바이트 단위로 이동</remarks>
        public int Stride;

        /// <summary>
        /// 크기
        /// </summary>
        /// <remarks>RGBA 버퍼의 총 크기</remarks>
        public UIntPtr Size;

        #endregion
    }
}

 

▶ WEBPYUVABuffer.cs

using System;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// WEBP YUVA 버퍼
    /// </summary>
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct WEBPYUVABuffer
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// Y
        /// </summary>
        /// <remarks>루마 샘플에 대한 포인터</remarks>
        public IntPtr Y;

        /// <summary>
        /// U
        /// </summary>
        /// <remarks>크로마 U 샘플에 대한 포인터</remarks>
        public IntPtr U;

        /// <summary>
        /// V
        /// </summary>
        /// <remarks>크로마 V 샘플에 대한 포인터</remarks>
        public IntPtr V;

        /// <summary>
        /// A
        /// </summary>
        /// <remarks>알파 샘플에 대한 포인터</remarks>
        public IntPtr A;

        /// <summary>
        /// Y 스트라이드
        /// </summary>
        /// <remarks>루마 스트라이드</remarks>
        public int YStride;

        /// <summary>
        /// U 스트라이드
        /// </summary>
        /// <remarks>크로마 U 스트라이드</remarks>
        public int UStride;

        /// <summary>
        /// V 스트라이드
        /// </summary>
        /// <remarks>크로마 V 스트라이드</remarks>
        public int VStride;

        /// <summary>
        /// A 스트라이드
        /// </summary>
        /// <remarks>알파 스트라이드</remarks>
        public int AStride;

        /// <summary>
        /// Y 크기
        /// </summary>
        /// <remarks>루마 평면 크기</remarks>
        public UIntPtr YSize;

        /// <summary>
        /// U 크기
        /// </summary>
        /// <remarks>크로마 평면 U사이즈</remarks>
        public UIntPtr USize;

        /// <summary>
        /// V 크기
        /// </summary>
        /// <remarks>크로마 평면 V사이즈</remarks>
        public UIntPtr VSize;

        /// <summary>
        /// A 크기
        /// </summary>
        /// <remarks>알파 평면 크기</remarks>
        public UIntPtr ASize;

        #endregion
    }
}

 

▶ WIN32Helper.cs

using System;
using System.Runtime.InteropServices;
using System.Security;

namespace TestProject
{
    /// <summary>
    /// WIN32 헬퍼
    /// </summary>
    [SuppressUnmanagedCodeSecurity]
    public sealed partial class WIN32Helper
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Delegate
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region WEBP 메모리 쓰기 대리자 - WEBPMemoryWriteDelegate(dataHandle, dataSize, picture)

        /// <summary>
        /// WEBP 메모리 쓰기 대리자
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="picture">WEBP 픽처</param>
        /// <returns>처리 결과</returns>
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate int WEBPMemoryWriteDelegate([In()] IntPtr dataHandle, UIntPtr dataSize, ref WEBPPicture picture);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Import
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 메모리 복사하기 - CopyMemory(targetHandle, sourceHandle, count)

        /// <summary>
        /// 메모리 복사하기
        /// </summary>
        /// <param name="targetHandle">타겟 핸들</param>
        /// <param name="sourceHandle">소스 핸들</param>
        /// <param name="count">카운트</param>
        [DllImport("kernel32", EntryPoint = "CopyMemory", SetLastError = false)]
        public static extern void CopyMemory(IntPtr targetHandle, IntPtr sourceHandle, uint count);

        #endregion

        #region WEBP 구성 초기화하기 (내부용, X86) - WebPConfigInitInternal_x86(configuration, preset, quality, version)

        /// <summary>
        /// WEBP 구성 초기화하기 (내부용, X86)
        /// </summary>
        /// <param name="configuration">WEBP 구성</param>
        /// <param name="preset">WEBP 프리셋</param>
        /// <param name="quality">품질</param>
        /// <param name="version">버전</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigInitInternal")]
        private static extern int WebPConfigInitInternal_x86(ref WEBPConfiguration configuration, WEBPPreset preset, float quality, int version);

        #endregion
        #region WEBP 구성 초기화하기 (내부용, X64) - WebPConfigInitInternal_x64(configuration, preset, quality, version)

        /// <summary>
        /// WEBP 구성 초기화하기 (내부용, X64)
        /// </summary>
        /// <param name="configuration">WEBP 구성</param>
        /// <param name="preset">WEBP 프리셋</param>
        /// <param name="quality">품질</param>
        /// <param name="version">버전</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigInitInternal")]
        private static extern int WebPConfigInitInternal_x64(ref WEBPConfiguration configuration, WEBPPreset preset, float quality, int version);

        #endregion
        #region WEBP 특징 구하기 (내부용, X86) - WebPGetFeaturesInternal_x86(dataHandle, dataSize, features, version)

        /// <summary>
        /// WEBP 특징 구하기 (내부용, X86)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="features">특징</param>
        /// <param name="version">버전</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetFeaturesInternal")]
        private static extern VP8StatusCode WebPGetFeaturesInternal_x86
        (
            [InAttribute()] IntPtr    dataHandle,
            UIntPtr                   dataSize,
            ref WEBPBitStreamFeatures features,
            int                       version
        );

        #endregion
        #region WEBP 특징 구하기 (내부용, X64) - WebPGetFeaturesInternal_x64(dataHandle, dataSize, features, version)

        /// <summary>
        /// WEBP 특징 구하기 (내부용, X64)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="features">특징</param>
        /// <param name="version">버전</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetFeaturesInternal")]
        private static extern VP8StatusCode WebPGetFeaturesInternal_x64
        (
            [InAttribute()] IntPtr    rawHandle,
            UIntPtr                   dataSize,
            ref WEBPBitStreamFeatures features,
            int                       version
        );

        #endregion
        #region WEBP 무손실 프리셋 구성하기 (X86) - WebPConfigLosslessPreset_x86(configuration, level)

        /// <summary>
        /// WEBP 무손실 프리셋 구성하기 (X86)
        /// </summary>
        /// <param name="configuration">WEBP 구성</param>
        /// <param name="level">레벨</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigLosslessPreset")]
        private static extern int WebPConfigLosslessPreset_x86(ref WEBPConfiguration configuration, int level);

        #endregion
        #region WEBP 무손실 프리셋 구성하기 (X64) - WebPConfigLosslessPreset_x64(configuration, level)

        /// <summary>
        /// WEBP 무손실 프리셋 구성하기 (X64)
        /// </summary>
        /// <param name="configuration">WEBP 구성</param>
        /// <param name="level">레벨</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigLosslessPreset")]
        private static extern int WebPConfigLosslessPreset_x64(ref WEBPConfiguration configuration, int level);

        #endregion
        #region WEBP 구성 검증하기 (X86) - WebPValidateConfig_x86(configuration)

        /// <summary>
        /// WEBP 구성 검증하기 (X86)
        /// </summary>
        /// <param name="configuration">구성</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPValidateConfig")]
        private static extern int WebPValidateConfig_x86(ref WEBPConfiguration configuration);

        #endregion
        #region WEBP 구성 검증하기 (X64) - WebPValidateConfig_x64(configuration)

        /// <summary>
        /// WEBP 구성 검증하기 (X64)
        /// </summary>
        /// <param name="configuration">구성</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPValidateConfig")]
        private static extern int WebPValidateConfig_x64(ref WEBPConfiguration configuration);

        #endregion
        #region WEBP 픽처 초기화하기 (내부용, X86) - WebPPictureInitInternal_x86(picture, version)

        /// <summary>
        /// WEBP 픽처 초기화하기 (내부용, X86)
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <param name="version">버전</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureInitInternal")]
        private static extern int WebPPictureInitInternal_x86(ref WEBPPicture picture, int version);

        #endregion
        #region WEBP 픽처 초기화하기 (내부용, X64) - WebPPictureInitInternal_x64(picture, version)

        /// <summary>
        /// WEBP 픽처 초기화하기 (내부용, X64)
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <param name="version">버전</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureInitInternal")]
        private static extern int WebPPictureInitInternal_x64(ref WEBPPicture picture, int version);

        #endregion
        #region WEBP 픽처 BGR 가져오기 (X86) - WebPPictureImportBGR_x86(picture, bgr, stride)

        /// <summary>
        /// WEBP 픽처 BGR 가져오기 (X86)
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <param name="bgr">BGR</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGR")]
        private static extern int WebPPictureImportBGR_x86(ref WEBPPicture picture, IntPtr bgr, int stride);

        #endregion
        #region WEBP 픽처 BGR 가져오기 (X64) - WebPPictureImportBGR_x64(picture, bgr, stride)

        /// <summary>
        /// WEBP 픽처 BGR 가져오기 (X64)
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <param name="bgr">BGR</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGR")]
        private static extern int WebPPictureImportBGR_x64(ref WEBPPicture picture, IntPtr bgr, int stride);

        #endregion
        #region WEBP 픽처 BGRA 가져오기 (X86) - WebPPictureImportBGRA_x86(picture, bgra, stride)

        /// <summary>
        /// WEBP 픽처 BGRA 가져오기 (X86)
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <param name="bgra">BGRA</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRA")]
        private static extern int WebPPictureImportBGRA_x86(ref WEBPPicture picture, IntPtr bgra, int stride);

        #endregion
        #region WEBP 픽처 BGRA 가져오기 (X64) - WebPPictureImportBGRA_x64(picture, bgra, stride)

        /// <summary>
        /// WEBP 픽처 BGRA 가져오기 (X64)
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <param name="bgra">BGRA</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRA")]
        private static extern int WebPPictureImportBGRA_x64(ref WEBPPicture picture, IntPtr bgra, int stride);

        #endregion
        #region WEBP 픽처 BGRX 가져오기 (X86) - WebPPictureImportBGRX_x86(picture, bgr, stride)

        /// <summary>
        /// WEBP 픽처 BGRX 가져오기 (X86)
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <param name="bgr">BGR</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRX")]
        private static extern int WebPPictureImportBGRX_x86(ref WEBPPicture picture, IntPtr bgr, int stride);

        #endregion
        #region WEBP 픽처 BGRX 가져오기 (X64) - WebPPictureImportBGRX_x64(picture, bgr, stride)

        /// <summary>
        /// WEBP 픽처 BGRX 가져오기 (X64)
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <param name="bgr">BGR</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRX")]
        private static extern int WebPPictureImportBGRX_x64(ref WEBPPicture picture, IntPtr bgr, int stride);

        #endregion
        #region WEBP 인코딩하기 (X86) - WebPEncode_x86(configuration, picture)

        /// <summary>
        /// WEBP 인코딩하기 (X86)
        /// </summary>
        /// <param name="configuration">WEBP 구성</param>
        /// <param name="picture">WEBP 픽처</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncode")]
        private static extern int WebPEncode_x86(ref WEBPConfiguration configuration, ref WEBPPicture picture);

        #endregion
        #region WEBP 인코딩하기 (X64) - WebPEncode_x64(configuration, picture)

        /// <summary>
        /// WEBP 인코딩하기 (X64)
        /// </summary>
        /// <param name="configuration">WEBP 구성</param>
        /// <param name="picture">WEBP 픽처</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncode")]
        private static extern int WebPEncode_x64(ref WEBPConfiguration configuration, ref WEBPPicture picture);

        #endregion
        #region WEBP 픽처 해제하기 (X86) - WebPPictureFree_x86(picture)

        /// <summary>
        /// WEBP 픽처 해제하기 (X86)
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureFree")]
        private static extern void WebPPictureFree_x86(ref WEBPPicture picture);

        #endregion
        #region WEBP 픽처 해제하기 (X64) - WebPPictureFree_x64(picture)

        /// <summary>
        /// WEBP 픽처 해제하기 (X64)
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureFree")]
        private static extern void WebPPictureFree_x64(ref WEBPPicture picture);

        #endregion
        #region WEBP 정보 구하기 (X86) - WebPGetInfo_x86(dataHandle, dataSize, width, height)

        /// <summary>
        /// WEBP 정보 구하기 (X86)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetInfo")]
        private static extern int WebPGetInfo_x86([InAttribute()] IntPtr dataHandle, UIntPtr dataSize, out int width, out int height);

        #endregion
        #region WEBP 정보 구하기 (X64) - WebPGetInfo_x64(dataHandle, dataSize, width, height)

        /// <summary>
        /// WEBP 정보 구하기 (X64)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetInfo")]
        private static extern int WebPGetInfo_x64([InAttribute()] IntPtr dataHandle, UIntPtr dataSize, out int width, out int height);

        #endregion
        #region WEBP BGR 디코딩하기 (X86) - WebPDecodeBGRInto_x86(dataHandle, dataSize, bufferHandle, bufferSize, stride)

        /// <summary>
        /// WEBP BGR 디코딩하기 (X86)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="bufferHandle">버퍼 핸들</param>
        /// <param name="bufferSize">버퍼 크기</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRInto")]
        private static extern IntPtr WebPDecodeBGRInto_x86([InAttribute()] IntPtr dataHandle, UIntPtr dataSize, IntPtr bufferHandle, int bufferSize, int stride);

        #endregion
        #region WEBP BGR 디코딩하기 (X64) - WebPDecodeBGRInto_x64(dataHandle, dataSize, bufferHandle, bufferSize, stride)

        /// <summary>
        /// WEBP BGR 디코딩하기 (X64)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="bufferHandle">버퍼 핸들</param>
        /// <param name="bufferSize">버퍼 크기</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRInto")]
        private static extern IntPtr WebPDecodeBGRInto_x64([InAttribute()] IntPtr dataHandle, UIntPtr dataSize, IntPtr bufferHandle, int bufferSize, int stride);

        #endregion
        #region WEBP BGRA 디코딩하기 (X86) - WebPDecodeBGRAInto_x86(dataHandle, dataSize, bufferHandle, bufferSize, stride)

        /// <summary>
        /// WEBP BGRA 디코딩하기 (X86)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="bufferHandle">버퍼 핸들</param>
        /// <param name="bufferSize">버퍼 크기</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRAInto")]
        private static extern IntPtr WebPDecodeBGRAInto_x86([InAttribute()] IntPtr dataHandle, UIntPtr dataSize, IntPtr bufferHandle, int bufferSize, int stride);

        #endregion
        #region WEBP BGRA 디코딩하기 (X64) - WebPDecodeBGRAInto_x64(dataHandle, dataSize, bufferHandle, bufferSize, stride)

        /// <summary>
        /// WEBP BGRA 디코딩하기 (X64)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="bufferHandle">버퍼 핸들</param>
        /// <param name="bufferSize">버퍼 크기</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRAInto")]
        private static extern IntPtr WebPDecodeBGRAInto_x64([InAttribute()] IntPtr dataHandle, UIntPtr dataSize, IntPtr bufferHandle, int bufferSize, int stride);

        #endregion
        #region WEBP ARGB 디코딩하기 (X86) - WebPDecodeARGBInto_x86(dataHandle, dataSize, bufferHandle, bufferSize, stride)

        /// <summary>
        /// WEBP ARGB 디코딩하기 (X86)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="bufferHandle">버퍼 핸들</param>
        /// <param name="bufferSize">버퍼 크기</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeARGBInto")]
        private static extern IntPtr WebPDecodeARGBInto_x86([InAttribute()] IntPtr dataHandle, UIntPtr dataSize, IntPtr bufferHandle, int bufferSize, int stride);

        #endregion
        #region WEBP ARGB 디코딩하기 (X64) - WebPDecodeARGBInto_x64(dataHandle, dataSize, bufferHandle, bufferSize, stride)

        /// <summary>
        /// WEBP ARGB 디코딩하기 (X64)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="bufferHandle">버퍼 핸들</param>
        /// <param name="bufferSize">버퍼 크기</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeARGBInto")]
        private static extern IntPtr WebPDecodeARGBInto_x64([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr bufferHandle, int bufferSize, int stride);

        #endregion
        #region WEBP 디코더 구성 초기화하기 (X86) - WebPInitDecoderConfigInternal_x86(configuration, version)

        /// <summary>
        /// WEBP 디코더 구성 초기화하기 (X86)
        /// </summary>
        /// <param name="configuration">WEBP 디코더 구성</param>
        /// <param name="version">버전</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPInitDecoderConfigInternal")]
        private static extern int WebPInitDecoderConfigInternal_x86(ref WEBPDecoderConfiguration configuration, int version);

        #endregion
        #region WEBP 디코더 구성 초기화하기 (X64) - WebPInitDecoderConfigInternal_x64(configuration, version)

        /// <summary>
        /// WEBP 디코더 구성 초기화하기 (X64)
        /// </summary>
        /// <param name="configuration">WEBP 디코더 구성</param>
        /// <param name="version">버전</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPInitDecoderConfigInternal")]
        private static extern int WebPInitDecoderConfigInternal_x64(ref WEBPDecoderConfiguration configuration, int version);

        #endregion
        #region WEBP 디코딩하기 (X86) - WebPDecode_x86(dataHandle, dataSize, configuration)

        /// <summary>
        /// WEBP 디코딩하기 (X86)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="configuration">WEBP 디코더 구성</param>
        /// <returns>상태 코드</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecode")]
        private static extern VP8StatusCode WebPDecode_x86(IntPtr dataHandle, UIntPtr dataSize, ref WEBPDecoderConfiguration configuration);

        #endregion
        #region WEBP 디코딩하기 (X64) - WebPDecode_x64(dataHandle, dataSize, configuration)

        /// <summary>
        /// WEBP 디코딩하기 (X64)
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="configuration">WEBP 디코더 구성</param>
        /// <returns>상태 코드</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecode")]
        private static extern VP8StatusCode WebPDecode_x64(IntPtr dataHandle, UIntPtr dataSize, ref WEBPDecoderConfiguration configuration);

        #endregion
        #region WEBP 디코더 버퍼 해제하기 (X86) - WebPFreeDecBuffer_x86(buffer)

        /// <summary>
        /// WEBP 디코더 버퍼 해제하기 (X86)
        /// </summary>
        /// <param name="buffer">WEBP 디코더 버퍼</param>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFreeDecBuffer")]
        private static extern void WebPFreeDecBuffer_x86(ref WEBPDecoderBuffer buffer);

        #endregion
        #region WEBP 디코더 버퍼 해제하기 (X64) - WebPFreeDecBuffer_x64(buffer)

        /// <summary>
        /// WEBP 디코더 버퍼 해제하기 (X64)
        /// </summary>
        /// <param name="buffer">WEBP 디코더 버퍼</param>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFreeDecBuffer")]
        private static extern void WebPFreeDecBuffer_x64(ref WEBPDecoderBuffer buffer);

        #endregion
        #region WEBP BGR 인코딩하기 (X86) - WebPEncodeBGR_x86(bgrHandle, width, height, stride, qualityFactor, outputHandle)

        /// <summary>
        /// WEBP BGR 인코딩하기 (X86)
        /// </summary>
        /// <param name="bgrHandle">BGR 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="qualityFactor">품질 인자</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGR")]
        private static extern int WebPEncodeBGR_x86([InAttribute()] IntPtr bgrHandle, int width, int height, int stride, float qualityFactor, out IntPtr outputHandle);

        #endregion
        #region WEBP BGR 인코딩하기 (X64) - WebPEncodeBGR_x64(bgrHandle, width, height, stride, qualityFactor, outputHandle)

        /// <summary>
        /// WEBP BGR 인코딩하기 (X64)
        /// </summary>
        /// <param name="bgrHandle">BGR 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="qualityFactor">품질 인자</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGR")]
        private static extern int WebPEncodeBGR_x64([InAttribute()] IntPtr bgrHandle, int width, int height, int stride, float qualityFactor, out IntPtr outputHandle);

        #endregion
        #region WEBP BGRA 인코딩하기 (X86) - WebPEncodeBGRA_x86(bgraHandle, width, height, stride, qualityFactor, outputHandle)

        /// <summary>
        /// WEBP BGRA 인코딩하기 (X86)
        /// </summary>
        /// <param name="bgraHandle">BGRA 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="qualityFactor">품질 인자</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGRA")]
        private static extern int WebPEncodeBGRA_x86([InAttribute()] IntPtr bgraHandle, int width, int height, int stride, float qualityFactor, out IntPtr outputHandle);

        #endregion
        #region WEBP BGRA 인코딩하기 (X64) - WebPEncodeBGRA_x64(bgraHandle, width, height, stride, qualityFactor, outputHandle)

        /// <summary>
        /// WEBP BGRA 인코딩하기 (X64)
        /// </summary>
        /// <param name="bgraHandle">BGRA 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="qualityFactor">품질 인자</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGRA")]
        private static extern int WebPEncodeBGRA_x64([InAttribute()] IntPtr bgraHandle, int width, int height, int stride, float qualityFactor, out IntPtr outputHandle);

        #endregion
        #region WEBP BGR 무손실 인코딩하기 (X86) - WebPEncodeLosslessBGR_x86(bgrHandle, width, height, stride, outputHandle)

        /// <summary>
        /// WEBP BGR 무손실 인코딩하기 (X86)
        /// </summary>
        /// <param name="bgrHandle">BGR 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGR")]
        private static extern int WebPEncodeLosslessBGR_x86([InAttribute()] IntPtr bgrHandle, int width, int height, int stride, out IntPtr outputHandle);

        #endregion
        #region WEBP BGR 무손실 인코딩하기 (X64) - WebPEncodeLosslessBGR_x64(bgrHandle, width, height, stride, outputHandle)

        /// <summary>
        /// WEBP BGR 무손실 인코딩하기 (X64)
        /// </summary>
        /// <param name="bgrHandle">BGR 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGR")]
        private static extern int WebPEncodeLosslessBGR_x64([InAttribute()] IntPtr bgrHandle, int width, int height, int stride, out IntPtr outputHandle);

        #endregion
        #region WEBP BGRA 무손실 인코딩하기 (X86) - WebPEncodeLosslessBGRA_x86(bgraHandle, width, height, stride, outputHandle)

        /// <summary>
        /// WEBP BGRA 무손실 인코딩하기 (X86)
        /// </summary>
        /// <param name="bgraHandle">BGRA 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGRA")]
        private static extern int WebPEncodeLosslessBGRA_x86([InAttribute()] IntPtr bgraHandle, int width, int height, int stride, out IntPtr outputHandle);

        #endregion
        #region WEBP BGRA 무손실 인코딩하기 (X64) - WebPEncodeLosslessBGRA_x64(bgraHandle, width, height, stride, outputHandle)

        /// <summary>
        /// WEBP BGRA 무손실 인코딩하기 (X64)
        /// </summary>
        /// <param name="bgraHandle">BGRA 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGRA")]
        private static extern int WebPEncodeLosslessBGRA_x64([InAttribute()] IntPtr bgraHandle, int width, int height, int stride, out IntPtr outputHandle);

        #endregion
        #region WEBP 해제하기 (X86) - WebPFree_x86(handle)

        /// <summary>
        /// WEBP 해제하기 (X86)
        /// </summary>
        /// <param name="handle">핸들</param>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFree")]
        private static extern void WebPFree_x86(IntPtr handle);

        #endregion
        #region WEBP 해제하기 (X64) - WebPFree_x64(handle)

        /// <summary>
        /// WEBP 해제하기 (X64)
        /// </summary>
        /// <param name="handle">핸들</param>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFree")]
        private static extern void WebPFree_x64(IntPtr handle);

        #endregion
        #region WEBP 디코더 버전 구하기 (X86) - WebPGetDecoderVersion_x86()

        /// <summary>
        /// WEBP 디코더 버전 구하기 (X86)
        /// </summary>
        /// <returns>WEBP 디코더 버전</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetDecoderVersion")]
        private static extern int WebPGetDecoderVersion_x86();

        #endregion
        #region WEBP 디코더 버전 구하기 (X64) - WebPGetDecoderVersion_x64()

        /// <summary>
        /// WEBP 디코더 버전 구하기 (X64)
        /// </summary>
        /// <returns>WEBP 디코더 버전</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetDecoderVersion")]
        private static extern int WebPGetDecoderVersion_x64();

        #endregion
        #region WEBP 픽처 왜곡 구하기 (X86) - WebPPictureDistortion_x86(sourcePicture, targetPicture, metricType, resultHandle)

        /// <summary>
        /// WEBP 픽처 왜곡 구하기 (X86)
        /// </summary>
        /// <param name="sourcePicture">소스 픽처</param>
        /// <param name="targetPicture">타겟 픽처</param>
        /// <param name="metricType">미터법 타입</param>
        /// <param name="resultHandle">결과 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x86", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureDistortion")]
        private static extern int WebPPictureDistortion_x86(ref WEBPPicture sourcePicture, ref WEBPPicture targetPicture, int metricType, IntPtr resultHandle);

        #endregion
        #region WEBP 픽처 왜곡 구하기 (X64) - WebPPictureDistortion_x64(sourcePicture, targetPicture, metricType, resultHandle)

        /// <summary>
        /// WEBP 픽처 왜곡 구하기 (X64)
        /// </summary>
        /// <param name="sourcePicture">소스 픽처</param>
        /// <param name="targetPicture">타겟 픽처</param>
        /// <param name="metricType">미터법 타입</param>
        /// <param name="resultHandle">결과 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("libwebp_x64", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureDistortion")]
        private static extern int WebPPictureDistortion_x64(ref WEBPPicture sourcePicture, ref WEBPPicture targetPicture, int metricType, IntPtr resultHandle);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 메모리 쓰기 대리자
        /// </summary>
        public static WEBPMemoryWriteDelegate memoryWriteDelegate;

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// WEBP 디코더 ABI 버전
        /// </summary>
        private static readonly int WEBP_DECODER_ABI_VERSION = 0x0208;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region WEBP 구성 초기화하기 - WEBPInitializeConfiguration(configuration, preset, quality)

        /// <summary>
        /// WEBP 구성 초기화하기
        /// </summary>
        /// <param name="configuration">WEBP 구성</param>
        /// <param name="preset">WEBP 프리셋</param>
        /// <param name="quality">품질</param>
        /// <returns>처리 결과</returns>
        public static int WEBPInitializeConfiguration(ref WEBPConfiguration configuration, WEBPPreset preset, float quality)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPConfigInitInternal_x86(ref configuration, preset, quality, WEBP_DECODER_ABI_VERSION);
                case 8  : return WebPConfigInitInternal_x64(ref configuration, preset, quality, WEBP_DECODER_ABI_VERSION);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 특징 구하기 - WEBPGetFeatures(dataHandle, dataSize, features)

        /// <summary>
        /// WEBP 특징 구하기
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="features">특징</param>
        /// <returns>처리 결과</returns>
        public static VP8StatusCode WEBPGetFeatures(IntPtr dataHandle, int dataSize, ref WEBPBitStreamFeatures features)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPGetFeaturesInternal_x86(dataHandle, (UIntPtr)dataSize, ref features, WEBP_DECODER_ABI_VERSION);
                case 8  : return WebPGetFeaturesInternal_x64(dataHandle, (UIntPtr)dataSize, ref features, WEBP_DECODER_ABI_VERSION);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 무손실 프리셋 구성하기 - WEBPConfigLosslessPreset(configuration, level)

        /// <summary>
        /// WEBP 무손실 프리셋 구성하기
        /// </summary>
        /// <param name="configuration">구성</param>
        /// <param name="level">레벨</param>
        /// <returns>처리 결과</returns>
        public static int WEBPConfigLosslessPreset(ref WEBPConfiguration configuration, int level)
        {
            switch (IntPtr.Size)
            {
                case 4  : return WebPConfigLosslessPreset_x86(ref configuration, level);
                case 8  : return WebPConfigLosslessPreset_x64(ref configuration, level);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 구성 검증하기 - WEBPValidateConfiguration(configuration)

        /// <summary>
        /// WEBP 구성 검증하기
        /// </summary>
        /// <param name="configuration">구성</param>
        /// <returns>처리 결과</returns>
        public static int WEBPValidateConfiguration(ref WEBPConfiguration configuration)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPValidateConfig_x86(ref configuration);
                case 8  : return WebPValidateConfig_x64(ref configuration);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 픽처 초기화하기 (내부용) - WEBPInitializePictureInternal(picture)

        /// <summary>
        /// WEBP 픽처 초기화하기 (내부용)
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <returns>처리 결과</returns>
        public static int WEBPInitializePictureInternal(ref WEBPPicture picture)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPPictureInitInternal_x86(ref picture, WEBP_DECODER_ABI_VERSION);
                case 8  : return WebPPictureInitInternal_x64(ref picture, WEBP_DECODER_ABI_VERSION);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 픽처 RGB 가져오기 - WEBPPictureImportBGR(picture, bgr, stride)

        /// <summary>
        /// WEBP 픽처 RGB 가져오기
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <param name="bgr">BGR</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        public static int WEBPPictureImportBGR(ref WEBPPicture picture, IntPtr bgr, int stride)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPPictureImportBGR_x86(ref picture, bgr, stride);
                case 8  : return WebPPictureImportBGR_x64(ref picture, bgr, stride);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 픽처 BGRA 가져오기 - WEBPPictureImportBGRA(picture, bgra, stride)

        /// <summary>
        /// WEBP 픽처 BGRA 가져오기
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <param name="bgra">BGRA</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        public static int WEBPPictureImportBGRA(ref WEBPPicture picture, IntPtr bgra, int stride)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPPictureImportBGRA_x86(ref picture, bgra, stride);
                case 8  : return WebPPictureImportBGRA_x64(ref picture, bgra, stride);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 픽처 BGRX 가져오기 - WEBPPictureImportBGRX(picture, bgr, stride)

        /// <summary>
        /// WEBP 픽처 BGRX 가져오기
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        /// <param name="bgr">BGR</param>
        /// <param name="stride">스트라이드</param>
        /// <returns>처리 결과</returns>
        public static int WEBPPictureImportBGRX(ref WEBPPicture picture, IntPtr bgr, int stride)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPPictureImportBGRX_x86(ref picture, bgr, stride);
                case 8  : return WebPPictureImportBGRX_x64(ref picture, bgr, stride);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 인코딩하기 - WEBPEncode(configuration, picture)

        /// <summary>
        /// WEBP 인코딩하기
        /// </summary>
        /// <param name="configuration">WEBP 구성</param>
        /// <param name="picture">WEBP 픽처</param>
        /// <returns>처리 결과</returns>
        /// <exception cref="InvalidOperationException"></exception>
        public static int WEBPEncode(ref WEBPConfiguration configuration, ref WEBPPicture picture)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPEncode_x86(ref configuration, ref picture);
                case 8  : return WebPEncode_x64(ref configuration, ref picture);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 픽처 해제하기 - WEBPPictureFree(picture)

        /// <summary>
        /// WEBP 픽처 해제하기
        /// </summary>
        /// <param name="picture">WEBP 픽처</param>
        public 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");
            }
        }

        #endregion
        #region WEBP 정보 구하기 - WEBPGetInformation(dataHandle, dataSize, width, height)

        /// <summary>
        /// WEBP 정보 구하기
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <returns>처리 결과</returns>
        /// <exception cref="InvalidOperationException"></exception>
        public static int WEBPGetInformation(IntPtr dataHandle, int dataSize, out int width, out int height)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPGetInfo_x86(dataHandle, (UIntPtr)dataSize, out width, out height);
                case 8  : return WebPGetInfo_x64(dataHandle, (UIntPtr)dataSize, out width, out height);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP BGR 디코딩하기 - WebPDecodeBGRInto(dataHandle, dataSize, bufferHandle, bufferSize, stride)

        /// <summary>
        /// WEBP BGR 디코딩하기
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="bufferHandle">버퍼 핸들</param>
        /// <param name="bufferSize">버퍼 크기</param>
        /// <param name="stride">스트라이드</param>
        /// <exception cref="InvalidOperationException"></exception>
        public static void WebPDecodeBGRInto(IntPtr dataHandle, int dataSize, IntPtr bufferHandle, int bufferSize, int stride)
        {
            switch(IntPtr.Size)
            {
                case 4 :

                    if(WebPDecodeBGRInto_x86(dataHandle, (UIntPtr)dataSize, bufferHandle, bufferSize, stride) == null)
                    {
                        throw new InvalidOperationException("Can not decode WebP");
                    }

                    break;

                case 8 :

                    if(WebPDecodeBGRInto_x64(dataHandle, (UIntPtr)dataSize, bufferHandle, bufferSize, stride) == null)
                    {
                        throw new InvalidOperationException("Can not decode WebP");
                    }

                    break;

                default :

                    throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP BGRA 디코딩하기 - WEBPDecodeBGRAInto(dataHandle, dataSize, bufferHandle, bufferSize, stride)

        /// <summary>
        /// WEBP BGRA 디코딩하기
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="bufferHandle">버퍼 핸들</param>
        /// <param name="bufferSize">버퍼 크기</param>
        /// <param name="stride">스트라이드</param>
        public static void WEBPDecodeBGRAInto(IntPtr dataHandle, int dataSize, IntPtr bufferHandle, int bufferSize, int stride)
        {
            switch(IntPtr.Size)
            {
                case 4 :

                    if(WebPDecodeBGRAInto_x86(dataHandle, (UIntPtr)dataSize, bufferHandle, bufferSize, stride) == null)
                    {
                        throw new InvalidOperationException("Can not decode WebP");
                    }

                    break;

                case 8 :

                    if(WebPDecodeBGRAInto_x64(dataHandle, (UIntPtr)dataSize, bufferHandle, bufferSize, stride) == null)
                    {
                        throw new InvalidOperationException("Can not decode WebP");
                    }

                    break;

                default :

                    throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP ARGB 디코딩하기 - WEBPDecodeARGBInto(dataHandle, dataSize, bufferHandle, bufferSize, stride)

        /// <summary>
        /// WEBP ARGB 디코딩하기
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="bufferHandle">버퍼 핸들</param>
        /// <param name="bufferSize">버퍼 크기</param>
        /// <param name="stride">스트라이드</param>
        public static void WEBPDecodeARGBInto(IntPtr dataHandle, int dataSize, IntPtr bufferHandle, int bufferSize, int stride)
        {
            switch(IntPtr.Size)
            {
                case 4 :

                    if(WebPDecodeARGBInto_x86(dataHandle, (UIntPtr)dataSize, bufferHandle, bufferSize, stride) == null)
                    {
                        throw new InvalidOperationException("Can not decode WebP");
                    }

                    break;

                case 8 :

                    if(WebPDecodeARGBInto_x64(dataHandle, (UIntPtr)dataSize, bufferHandle, bufferSize, stride) == null)
                    {
                        throw new InvalidOperationException("Can not decode WebP");
                    }

                    break;

                default :

                    throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 디코더 구성 초기화하기 - WEBPInitializeDecoderConfiguration(configuration)

        /// <summary>
        /// WEBP 디코더 구성 초기화하기
        /// </summary>
        /// <param name="configuration">WEBP 디코더 구성</param>
        /// <returns>처리 결과</returns>
        public static int WEBPInitializeDecoderConfiguration(ref WEBPDecoderConfiguration configuration)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPInitDecoderConfigInternal_x86(ref configuration, WEBP_DECODER_ABI_VERSION);
                case 8  : return WebPInitDecoderConfigInternal_x64(ref configuration, WEBP_DECODER_ABI_VERSION);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 디코딩하기 - WEBPDecode(dataHandle, dataSize, configuration)

        /// <summary>
        /// WEBP 디코딩하기
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="configuration">WEBP 디코더 구성</param>
        /// <returns>상태 코드</returns>
        public static VP8StatusCode WEBPDecode(IntPtr dataHandle, int dataSize, ref WEBPDecoderConfiguration configuration)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPDecode_x86(dataHandle, (UIntPtr)dataSize, ref configuration);
                case 8  : return WebPDecode_x64(dataHandle, (UIntPtr)dataSize, ref configuration);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 디코더 버퍼 해제하기 - WEBPFreeDecoderBuffer(buffer)

        /// <summary>
        /// WEBP 디코더 버퍼 해제하기
        /// </summary>
        /// <param name="buffer">WEBP 디코더 버퍼</param>
        public static void WEBPFreeDecoderBuffer(ref WEBPDecoderBuffer 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");
            }
        }

        #endregion
        #region WEBP BGR 인코딩하기 - WEBPEncodeBGR(bgrHandle, width, height, stride, qualityFactor, outputHandle)

        /// <summary>
        /// WEBP BGR 인코딩하기
        /// </summary>
        /// <param name="bgrHandle">BGR 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="qualityFactor">품질 인자</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        public static int WEBPEncodeBGR(IntPtr bgrHandle, int width, int height, int stride, float qualityFactor, out IntPtr outputHandle)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPEncodeBGR_x86(bgrHandle, width, height, stride, qualityFactor, out outputHandle);
                case 8  : return WebPEncodeBGR_x64(bgrHandle, width, height, stride, qualityFactor, out outputHandle);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP BGRA 인코딩하기 - WEBPEncodeBGRA(bgraHandle, width, height, stride, qualityFactor, outputHandle)

        /// <summary>
        /// WEBP BGRA 인코딩하기
        /// </summary>
        /// <param name="bgraHandle">BGRA 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="qualityFactor">품질 인자</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        public static int WEBPEncodeBGRA(IntPtr bgraHandle, int width, int height, int stride, float qualityFactor, out IntPtr outputHandle)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPEncodeBGRA_x86(bgraHandle, width, height, stride, qualityFactor, out outputHandle);
                case 8  : return WebPEncodeBGRA_x64(bgraHandle, width, height, stride, qualityFactor, out outputHandle);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP BGR 무손실 인코딩하기 - WEBPEncodeLosslessBGR(bgrHandle, width, height, stride, outputHandle)

        /// <summary>
        /// WEBP BGR 무손실 인코딩하기
        /// </summary>
        /// <param name="bgrHandle">BGR 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        public static int WEBPEncodeLosslessBGR(IntPtr bgrHandle, int width, int height, int stride, out IntPtr outputHandle)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPEncodeLosslessBGR_x86(bgrHandle, width, height, stride, out outputHandle);
                case 8  : return WebPEncodeLosslessBGR_x64(bgrHandle, width, height, stride, out outputHandle);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP BGRA 무손실 인코딩하기 - WEBPEncodeLosslessBGRA(bgraHandle, width, height, stride, outputHandle)

        /// <summary>
        /// WEBP BGRA 무손실 인코딩하기
        /// </summary>
        /// <param name="bgraHandle">BGRA 핸들</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="stride">스트라이드</param>
        /// <param name="outputHandle">출력 핸들</param>
        /// <returns>처리 결과</returns>
        public static int WEBPEncodeLosslessBGRA(IntPtr bgraHandle, int width, int height, int stride, out IntPtr outputHandle)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPEncodeLosslessBGRA_x86(bgraHandle, width, height, stride, out outputHandle);
                case 8  : return WebPEncodeLosslessBGRA_x64(bgraHandle, width, height, stride, out outputHandle);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 해제하기 - WEBPFree(handle)

        /// <summary>
        /// WEBP 해제하기
        /// </summary>
        /// <param name="handle">핸들</param>
        public static void WEBPFree(IntPtr handle)
        {
            switch(IntPtr.Size)
            {
                case 4  : WebPFree_x86(handle); break;
                case 8  : WebPFree_x64(handle); break;
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
        #region WEBP 디코더 버전 구하기 - WEBPGetDecoderVersion()

        /// <summary>
        /// WEBP 디코더 버전 구하기
        /// </summary>
        /// <returns>WEBP 디코더 버전</returns>
        public 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");
            }
        }

        #endregion
        #region WEBP 픽처 왜곡 구하기 - WEBPPictureDistortion(sourcePicture, targetPicture, metricType, resultHandle)

        /// <summary>
        /// WEBP 픽처 왜곡 구하기
        /// </summary>
        /// <param name="sourcePicture">소스 픽처</param>
        /// <param name="targetPicture">타겟 픽처</param>
        /// <param name="metricType">미터법 타입</param>
        /// <param name="resultHandle">결과 핸들</param>
        /// <returns>처리 결과</returns>
        public static int WEBPPictureDistortion(ref WEBPPicture sourcePicture, ref WEBPPicture targetPicture, int metricType, IntPtr resultHandle)
        {
            switch(IntPtr.Size)
            {
                case 4  : return WebPPictureDistortion_x86(ref sourcePicture, ref targetPicture, metricType, resultHandle);
                case 8  : return WebPPictureDistortion_x64(ref sourcePicture, ref targetPicture, metricType, resultHandle);
                default : throw new InvalidOperationException("Invalid platform. Can not find proper function");
            }
        }

        #endregion
    }
}

 

▶ WEBPHelper.cs

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// WEBP 헬퍼
    /// </summary>
    public sealed class WEBPHelper : IDisposable
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// WEBP 최대 차원
        /// </summary>
        private const int WEBP_MAXIMUM_DIMENSION = 16383;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 정보 구하기 - GetInformation(sourceByteArray, width, height, hasAlpha, hasAnimation, format)

        /// <summary>
        /// 정보 구하기
        /// </summary>
        /// <param name="sourceByteArray">소스 바이트 배열</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="hasAlpha">알파 여부</param>
        /// <param name="hasAnimation">애니메이션 여부</param>
        /// <param name="format">포맷</param>
        public void GetInformation
        (
            byte[]     sourceByteArray,
            out int    width,
            out int    height,
            out bool   hasAlpha,
            out bool   hasAnimation,
            out string format
        )
        {
            VP8StatusCode statusCode;
            GCHandle      sourceHandle = GCHandle.Alloc(sourceByteArray, GCHandleType.Pinned);

            try
            {
                IntPtr pinnedSourceHandle = sourceHandle.AddrOfPinnedObject();

                WEBPBitStreamFeatures features = new WEBPBitStreamFeatures();

                statusCode = WIN32Helper.WEBPGetFeatures(pinnedSourceHandle, sourceByteArray.Length, ref features);

                if(statusCode != 0)
                {
                    throw new Exception(statusCode.ToString());
                }

                width  = features.Width;
                height = features.Height;

                if(features.HasAlpha == 1)
                {
                    hasAlpha = true;
                }
                else
                {
                    hasAlpha = false;
                }

                if(features.HasAnimation == 1)
                {
                    hasAnimation = true;
                }
                else
                {
                    hasAnimation = false;
                }

                switch(features.Format)
                {
                    case 1  : format = "lossy";     break;
                    case 2  : format = "lossless";  break;
                    default : format = "undefined"; break;
                }
            }
            finally
            {
                if(sourceHandle.IsAllocated)
                {
                    sourceHandle.Free();
                }
            }
        }

        #endregion
        #region 디코딩하기 - Decode(sourceByteArray)

        /// <summary>
        /// 디코딩하기
        /// </summary>
        /// <param name="sourceByteArray">소스 바이트 배열</param>
        /// <returns>비트맵</returns>
        public Bitmap Decode(byte[] sourceByteArray)
        {
            Bitmap     targetBitmap     = null;
            BitmapData targetBitmapData = null;
            GCHandle   sourceHandle     = GCHandle.Alloc(sourceByteArray, GCHandleType.Pinned);

            try
            {
                GetInformation
                (
                    sourceByteArray,
                    out int    imageWidth,
                    out int    imageHeight,
                    out bool   hasAlpha,
                    out bool   hasAnimation,
                    out string format
                );

                if(hasAlpha)
                {
                    targetBitmap = new Bitmap(imageWidth, imageHeight, PixelFormat.Format32bppArgb);
                }
                else
                {
                    targetBitmap = new Bitmap(imageWidth, imageHeight, PixelFormat.Format24bppRgb);
                }

                targetBitmapData = targetBitmap.LockBits
                (
                    new Rectangle(0, 0, imageWidth, imageHeight),
                    ImageLockMode.WriteOnly,
                    targetBitmap.PixelFormat
                );

                int    targetSize = targetBitmapData.Stride * imageHeight;
                IntPtr dataHandle = sourceHandle.AddrOfPinnedObject();

                if(targetBitmap.PixelFormat == PixelFormat.Format24bppRgb)
                {
                    WIN32Helper.WebPDecodeBGRInto
                    (
                        dataHandle,
                        sourceByteArray.Length,
                        targetBitmapData.Scan0,
                        targetSize,
                        targetBitmapData.Stride
                    );
                }
                else
                {
                    WIN32Helper.WEBPDecodeBGRAInto
                    (
                        dataHandle,
                        sourceByteArray.Length,
                        targetBitmapData.Scan0,
                        targetSize,
                        targetBitmapData.Stride
                    );
                }

                return targetBitmap;
            }
            finally
            {
                if(targetBitmapData != null)
                {
                    targetBitmap.UnlockBits(targetBitmapData);
                }

                if(sourceHandle.IsAllocated)
                {
                    sourceHandle.Free();
                }
            }
        }

        #endregion
        #region 디코딩하기 - Decode(sourceByteArray, options, pixelFormat)

        /// <summary>
        /// 디코딩하기
        /// </summary>
        /// <param name="sourceByteArray">소스 바이트 배열</param>
        /// <param name="options">WEBP 디코더 옵션</param>
        /// <param name="pixelFormat">픽셀 포맷</param>
        /// <returns>비트맵</returns>
        public Bitmap Decode(byte[] sourceByteArray, WEBPDecoderOptions options, PixelFormat pixelFormat = PixelFormat.DontCare)
        {
            GCHandle      sourceHandle     = GCHandle.Alloc(sourceByteArray, GCHandleType.Pinned);
            Bitmap        targetBitmap     = null;
            BitmapData    targetBitmapData = null;
            VP8StatusCode result;

            try
            {
                WEBPDecoderConfiguration configuration = new WEBPDecoderConfiguration();

                if(WIN32Helper.WEBPInitializeDecoderConfiguration(ref configuration) == 0)
                {
                    throw new Exception("WebPInitDecoderConfig failed. Wrong version?");
                }

                IntPtr dataHandle = sourceHandle.AddrOfPinnedObject();
                int    width;
                int    height;

                if(options.UseScaling == 0)
                {
                    result = WIN32Helper.WEBPGetFeatures(dataHandle, sourceByteArray.Length, ref configuration.Input);

                    if(result != VP8StatusCode.VP8_STATUS_OK)
                    {
                        throw new Exception("Failed WebPGetFeatures with error " + result);
                    }

                    if(options.UseCropping == 1)
                    {
                        if
                        (
                            options.CropLeft + options.CropWidth  > configuration.Input.Width ||
                            options.CropTop  + options.CropHeight > configuration.Input.Height
                        )
                        {
                            throw new Exception("Crop options exceeded WebP image dimensions");
                        }

                        width  = options.CropWidth;
                        height = options.CropHeight;
                    }
                }
                else
                {
                    width = options.ScaledWidth;
                    height = options.ScaledHeight;
                }

                configuration.Options.BypassFiltering        = options.BypassFiltering;
                configuration.Options.NoFancyUpsampling      = options.NoFancyUpsampling;
                configuration.Options.UseCropping            = options.UseCropping;
                configuration.Options.CropLeft               = options.CropLeft;
                configuration.Options.CropTop                = options.CropTop;
                configuration.Options.CropWidth              = options.CropWidth;
                configuration.Options.CropHeight             = options.CropHeight;
                configuration.Options.UseScaling             = options.UseScaling;
                configuration.Options.ScaledWidth            = options.ScaledWidth;
                configuration.Options.ScaledHeight           = options.ScaledHeight;
                configuration.Options.UseThreads             = options.UseThreads;
                configuration.Options.DitheringStrength      = options.DitheringStrength;
                configuration.Options.Flip                   = options.Flip;
                configuration.Options.AlphaDitheringStrength = options.AlphaDitheringStrength;

                if(configuration.Input.HasAlpha == 1)
                {
                    configuration.Output.ColorSpace = WEBP_CSP_MODE.MODE_bgrA;

                    targetBitmap = new Bitmap(configuration.Input.Width, configuration.Input.Height, PixelFormat.Format32bppArgb);
                }
                else
                {
                    configuration.Output.ColorSpace = WEBP_CSP_MODE.MODE_BGR;

                    targetBitmap = new Bitmap(configuration.Input.Width, configuration.Input.Height, PixelFormat.Format24bppRgb);
                }

                targetBitmapData = targetBitmap.LockBits
                (
                    new Rectangle(0, 0, targetBitmap.Width, targetBitmap.Height),
                    ImageLockMode.WriteOnly,
                    targetBitmap.PixelFormat
                );

                configuration.Output.U.RGBA.RGBA      = targetBitmapData.Scan0;
                configuration.Output.U.RGBA.Stride    = targetBitmapData.Stride;
                configuration.Output.U.RGBA.Size      = (UIntPtr)(targetBitmap.Height * targetBitmapData.Stride);
                configuration.Output.Height           = targetBitmap.Height;
                configuration.Output.Width            = targetBitmap.Width;
                configuration.Output.IsExternalMemory = 1;

                result = WIN32Helper.WEBPDecode(dataHandle, sourceByteArray.Length, ref configuration);

                if(result != VP8StatusCode.VP8_STATUS_OK)
                {
                    throw new Exception("Failed WebPDecode with error " + result);
                }

                WIN32Helper.WEBPFreeDecoderBuffer(ref configuration.Output);

                return targetBitmap;
            }
            finally
            {
                if(targetBitmapData != null)
                {
                    targetBitmap.UnlockBits(targetBitmapData);
                }

                if(sourceHandle.IsAllocated)
                {
                    sourceHandle.Free();
                }
            }
        }

        #endregion
        #region 로드하기 - Load(filePath)

        /// <summary>
        /// 로드하기
        /// </summary>
        /// <param name="filePath">파일 경로</param>
        /// <returns>비트맵</returns>
        public Bitmap Load(string filePath)
        {
            byte[] sourceByteArray = File.ReadAllBytes(filePath);

            return Decode(sourceByteArray);
        }

        #endregion
        #region 고속/저품질 썸네일 구하기 - GetThumbnailWithFasterLowQuality(sourceByteArray, width, height)

        /// <summary>
        /// 고속/저품질 썸네일 구하기
        /// </summary>
        /// <param name="sourceByteArray">소스 바이트 배열</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <returns>비트맵</returns>
        public Bitmap GetThumbnailWithFasterLowQuality(byte[] sourceByteArray, int width, int height)
        {
            GCHandle   sourceHandle = GCHandle.Alloc(sourceByteArray, GCHandleType.Pinned);
            Bitmap     bitmap       = null;
            BitmapData bitmapData   = null;

            try
            {
                WEBPDecoderConfiguration configuration = new WEBPDecoderConfiguration();

                if(WIN32Helper.WEBPInitializeDecoderConfiguration(ref configuration) == 0)
                {
                    throw new Exception("WebPInitDecoderConfig failed. Wrong version?");
                }

                configuration.Options.BypassFiltering   = 1;
                configuration.Options.NoFancyUpsampling = 1;
                configuration.Options.UseThreads        = 1;
                configuration.Options.UseScaling        = 1;
                configuration.Options.ScaledWidth       = width;
                configuration.Options.ScaledHeight      = height;

                bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);

                bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bitmap.PixelFormat);

                configuration.Output.ColorSpace       = WEBP_CSP_MODE.MODE_BGR;
                configuration.Output.U.RGBA.RGBA      = bitmapData.Scan0;
                configuration.Output.U.RGBA.Stride    = bitmapData.Stride;
                configuration.Output.U.RGBA.Size      = (UIntPtr)(height * bitmapData.Stride);
                configuration.Output.Height           = height;
                configuration.Output.Width            = width;
                configuration.Output.IsExternalMemory = 1;

                IntPtr pinnedSourceHandle = sourceHandle.AddrOfPinnedObject();

                VP8StatusCode statusCode = WIN32Helper.WEBPDecode(pinnedSourceHandle, sourceByteArray.Length, ref configuration);

                if(statusCode != VP8StatusCode.VP8_STATUS_OK)
                {
                    throw new Exception("Failed WebPDecode with error " + statusCode);
                }

                WIN32Helper.WEBPFreeDecoderBuffer(ref configuration.Output);

                return bitmap;
            }
            finally
            {
                if(bitmapData != null)
                {
                    bitmap.UnlockBits(bitmapData);
                }

                if(sourceHandle.IsAllocated)
                {
                    sourceHandle.Free();
                }
            }
        }

        #endregion
        #region 저속/고품질 썸네일 구하기 - GetThumbnailWithSlowHighQuality(sourceByteArray, width, height)

        /// <summary>
        /// 저속/고품질 썸네일 구하기
        /// </summary>
        /// <param name="sourceByteArray">소스 바이트 배열</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <returns>비트맵</returns>
        public Bitmap GetThumbnailWithSlowHighQuality(byte[] sourceByteArray, int width, int height)
        {
            GCHandle   sourceHandle = GCHandle.Alloc(sourceByteArray, GCHandleType.Pinned);
            Bitmap     bitmap       = null;
            BitmapData bitmapData   = null;

            try
            {
                WEBPDecoderConfiguration configuration = new WEBPDecoderConfiguration();

                if(WIN32Helper.WEBPInitializeDecoderConfiguration(ref configuration) == 0)
                {
                    throw new Exception("WebPInitDecoderConfig failed. Wrong version?");
                }

                IntPtr pinnedSourceHandle = sourceHandle.AddrOfPinnedObject();

                VP8StatusCode statusCode = WIN32Helper.WEBPGetFeatures(pinnedSourceHandle, sourceByteArray.Length, ref configuration.Input);

                if(statusCode != VP8StatusCode.VP8_STATUS_OK)
                {
                    throw new Exception("Failed WebPGetFeatures with error " + statusCode);
                }

                configuration.Options.BypassFiltering   = 0;
                configuration.Options.NoFancyUpsampling = 0;
                configuration.Options.UseThreads        = 1;
                configuration.Options.UseScaling        = 1;
                configuration.Options.ScaledWidth       = width;
                configuration.Options.ScaledHeight      = height;

                if(configuration.Input.HasAlpha == 1)
                {
                    configuration.Output.ColorSpace = WEBP_CSP_MODE.MODE_bgrA;

                    bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
                }
                else
                {
                    configuration.Output.ColorSpace = WEBP_CSP_MODE.MODE_BGR;

                    bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
                }

                bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bitmap.PixelFormat);

                configuration.Output.U.RGBA.RGBA      = bitmapData.Scan0;
                configuration.Output.U.RGBA.Stride    = bitmapData.Stride;
                configuration.Output.U.RGBA.Size      = (UIntPtr)(height * bitmapData.Stride);
                configuration.Output.Height           = height;
                configuration.Output.Width            = width;
                configuration.Output.IsExternalMemory = 1;

                statusCode = WIN32Helper.WEBPDecode(pinnedSourceHandle, sourceByteArray.Length, ref configuration);

                if(statusCode != VP8StatusCode.VP8_STATUS_OK)
                {
                    throw new Exception("Failed WebPDecode with error " + statusCode);
                }

                WIN32Helper.WEBPFreeDecoderBuffer(ref configuration.Output);

                return bitmap;
            }
            finally
            {
                if(bitmapData != null)
                {
                    bitmap.UnlockBits(bitmapData);
                }

                if(sourceHandle.IsAllocated)
                {
                    sourceHandle.Free();
                }
            }
        }

        #endregion
        #region 저장하기 - Save(bitmap, filePath, quality)

        /// <summary>
        /// 저장하기
        /// </summary>
        /// <param name="bitmap">비트맵</param>
        /// <param name="filePath">파일 경로</param>
        /// <param name="quality">품질</param>
        public void Save(Bitmap bitmap, string filePath, int quality = 75)
        {
            byte[] sourceByteArray;

            sourceByteArray = EncodeLossy(bitmap, quality);

            File.WriteAllBytes(filePath, sourceByteArray);
        }

        #endregion
        #region 손실 인코딩하기 - EncodeLossy(bitmap, quality)

        /// <summary>
        /// 손실 인코딩하기
        /// </summary>
        /// <param name="bitmap">비트맵</param>
        /// <param name="quality">품질</param>
        /// <returns>바이트 배열</returns>
        public byte[] EncodeLossy(Bitmap bitmap, int quality = 75)
        {
            if(bitmap.Width == 0 || bitmap.Height == 0)
            {
                throw new ArgumentException("Bitmap contains no data.", "bmp");
            }

            if(bitmap.Width > WEBP_MAXIMUM_DIMENSION || bitmap.Height > WEBP_MAXIMUM_DIMENSION)
            {
                throw new NotSupportedException
                (
                    "Bitmap's dimension is too large. Max is " + WEBP_MAXIMUM_DIMENSION + "x" + WEBP_MAXIMUM_DIMENSION + " pixels."
                );
            }

            if(bitmap.PixelFormat != PixelFormat.Format24bppRgb && bitmap.PixelFormat != PixelFormat.Format32bppArgb)
            {
                throw new NotSupportedException("Only support Format24bppRgb and Format32bppArgb pixelFormat.");
            }

            BitmapData bitmapData          = null;
            IntPtr     unmanagedDataHandle = IntPtr.Zero;

            try
            {
                int size;
                
                bitmapData = bitmap.LockBits
                (
                    new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                    ImageLockMode.ReadOnly,
                    bitmap.PixelFormat
                );

                if(bitmap.PixelFormat == PixelFormat.Format24bppRgb)
                {
                    size = WIN32Helper.WEBPEncodeBGR
                    (
                        bitmapData.Scan0,
                        bitmap.Width,
                        bitmap.Height,
                        bitmapData.Stride,
                        quality,
                        out unmanagedDataHandle
                    );
                }
                else
                {
                    size = WIN32Helper.WEBPEncodeBGRA
                    (
                        bitmapData.Scan0,
                        bitmap.Width,
                        bitmap.Height,
                        bitmapData.Stride,
                        quality,
                        out unmanagedDataHandle
                    );
                }

                if(size == 0)
                {
                    throw new Exception("Can´t encode WebP");
                }

                byte[] targetByteArray = new byte[size];

                Marshal.Copy(unmanagedDataHandle, targetByteArray, 0, size);

                return targetByteArray;
            }
            finally
            {
                if(bitmapData != null)
                {
                    bitmap.UnlockBits(bitmapData);
                }

                if(unmanagedDataHandle != IntPtr.Zero)
                {
                    WIN32Helper.WEBPFree(unmanagedDataHandle);
                }
            }
        }

        #endregion
        #region 손실 인코딩하기 - EncodeLossy(bitmap, quality, speed, information)

        /// <summary>
        /// 손실 인코딩하기
        /// </summary>
        /// <param name="bitmap">비트맵</param>
        /// <param name="quality">품질</param>
        /// <param name="speed">속도</param>
        /// <param name="information">정보 여부</param>
        /// <returns>바이트 배열</returns>
        public byte[] EncodeLossy(Bitmap bitmap, int quality, int speed, bool information = false)
        {
            WEBPConfiguration configuration = new WEBPConfiguration();

            if(WIN32Helper.WEBPInitializeConfiguration(ref configuration, WEBPPreset.WEBP_PRESET_DEFAULT, 75) == 0)
            {
                throw new Exception("Can´t configure preset");
            }

            configuration.Method = speed;

            if(configuration.Method > 6)
            {
                configuration.Method = 6;
            }

            configuration.Quality        = quality;
            configuration.AutoFilter     = 1;
            configuration.Pass           = speed + 1;
            configuration.SegmentCount   = 4;
            configuration.Partitions     = 3;
            configuration.ThreadLevel    = 1;
            configuration.AlphaQuality   = quality;
            configuration.AlphaFiltering = 2;
            configuration.UseSharpYUV    = 1;

            if(WIN32Helper.WEBPGetDecoderVersion() > 1082)
            {
                configuration.Preprocessing = 4;
                configuration.UseSharpYUV   = 1;
            }
            else
            {
                configuration.Preprocessing = 3;
            }

            return AdvancedEncode(bitmap, configuration, information);
        }

        #endregion
        #region 무손실 인코딩하기 - EncodeLossless(bitmap)

        /// <summary>
        /// 무손실 인코딩하기
        /// </summary>
        /// <param name="bitmap">비트맵</param>
        /// <returns>바이트 배열</returns>
        public byte[] EncodeLossless(Bitmap bitmap)
        {
            if(bitmap.Width == 0 || bitmap.Height == 0)
            {
                throw new ArgumentException("Bitmap contains no data.", "bmp");
            }

            if(bitmap.Width > WEBP_MAXIMUM_DIMENSION || bitmap.Height > WEBP_MAXIMUM_DIMENSION)
            {
                throw new NotSupportedException
                (
                    "Bitmap's dimension is too large. Max is " + WEBP_MAXIMUM_DIMENSION + "x" + WEBP_MAXIMUM_DIMENSION + " pixels."
                );
            }

            if(bitmap.PixelFormat != PixelFormat.Format24bppRgb && bitmap.PixelFormat != PixelFormat.Format32bppArgb)
            {
                throw new NotSupportedException("Only support Format24bppRgb and Format32bppArgb pixelFormat.");
            }

            BitmapData bitmapData          = null;
            IntPtr     unmanagedDataHandle = IntPtr.Zero;

            try
            {
                bitmapData = bitmap.LockBits
                (
                    new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                    ImageLockMode.ReadOnly,
                    bitmap.PixelFormat
                );

                int size;

                if(bitmap.PixelFormat == PixelFormat.Format24bppRgb)
                {
                    size = WIN32Helper.WEBPEncodeLosslessBGR
                    (
                        bitmapData.Scan0,
                        bitmap.Width,
                        bitmap.Height,
                        bitmapData.Stride,
                        out unmanagedDataHandle
                    );
                }
                else
                {
                    size = WIN32Helper.WEBPEncodeLosslessBGRA
                    (
                        bitmapData.Scan0,
                        bitmap.Width,
                        bitmap.Height,
                        bitmapData.Stride,
                        out unmanagedDataHandle
                    );
                }

                byte[] targetByteArray = new byte[size];

                Marshal.Copy(unmanagedDataHandle, targetByteArray, 0, size);

                return targetByteArray;
            }
            finally
            {
                if(bitmapData != null)
                {
                    bitmap.UnlockBits(bitmapData);
                }

                if(unmanagedDataHandle != IntPtr.Zero)
                {
                    WIN32Helper.WEBPFree(unmanagedDataHandle);
                }
            }
        }

        #endregion
        #region 무손실 인코딩하기 - EncodeLossless(bitmap, speed)

        /// <summary>
        /// 무손실 인코딩하기
        /// </summary>
        /// <param name="bitmap">비트맵</param>
        /// <param name="speed">속도</param>
        /// <returns>바이트 배열</returns>
        public byte[] EncodeLossless(Bitmap bitmap, int speed)
        {
            WEBPConfiguration configuration = new WEBPConfiguration();

            if(WIN32Helper.WEBPInitializeConfiguration(ref configuration, WEBPPreset.WEBP_PRESET_DEFAULT, (speed + 1) * 10) == 0)
            {
                throw new Exception("Can´t config preset");
            }
                
            if(WIN32Helper.WEBPGetDecoderVersion() > 1082)
            {
                if(WIN32Helper.WEBPConfigLosslessPreset(ref configuration, speed) == 0)
                {
                    throw new Exception("Can´t configure lossless preset");
                }
            }
            else
            {
                configuration.Lossless = 1;
                configuration.Method   = speed;

                if(configuration.Method > 6)
                {
                    configuration.Method = 6;
                }

                configuration.Quality  = (speed + 1) * 10;
            }

            configuration.Pass           = speed + 1;
            configuration.ThreadLevel    = 1;
            configuration.AlphaFiltering = 2;
            configuration.UseSharpYUV    = 1;
            configuration.Exact          = 0;

            return AdvancedEncode(bitmap, configuration, false);
        }

        #endregion
        #region 무손실 근접 인코딩하기 - EncodeNearLossless(bitmap, quality, speed)

        /// <summary>
        /// 무손실 근접 인코딩하기
        /// </summary>
        /// <param name="bitmap">비트맵</param>
        /// <param name="quality">품질</param>
        /// <param name="speed">속도</param>
        /// <returns>바이트 배열</returns>
        public byte[] EncodeNearLossless(Bitmap bitmap, int quality, int speed = 9)
        {
            if(WIN32Helper.WEBPGetDecoderVersion() <= 1082)
            {
                throw new Exception("This DLL version not support EncodeNearLossless");
            }

            WEBPConfiguration configuration = new WEBPConfiguration();

            if(WIN32Helper.WEBPInitializeConfiguration(ref configuration, WEBPPreset.WEBP_PRESET_DEFAULT, (speed + 1) * 10) == 0)
            {
                throw new Exception("Can´t configure preset");
            }

            if(WIN32Helper.WEBPConfigLosslessPreset(ref configuration, speed) == 0)
            {
                throw new Exception("Can´t configure lossless preset");
            }

            configuration.Pass           = speed + 1;
            configuration.NearLossless   = quality;
            configuration.ThreadLevel    = 1;
            configuration.AlphaFiltering = 2;
            configuration.UseSharpYUV    = 1;
            configuration.Exact          = 0;

            return AdvancedEncode(bitmap, configuration, false);
        }

        #endregion
        #region 버전 구하기 - GetVersion()

        /// <summary>
        /// 버전 구하기
        /// </summary>
        /// <returns>버전</returns>
        public string GetVersion()
        {
            uint version      = (uint)WIN32Helper.WEBPGetDecoderVersion();
            uint revision     = version % 256;
            uint minorVersion = (version >> 8) % 256;
            uint majorVersion = (version >> 16) % 256;

            return majorVersion + "." + minorVersion + "." + revision;
        }

        #endregion
        #region 픽처 왜곡 구하기 - GetPictureDistortion(sourceBitmap, targetBitmap, metricType)

        /// <summary>
        /// 픽처 왜곡 구하기
        /// </summary>
        /// <param name="sourceBitmap">소스 비트맵</param>
        /// <param name="targetBitmap">타겟 비트맵</param>
        /// <param name="metricType">미터법 타입</param>
        /// <returns>픽처 왜곡 배열</returns>
        /// <remarks>
        /// 두 사진 간의 PSNR, SSIM 또는 LSIM 왜곡 메트릭을 계산한다.
        /// 경고 : 이 기능은 CPU를 많이 사용한다.
        /// </remarks>
        public float[] GetPictureDistortion(Bitmap sourceBitmap, Bitmap targetBitmap, int metricType)
        {
            WEBPPicture sourcePicture    = new WEBPPicture();
            WEBPPicture targetPicture    = new WEBPPicture();
            BitmapData  sourceBitmapData = null;
            BitmapData  targetBitmapData = null;
            float[]     targetArray      = new float[5];

            GCHandle pinnedTargetHandle = GCHandle.Alloc(targetArray, GCHandleType.Pinned);

            try
            {
                if(sourceBitmap == null)
                {
                    throw new Exception("Source picture is void");
                }

                if(targetBitmap == null)
                {
                    throw new Exception("Reference picture is void");
                }

                if(metricType > 2)
                {
                    throw new Exception("Bad metric_type. Use 0 = PSNR, 1 = SSIM, 2 = LSIM");
                }

                if(sourceBitmap.Width != targetBitmap.Width || sourceBitmap.Height != targetBitmap.Height)
                {
                    throw new Exception("Source and Reference pictures have different dimensions");
                }

                sourceBitmapData = sourceBitmap.LockBits
                (
                    new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height),
                    ImageLockMode.ReadOnly,
                    sourceBitmap.PixelFormat
                );

                sourcePicture = new WEBPPicture();

                if(WIN32Helper.WEBPInitializePictureInternal(ref sourcePicture) != 1)
                {
                    throw new Exception("Can´t initialize WebPPictureInit");
                }

                sourcePicture.Width  = (int)sourceBitmap.Width;
                sourcePicture.Height = (int)sourceBitmap.Height;

                if(sourceBitmapData.PixelFormat == PixelFormat.Format32bppArgb)
                {
                    sourcePicture.UseARGB = 1;

                    if(WIN32Helper.WEBPPictureImportBGRA(ref sourcePicture, sourceBitmapData.Scan0, sourceBitmapData.Stride) != 1)
                    {
                        throw new Exception("Can´t allocate memory in WebPPictureImportBGR");
                    }
                }
                else
                {
                    sourcePicture.UseARGB = 0;

                    if(WIN32Helper.WEBPPictureImportBGR(ref sourcePicture, sourceBitmapData.Scan0, sourceBitmapData.Stride) != 1)
                    {
                        throw new Exception("Can´t allocate memory in WebPPictureImportBGR");
                    }
                }

                targetBitmapData = targetBitmap.LockBits
                (
                    new Rectangle(0, 0, targetBitmap.Width, targetBitmap.Height),
                    ImageLockMode.ReadOnly,
                    targetBitmap.PixelFormat
                );

                targetPicture = new WEBPPicture();

                if(WIN32Helper.WEBPInitializePictureInternal(ref targetPicture) != 1)
                {
                    throw new Exception("Can´t initialize WebPPictureInit");
                }

                targetPicture.Width   = (int)targetBitmap.Width;
                targetPicture.Height  = (int)targetBitmap.Height;
                targetPicture.UseARGB = 1;

                if(sourceBitmapData.PixelFormat == PixelFormat.Format32bppArgb)
                {
                    sourcePicture.UseARGB = 1;

                    if(WIN32Helper.WEBPPictureImportBGRA(ref targetPicture, targetBitmapData.Scan0, targetBitmapData.Stride) != 1)
                    {
                        throw new Exception("Can´t allocate memory in WebPPictureImportBGR");
                    }
                }
                else
                {
                    sourcePicture.UseARGB = 0;

                    if(WIN32Helper.WEBPPictureImportBGR(ref targetPicture, targetBitmapData.Scan0, targetBitmapData.Stride) != 1)
                    {
                        throw new Exception("Can´t allocate memory in WebPPictureImportBGR");
                    }
                }

                IntPtr targetHandle = pinnedTargetHandle.AddrOfPinnedObject();

                if(WIN32Helper.WEBPPictureDistortion(ref sourcePicture, ref targetPicture, metricType, targetHandle) != 1)
                {
                    throw new Exception("Can´t measure.");
                }

                return targetArray;
            }
            finally
            {
                if(sourceBitmapData != null)
                {
                    sourceBitmap.UnlockBits(sourceBitmapData);
                }

                if(targetBitmapData != null)
                {
                    targetBitmap.UnlockBits(targetBitmapData);
                }

                if(sourcePicture.ARGB != IntPtr.Zero)
                {
                    WIN32Helper.WEBPPictureFree(ref sourcePicture);
                }

                if(targetPicture.ARGB != IntPtr.Zero)
                {
                    WIN32Helper.WEBPPictureFree(ref targetPicture);
                }

                if(pinnedTargetHandle.IsAllocated)
                {
                    pinnedTargetHandle.Free();
                }
            }
        }

        #endregion

        #region 리소스 해제하기 - Dispose()

        /// <summary>
        /// 리소스 해제하기
        /// </summary>
        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 메모리 라이터 - MemoryWriter(dataHandle, dataSize, picture)

        /// <summary>
        /// 메모리 라이터
        /// </summary>
        /// <param name="dataHandle">데이터 핸들</param>
        /// <param name="dataSize">데이터 크기</param>
        /// <param name="picture">WEBP 픽처</param>
        /// <returns>처리 결과</returns>
        private int MemoryWriter([InAttribute()] IntPtr dataHandle, UIntPtr dataSize, ref WEBPPicture picture)
        {
            WIN32Helper.CopyMemory(picture.CustomPointer, dataHandle, (uint)dataSize);

            picture.CustomPointer = new IntPtr(picture.CustomPointer.ToInt64() + (int)dataSize);

            return 1;
        }
        
        #endregion
        #region 개선 인코딩하기 - AdvancedEncode(bitmap, configuration, information)

        /// <summary>
        /// 개선 인코딩하기
        /// </summary>
        /// <param name="bitmap">비트맵</param>
        /// <param name="configuration">WEBP 구성</param>
        /// <param name="information">정보 여부</param>
        /// <returns>바이트 배열</returns>
        private byte[] AdvancedEncode(Bitmap bitmap, WEBPConfiguration configuration, bool information)
        {
            byte[]                  targetByteArray = null;
            byte[]                  sourceByteArray = null;
            WEBPPicture             picture           = new WEBPPicture();
            BitmapData              bitmapData        = null;
            WEBPAuxiliaryStatistics statistics        = new WEBPAuxiliaryStatistics();
            IntPtr                  statisticsHandle  = IntPtr.Zero;
            GCHandle                pinnedArrayHandle = new GCHandle();
            int                     sourceSize;

            try
            {
                if(WIN32Helper.WEBPValidateConfiguration(ref configuration) != 1)
                {
                    throw new Exception("Bad configuration parameters");
                }

                if(bitmap.Width == 0 || bitmap.Height == 0)
                {
                    throw new ArgumentException("Bitmap contains no data.", "bmp");
                }

                if(bitmap.Width > WEBP_MAXIMUM_DIMENSION || bitmap.Height > WEBP_MAXIMUM_DIMENSION)
                {
                    throw new NotSupportedException
                    (
                        "Bitmap's dimension is too large. Max is " + WEBP_MAXIMUM_DIMENSION + "x" + WEBP_MAXIMUM_DIMENSION + " pixels."
                    );
                }

                if(bitmap.PixelFormat != PixelFormat.Format24bppRgb && bitmap.PixelFormat != PixelFormat.Format32bppArgb)
                {
                    throw new NotSupportedException("Only support Format24bppRgb and Format32bppArgb pixelFormat.");
                }

                bitmapData = bitmap.LockBits
                (
                    new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                    ImageLockMode.ReadOnly,
                    bitmap.PixelFormat
                );

                if(WIN32Helper.WEBPInitializePictureInternal(ref picture) != 1)
                {
                    throw new Exception("Can´t initialize WebPPictureInit");
                }

                picture.Width   = (int)bitmap.Width;
                picture.Height  = (int)bitmap.Height;
                picture.UseARGB = 1;

                if(bitmap.PixelFormat == PixelFormat.Format32bppArgb)
                {
                    int result = WIN32Helper.WEBPPictureImportBGRA(ref picture, bitmapData.Scan0, bitmapData.Stride);

                    if(result != 1)
                    {
                        throw new Exception("Can´t allocate memory in WebPPictureImportBGRA");
                    }

                    picture.ColorSpace = (uint)WEBP_CSP_MODE.MODE_bgrA;

                    sourceSize = bitmap.Width * bitmap.Height * 32;
                    sourceByteArray = new byte[bitmap.Width * bitmap.Height * 32]; 
                }
                else
                {
                    int result = WIN32Helper.WEBPPictureImportBGR(ref picture, bitmapData.Scan0, bitmapData.Stride);

                    if(result != 1)
                    {
                        throw new Exception("Can´t allocate memory in WebPPictureImportBGR");
                    }

                    sourceSize = bitmap.Width * bitmap.Height * 24;
                }

                if(information)
                {
                    statistics       = new WEBPAuxiliaryStatistics();
                    statisticsHandle = Marshal.AllocHGlobal(Marshal.SizeOf(statistics));

                    Marshal.StructureToPtr(statistics, statisticsHandle, false);

                    picture.Statistics = statisticsHandle;
                }

                if(sourceSize > 2147483591)
                {
                    sourceSize = 2147483591;
                }

                sourceByteArray = new byte[bitmap.Width * bitmap.Height * 32];

                pinnedArrayHandle = GCHandle.Alloc(sourceByteArray, GCHandleType.Pinned);

                IntPtr initialHandle = pinnedArrayHandle.AddrOfPinnedObject();

                picture.CustomPointer = initialHandle;

                WIN32Helper.memoryWriteDelegate = new WIN32Helper.WEBPMemoryWriteDelegate(MemoryWriter);

                picture.Writer = Marshal.GetFunctionPointerForDelegate(WIN32Helper.memoryWriteDelegate);

                if(WIN32Helper.WEBPEncode(ref configuration, ref picture) != 1)
                {
                    throw new Exception("Encoding error : " + ((WEBPEncodingError)picture.ErrorCode).ToString());
                }

                WIN32Helper.memoryWriteDelegate = null;

                bitmap.UnlockBits(bitmapData);

                bitmapData = null;

                int size = (int)((long)picture.CustomPointer - (long)initialHandle);

                targetByteArray = new byte[size];

                Array.Copy(sourceByteArray, targetByteArray, size);

                pinnedArrayHandle.Free();

                sourceByteArray = null;

                if(information)
                {
                    statistics = (WEBPAuxiliaryStatistics)Marshal.PtrToStructure(statisticsHandle, typeof(WEBPAuxiliaryStatistics));

                    MessageBox.Show
                    (
                        "Dimension      : " + picture.Width + " x " + picture.Height + " pixels\n"        +
                        "Output         : " + statistics.CodedSize                 + " bytes\n"           +
                        "PSNR Y         : " + statistics.PSNRY                     + " db\n"              +
                        "PSNR u         : " + statistics.PSNRU                     + " db\n"              +
                        "PSNR v         : " + statistics.PSNRV                     + " db\n"              +
                        "PSNR ALL       : " + statistics.PSNRALL                   + " db\n"              +
                        "Block intra4   : " + statistics.BlockCountIntra4          + "\n"                 +
                        "Block intra16  : " + statistics.BlockCountIntra16         + "\n"                 +
                        "Block skipped  : " + statistics.BlockCountSkipped         + "\n"                 +
                        "Header size    : " + statistics.HeaderByteCount           + " bytes\n"           +
                        "Mode-partition : " + statistics.ModePartition0            + " bytes\n"           +
                        "Macro-blocks 0 : " + statistics.SegmentSizeSegments0      + " residuals bytes\n" +
                        "Macro-blocks 1 : " + statistics.SegmentSizeSegments1      + " residuals bytes\n" +
                        "Macro-blocks 2 : " + statistics.SegmentSizeSegments2      + " residuals bytes\n" +
                        "Macro-blocks 3 : " + statistics.SegmentSizeSegments3      + " residuals bytes\n" +
                        "Quantizer    0 : " + statistics.SegmentQuantizerSegments0 + " residuals bytes\n" +
                        "Quantizer    1 : " + statistics.SegmentQuantizerSegments1 + " residuals bytes\n" +
                        "Quantizer    2 : " + statistics.SegmentQuantizerSegments2 + " residuals bytes\n" +
                        "Quantizer    3 : " + statistics.SegmentQuantizerSegments3 + " residuals bytes\n" +
                        "Filter level 0 : " + statistics.SegmentLevelSegments0     + " residuals bytes\n" +
                        "Filter level 1 : " + statistics.SegmentLevelSegments1     + " residuals bytes\n" +
                        "Filter level 2 : " + statistics.SegmentLevelSegments2     + " residuals bytes\n" +
                        "Filter level 3 : " + statistics.SegmentLevelSegments3     + " residuals bytes\n",
                        "Compression statistics"
                    );
                }

                return targetByteArray;
            }
            finally
            {
                if(pinnedArrayHandle.IsAllocated)
                {
                    pinnedArrayHandle.Free();
                }

                if(statisticsHandle != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(statisticsHandle);
                }

                if(bitmapData != null)
                {
                    bitmap.UnlockBits(bitmapData);
                }

                if(picture.ARGB != IntPtr.Zero)
                {
                    WIN32Helper.WEBPPictureFree(ref picture);
                }
            }
        }

        #endregion
    }
}

 

▶ MainForm.cs

using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : Form
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 파일 열기 대화 상자 1
        /// </summary>
        private OpenFileDialog openFileDialog1;

        /// <summary>
        /// 파일 열기 대화 상자 2
        /// </summary>
        private OpenFileDialog openFileDialog2;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            this.openFileDialog1 = new OpenFileDialog();

            this.openFileDialog1.Filter   = "이미지 파일(*.webp, *.png, *.tif, *.tiff)|*.webp;*.png;*.tif;*.tiff";
            this.openFileDialog1.FileName = string.Empty;

            this.openFileDialog2 = new OpenFileDialog();

            this.openFileDialog2.Filter   = "WebP 파일(*.webp)|*.webp";
            this.openFileDialog2.FileName = string.Empty;

            Load                         += Form_Load;
            this.loadButton.Click        += loadButton_Click;
            this.saveButton.Click        += saveButton_Click;
            this.cropFlipButton.Click    += cropFlipButton_Click;
            this.thumbnailButton.Click   += thumbnailButton_Click;
            this.measureButton.Click     += measureButton_Click;
            this.informationButton.Click += informationButton_Click;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 폼 로드시 처리하기 - Form_Load(sender, e)

        /// <summary>
        /// 폼 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_Load(object sender, EventArgs e)
        {
            try
            {
                using(WEBPHelper webp = new WEBPHelper())
                {
                    Text += " (libwebp V" + webp.GetVersion() + ")";
                }
            }
            catch(Exception exception)
            {
                MessageBox.Show(this, exception.ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion
        #region 이미지 로드 버튼 클릭시 처리하기 - loadButton_Click(sender, e)

        /// <summary>
        /// 이미지 로드 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void loadButton_Click(object sender, EventArgs e)
        {
            try
            {
                if(this.openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    string filePath = this.openFileDialog1.FileName;

                    if(Path.GetExtension(filePath) == ".webp")
                    {
                        using(WEBPHelper webp = new WEBPHelper())
                        {
                            this.pictureBox.Image = webp.Load(filePath);
                        }
                    }
                    else
                    {
                        this.pictureBox.Image = Image.FromFile(filePath);
                    }
                }
            }
            catch(Exception exception)
            {
                MessageBox.Show(this, exception.ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion
        #region WEBP 저장 버튼 클릭시 처리하기 - saveButton_Click(sender, e)

        /// <summary>
        /// WEBP 저장 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void saveButton_Click(object sender, EventArgs e)
        {
            if(this.pictureBox.Image == null)
            {
                MessageBox.Show("저장할 이미지가 없습니다.");

                return;
            }

            CheckForIllegalCrossThreadCalls = false;

            byte[] targetByteArray;

            try
            {
                Bitmap sourceBitmap = this.pictureBox.Image as Bitmap;

                // 손실 인코딩
                string filePath1 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SimpleLossy.webp");

                using(WEBPHelper webp = new WEBPHelper())
                {
                    targetByteArray = webp.EncodeLossy(sourceBitmap, 75);
                }

                File.WriteAllBytes(filePath1, targetByteArray);

                // 무손실 인코딩
                string filePath2 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SimpleLossless.webp");

                using(WEBPHelper webp = new WEBPHelper())
                {
                    targetByteArray = webp.EncodeLossless(sourceBitmap);
                }

                File.WriteAllBytes(filePath2, targetByteArray);

                // 개선된 손실 인코딩
                string filePath3 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AdvanceLossy.webp");

                using(WEBPHelper webp = new WEBPHelper())
                {
                    targetByteArray = webp.EncodeLossy(sourceBitmap, 71, 9, true);
                }

                File.WriteAllBytes(filePath3, targetByteArray);

                // 개선된 무손실 인코딩
                string filePath4 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AdvanceLossless.webp");

                using(WEBPHelper webp = new WEBPHelper())
                {
                    targetByteArray = webp.EncodeLossless(sourceBitmap, 9);
                }

                File.WriteAllBytes(filePath4, targetByteArray);

                // 메모리에서 품질 40 및 속도 9로 근접 무손실 모드로 인코딩 테스트
                // 품질 100      : 손실 없음(-lossless와 동일한 비트 스트림)
                // 품질 80       : 매우 매우 높은 PSNR(약 54dB)이며 WebP 무손실 이미지에 비해 추가로 5-10% 크기 감소를 얻는다.
                // 품질 60       : PSNR이 매우 높고(약 48dB) WebP 무손실 이미지에 비해 추가로 20%-25% 크기 감소를 얻는다.
                // 품질 40       : 높은 PSNR(약 42dB) 및 WebP 무손실 이미지에 비해 추가로 30-35% 크기 감소를 얻는다.
                // 품질 20(이하) : 중간 PSNR(약 36dB)이며 WebP 무손실 이미지에 비해 추가로 40-50% 크기 감소를 얻는다.
                string filePath5 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "NearLossless.webp");

                using(WEBPHelper webp = new WEBPHelper())
                {
                    targetByteArray = webp.EncodeNearLossless(sourceBitmap, 40, 9);
                }

                File.WriteAllBytes(filePath5, targetByteArray);

                MessageBox.Show("작업을 완료했습니다.");
            }
            catch(Exception exception)
            {
                MessageBox.Show(this, exception.ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion
        #region 로드(CROP/FLIP) 버튼 클릭시 처리하기 - cropFlipButton_Click(sender, e)

        /// <summary>
        /// 로드(CROP/FLIP) 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void cropFlipButton_Click(object sender, EventArgs e)
        {
            try
            {
                if(this.openFileDialog2.ShowDialog() == DialogResult.OK)
                {
                    string filePath = this.openFileDialog2.FileName;

                    byte[] sourceByteArray = File.ReadAllBytes(filePath);

                    WEBPDecoderOptions decoderOptions = new WEBPDecoderOptions
                    {
                        UseCropping = 1,
                        CropTop     = 10,  // 자르기 영역의 맨 위 시작
                        CropLeft    = 10,  // 자르기 영역의 왼쪽 시작
                        CropHeight  = 250, // 자르기 영역의 높이
                        CropWidth   = 300, // 자르기 영역의 너비
                        UseThreads  = 1,   // 멀티 스레딩 사용
                        Flip         = 1    // 이미지 뒤집기
                    };

                    using(WEBPHelper webp = new WEBPHelper())
                    {
                        this.pictureBox.Image = webp.Decode(sourceByteArray, decoderOptions);
                    }
                }
            }
            catch(Exception exception)
            {
                MessageBox.Show(this, exception.ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion
        #region 썸네일 로드 버튼 클릭시 처리하기 - thumbnailButton_Click(sender, e)

        /// <summary>
        /// 썸네일 로드 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void thumbnailButton_Click(object sender, EventArgs e)
        {
            try
            {
                if(this.openFileDialog2.ShowDialog() == DialogResult.OK)
                {
                    string filePath = this.openFileDialog2.FileName;

                    byte[] sourceByteArray = File.ReadAllBytes(filePath);

                    using(WEBPHelper webp = new WEBPHelper())
                    {
                        this.pictureBox.Image = webp.GetThumbnailWithSlowHighQuality(sourceByteArray, 200, 150);
                    }
                }
            }
            catch(Exception exception)
            {
                MessageBox.Show(this, exception.ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion
        #region WEBP 측정 버튼 클릭시 처리하기 - measureButton_Click(sender, e)

        /// <summary>
        /// WEBP 측정 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void measureButton_Click(object sender, EventArgs e)
        {
            try
            {
                if(this.pictureBox.Image == null)
                {
                    MessageBox.Show("이미지가 없습니다.");
                }

                if(this.openFileDialog2.ShowDialog() == DialogResult.OK)
                {
                    Bitmap  sourceBitmap = this.pictureBox.Image as Bitmap;
                    Bitmap  referenceBitmap;
                    float[] targetArray;

                    using(WEBPHelper webp = new WEBPHelper())
                    {
                        referenceBitmap = webp.Load(this.openFileDialog2.FileName);
                    }

                    using(WEBPHelper webp = new WEBPHelper())
                    {
                        targetArray = webp.GetPictureDistortion(sourceBitmap, referenceBitmap, 0); // PSNR 측정
                    }

                    MessageBox.Show
                    (
                        this,
                        $"적색 : {targetArray[0]}dB.\n" +
                        $"녹색 : {targetArray[1]}dB.\n" + 
                        $"청색 : {targetArray[2]}dB.\n" +
                        $"알파 : {targetArray[3]}dB.\n" +
                        $"전체 : {targetArray[4]}dB.",
                        "PSNR",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information
                    );

                    using(WEBPHelper webp = new WEBPHelper())
                    {
                        targetArray = webp.GetPictureDistortion(sourceBitmap, referenceBitmap, 1); // SSIM 측정
                    }

                    MessageBox.Show
                    (
                        this,
                        $"적색 : {targetArray[0]}dB.\n" +
                        $"녹색 : {targetArray[1]}dB.\n" + 
                        $"청색 : {targetArray[2]}dB.\n" +
                        $"알파 : {targetArray[3]}dB.\n" +
                        $"전체 : {targetArray[4]}dB.",
                        "PSNR",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information
                    );

                    using(WEBPHelper webp = new WEBPHelper())
                    {
                        targetArray = webp.GetPictureDistortion(sourceBitmap, referenceBitmap, 2); // LSIM 측정
                    }

                    MessageBox.Show
                    (
                        this,
                        $"적색 : {targetArray[0]}dB.\n" +
                        $"녹색 : {targetArray[1]}dB.\n" + 
                        $"청색 : {targetArray[2]}dB.\n" +
                        $"알파 : {targetArray[3]}dB.\n" +
                        $"전체 : {targetArray[4]}dB.",
                        "PSNR",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information
                    );
                }
            }
            catch(Exception exception)
            {
                MessageBox.Show(this, exception.ToString(), "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion
        #region WEBP 정보 버튼 클릭시 처리하기 - informationButton_Click(sender, e)

        /// <summary>
        /// WEBP 정보 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void informationButton_Click(object sender, EventArgs e)
        {
            int    width;
            int    height;
            bool   has_alpha;
            bool   has_animation;
            string format;

            try
            {
                if(this.openFileDialog2.ShowDialog() == DialogResult.OK)
                {
                    string filePath = this.openFileDialog2.FileName;

                    byte[] sourceByteArray = File.ReadAllBytes(filePath);

                    using(WEBPHelper webp = new WEBPHelper())
                    {
                        webp.GetInformation(sourceByteArray, out width, out height, out has_alpha, out has_animation, out format);
                    }

                    MessageBox.Show
                    (
                        this,
                        $"너비 : {width}\n"                    +
                        $"높이 : {height}\n"                   +
                        $"투명도 여부 : {has_alpha}\n"         +
                        $"애니메이션 여부 : {has_animation}\n" +
                        $"포맷 : {format}",
                        "INFORMATION",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information
                    );
                }
            }
            catch(Exception exception)
            {
                MessageBox.Show(this, exception.ToString(), "INFORMATION", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요