๋ฐ˜์‘ํ˜•

WebP(์›นํ”ผ)๋ž€?

WebP ๋ณ€ํ™˜ ์˜ˆ์‹œ ์ด๋ฏธ์ง€. ์ถœ์ฒ˜: WebP Google Homepage
WebP ๋ณ€ํ™˜ ์˜ˆ์‹œ ์ด๋ฏธ์ง€. ์ถœ์ฒ˜: WebP Google Homepage

C#์—์„œ WebP ๋ณ€ํ™˜ ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•˜๊ธฐ์— ์•ž์„œ, WebP๊ฐ€ ๋ฌด์—‡์ธ์ง€๋ถ€ํ„ฐ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. WebP๋Š” ๊ตฌ๊ธ€์—์„œ ๋งŒ๋“  ์ด๋ฏธ์ง€ ํฌ๋งท์ž…๋‹ˆ๋‹ค(WebP๋Š” ์›นํ”ผ๋ผ๊ณ  ์ฝ์Šต๋‹ˆ๋‹ค). WebP์˜ ์„ค๋ช…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

WebP(์›นํ”ผ, weppy)๋Š” ์†์‹ค/๋น„์†์‹ค ์••์ถ• ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ์œ„ํ•œ ์ด๋ฏธ์ง€ ํฌ๋งท์ด๋‹ค. On2 ํ…Œํฌ๋†€๋Ÿฌ์ง€์Šค์˜ ๊ธฐ์ˆ ์„ ๊ตฌ๋งคํ•˜์—ฌ, ๊ทธ๊ฒƒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ๊ธ€์ด ๊ฐœ๋ฐœํ•˜์—ฌ, 2010๋…„ 9์›” 30์ผ ๊ณต๊ฐœํ•˜์˜€๋‹ค. ์˜์ƒ ํฌ๋งท์ธ VP8์˜ ํŒŒ์ƒ์œผ๋กœ, ๋ฉ€ํ‹ฐ๋ฏธ๋””์–ด๋ฅผ ๋‹ด๋Š” ํฌ๋งท์ธ WebM์˜ ์ž๋งค ํ”„๋กœ์ ํŠธ์ด๋‹ค. - ์œ„ํ‚ค๋ฐฑ๊ณผ

๋ถ€์—ฐ ์„ค๋ช…์„ ํ•˜์ž๋ฉด, WebP ํฌ๋งท์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” JPEG, PNG์™€ ๊ฐ™์€ ํฌ๋งท์„ ๋Œ€์ฒดํ•˜๊ธฐ ์œ„ํ•ด ๊ฐœ๋ฐœ๋œ ๊ฒƒ์ธ๋ฐ์š”. ๊ธฐ์กด ํฌ๋งท ๋Œ€๋น„ํ•˜์—ฌ ์••์ถ•๋ฅ ์€ ๋”์šฑ ์ข‹์•„์ง€๊ณ  ๋น„์Šทํ•œ ํ’ˆ์งˆ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ๊ธ€์€ ์ˆ˜๋งŽ์€ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋“ค์„ ๋ณด์—ฌ์ฃผ๋Š”๋ฐ, ๊ฐ ํŽ˜์ด์ง€๋งˆ๋‹ค ์ด๋ฏธ์ง€ ํฌ๋งท์„ WebP๋กœ ๋Œ€์ฒดํ•œ๋‹ค๋ฉด ์„œ๋ฒ„ ํŠธ๋ž˜ํ”ฝ์ด ์ƒ๋‹นํžˆ ๋งŽ์ด ์ค„์–ด๋“ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ ํŠธ๋ž˜ํ”ฝ๋„ ๋น„์šฉ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๊ตฌ๊ธ€์€ ๋น„์šฉ ์ ˆ๊ฐ์„ ์œ„ํ•ด ์ด๋Ÿฌํ•œ ํฌ๋งท์„ ๋งŒ๋“  ๊ฒƒ์ด ์•„๋‹Œ๊ฐ€ ํ•˜๋Š” ์ƒ๊ฐ์ด ๋“ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

WebP Library ์ฐธ๊ณ  ์‚ฌ์ดํŠธ

WebP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๊ด€ํ•œ ์ž๋ฃŒ๋Š” ์•„๋ž˜ ํ™ˆํŽ˜์ด์ง€์—์„œ ์ฐธ๊ณ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

https://developers.google.com/speed/webp

 

An image format for the Web | WebP | Google Developers

An image format for the Web.

developers.google.com

WebP์— ๊ด€ํ•œ ์†Œ๊ฐœ์™€ API๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์„ค๋ช…, ๊ทธ๋ฆฌ๊ณ  ์˜ต์…˜์— ๋”ฐ๋ฅธ ์ด๋ฏธ์ง€ ์„ค๋ช…์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  .Net์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋„๋ก WebP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ์‹ผ libwebp-net๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

https://github.com/imazen/libwebp-net

 

GitHub - imazen/libwebp-net: A .NET wrapper for libwebp

A .NET wrapper for libwebp. Contribute to imazen/libwebp-net development by creating an account on GitHub.

github.com

์ฐธ๊ณ ๋กœ NuGet์—์„œ๋„ Imazen.WebP๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Imazen.WebP NuGet Package
Imazen.WebP NuGet Package

ํ•˜์ง€๋งŒ Imazen.WebP๋Š” ์•ฝ 4๋…„ ์ „์— ์—…๋ฐ์ดํŠธํ•œ ์ดํ›„ ๋” ์ด์ƒ ์—…๋ฐ์ดํŠธ๊ฐ€ ์ด๋ค„์ง€์ง€ ์•Š๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ SimpleEncoder ๊ฐ์ฒด์˜ Encode ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ 'GDI+ ์ผ๋ฐ˜ ์˜ค๋ฅ˜'๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์ง„ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋ณธ๋ฌธ์—์„œ๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ C#์—์„œ WebP Library๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.

libwebp.dll๋กœ C#์—์„œ WebP ๋ณ€ํ™˜ํ•˜๊ธฐ

์•ž์—์„œ ์–ธ๊ธ‰ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ, Imazen.WebP ์‚ฌ์šฉ ์‹œ GDI+ ์ผ๋ฐ˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋ฐ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์•„๋ฌด๋ฆฌ ๊ฒ€์ƒ‰ํ•ด๋„ ๋‚˜์˜ค์ง€ ์•Š๋”๊ตฐ์š”. ๊ทธ๋ž˜์„œ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ, libwebp.dll์„ P/Invoke ๋ฐฉ์‹์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

C#์—์„œ P/Invoke ๋ฐฉ์‹์œผ๋กœ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด, ๋‹ค์Œ์˜ libwebp.dll์„ ๋‹ค์šด๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ํŒŒ์ผ์€ Imazen.WebP GitHub์— ๋‹ค์šด๋กœ๋“œ ์ฃผ์†Œ๊ฐ€ ๊ธฐ์žฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

x86_x64 libwebp.dll v0.5.2

x86 libwebp.dll v0.5.2

๋งŒ์•ฝ, ์œ„ ๋งํฌ์˜ ํŒŒ์ผ์ด ๋‹ค์šด๋กœ๋“œ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์•„๋ž˜์˜ ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•˜์„ธ์š”.

libwebp.zip
0.40MB

ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œ ํ•œ ํ›„ ํ”„๋กœ์ ํŠธ ๊ฒฝ๋กœ์— ๋ถ™์—ฌ ๋„ฃ์Šต๋‹ˆ๋‹ค.

๊ฒฝ๋กœ์— libwebp.dll ์ถ”๊ฐ€
๊ฒฝ๋กœ์— libwebp.dll ์ถ”๊ฐ€

๊ทธ๋ฆฌ๊ณ  ํ”„๋กœ์ ํŠธ ํŒŒ์ผ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ์— libwebp.dll ์ถ”๊ฐ€ํ•˜๊ธฐ
ํ”„๋กœ์ ํŠธ์— libwebp.dll ์ถ”๊ฐ€ํ•˜๊ธฐ

์ถ”๊ฐ€๋œ dll ํŒŒ์ผ์˜ ์†์„ฑ์—์„œ ์ถœ๋ ฅ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋ณต์‚ฌ ํ•ญ๋ชฉ์„ ํ•ญ์ƒ ๋ณต์‚ฌ๋กœ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

ํ•ญ์ƒ ๋ณต์‚ฌ ์˜ต์…˜ ์„ ํƒ
ํ•ญ์ƒ ๋ณต์‚ฌ ์˜ต์…˜ ์„ ํƒ

๊ทธ๋ฆฌ๊ณ  WebP.cs ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;

namespace ExamWebPConverter
{
    class WebP
    {
        [DllImport("libwebp.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int WebPEncodeBGR(IntPtr ptrIn, int width, int height, int stride, float quality, out IntPtr ptrOut);

        [DllImport("libwebp.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int WebPEncodeLosslessBGR(IntPtr ptrIn, int width, int height, int stride, out IntPtr ptrOut);

        [DllImport("libwebp.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int WebPFree(IntPtr ptr);

        public void SaveLossy(Bitmap bmp, string path, int quality)
        {
            byte[] arrayWebP = null;

            EncodeLossy(bmp, out arrayWebP, quality);

            File.WriteAllBytes(path, arrayWebP);
        }

        private void EncodeLossy(Bitmap bmp, out byte[] arrayWebP, int quality)
        {
            IntPtr unmanagedPtr;
            BitmapData dataBitmap = null;

            dataBitmap = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            int size = WebPEncodeBGR(dataBitmap.Scan0, bmp.Width, bmp.Height, dataBitmap.Stride, quality, out unmanagedPtr);

            arrayWebP = new byte[size];
            Marshal.Copy(unmanagedPtr, arrayWebP, 0, size);

            bmp.UnlockBits(dataBitmap);

            WebPFree(unmanagedPtr);
        }

        public void SaveLossless(Bitmap bmp, string path)
        {
            byte[] arrayWebP = null;

            EncodeLossless(bmp, out arrayWebP);

            File.WriteAllBytes(path, arrayWebP);
        }

        private void EncodeLossless(Bitmap bmp, out byte[] arrayWebP)
        {
            IntPtr unmanagedPtr;
            BitmapData dataBitmap = null;

            dataBitmap = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            int size = WebPEncodeLosslessBGR(dataBitmap.Scan0, bmp.Width, bmp.Height, dataBitmap.Stride, out unmanagedPtr);

            arrayWebP = new byte[size];
            Marshal.Copy(unmanagedPtr, arrayWebP, 0, size);

            bmp.UnlockBits(dataBitmap);

            WebPFree(unmanagedPtr);
        }
    }
}

SaveLossy๋Š” ์†์‹ค ์••์ถ•์„, SaveLossless๋Š” ๋ฌด์†์‹ค ์••์ถ•์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ํ•จ์ˆ˜์˜ ๋™์ž‘์€ Bitmap์œผ๋กœ ์ž…๋ ฅ๋ฐ›์€ ํŒŒ์ผ์„ WebP ํŒŒ์ผ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ, ์œ„ ์ฝ”๋“œ๋Š” WebP๋กœ Encode ํ•˜๋Š” API๋งŒ ์ •์˜ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ WebP๋ฅผ Decode ํ•˜๋Š” API๋„ ์ •์˜ํ•˜๋ฉด WebP๋ฅผ PNG๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„ ์ฝ”๋“œ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

private void buttonConvert_Click(object sender, EventArgs e)
{
	try
	{
		WebP w = new WebP();

		Bitmap bmp = new Bitmap(@"../../../image/1.jpg");
		w.SaveLossy(bmp, @"../../../image/1_lossy.webp", 75);
		w.SaveLossless(bmp, @"../../../image/1_lossless.webp");
	}
	catch(Exception exc)
	{
		MessageBox.Show(exc.Message);
	}
}

์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ์ƒ˜ํ”Œ ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

ExamWebPConverter.zip
0.27MB

๋ฐ˜์‘ํ˜•