We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add support for RGBA webp image encoding and decoding
Would it be possible to wrap the `WebPEncodeRGBA` and `WebPDecodeRGBA` functionality of the webp library inside Pillow?


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `selftest.py`
Content:
```
1 # minimal sanity check
2 from __future__ import print_function
3 ROOT = "."
4 
5 import os, sys
6 sys.path.insert(0, ROOT)
7 
8 from PIL import Image
9 from PIL import ImageDraw
10 from PIL import ImageFilter
11 from PIL import ImageMath
12 
13 try:
14     Image.core.ping
15 except ImportError as v:
16     print("***", v)
17     sys.exit()
18 except AttributeError:
19     pass
20 
21 def _info(im):
22     im.load()
23     return im.format, im.mode, im.size
24 
25 def testimage():
26     """
27     PIL lets you create in-memory images with various pixel types:
28 
29     >>> im = Image.new("1", (128, 128)) # monochrome
30     >>> _info(im)
31     (None, '1', (128, 128))
32     >>> _info(Image.new("L", (128, 128))) # grayscale (luminance)
33     (None, 'L', (128, 128))
34     >>> _info(Image.new("P", (128, 128))) # palette
35     (None, 'P', (128, 128))
36     >>> _info(Image.new("RGB", (128, 128))) # truecolor
37     (None, 'RGB', (128, 128))
38     >>> _info(Image.new("I", (128, 128))) # 32-bit integer
39     (None, 'I', (128, 128))
40     >>> _info(Image.new("F", (128, 128))) # 32-bit floating point
41     (None, 'F', (128, 128))
42 
43     Or open existing files:
44 
45     >>> im = Image.open(os.path.join(ROOT, "Images/lena.gif"))
46     >>> _info(im)
47     ('GIF', 'P', (128, 128))
48     >>> _info(Image.open(os.path.join(ROOT, "Images/lena.ppm")))
49     ('PPM', 'RGB', (128, 128))
50     >>> try:
51     ...  _info(Image.open(os.path.join(ROOT, "Images/lena.jpg")))
52     ... except IOError as v:
53     ...  print(v)
54     ('JPEG', 'RGB', (128, 128))
55 
56     PIL doesn't actually load the image data until it's needed,
57     or you call the "load" method:
58 
59     >>> im = Image.open(os.path.join(ROOT, "Images/lena.ppm"))
60     >>> print(im.im) # internal image attribute
61     None
62     >>> a = im.load()
63     >>> type(im.im) # doctest: +ELLIPSIS
64     <... '...ImagingCore'>
65 
66     You can apply many different operations on images.  Most
67     operations return a new image:
68 
69     >>> im = Image.open(os.path.join(ROOT, "Images/lena.ppm"))
70     >>> _info(im.convert("L"))
71     (None, 'L', (128, 128))
72     >>> _info(im.copy())
73     (None, 'RGB', (128, 128))
74     >>> _info(im.crop((32, 32, 96, 96)))
75     (None, 'RGB', (64, 64))
76     >>> _info(im.filter(ImageFilter.BLUR))
77     (None, 'RGB', (128, 128))
78     >>> im.getbands()
79     ('R', 'G', 'B')
80     >>> im.getbbox()
81     (0, 0, 128, 128)
82     >>> len(im.getdata())
83     16384
84     >>> im.getextrema()
85     ((61, 255), (26, 234), (44, 223))
86     >>> im.getpixel((0, 0))
87     (223, 162, 133)
88     >>> len(im.getprojection())
89     2
90     >>> len(im.histogram())
91     768
92     >>> _info(im.point(list(range(256))*3))
93     (None, 'RGB', (128, 128))
94     >>> _info(im.resize((64, 64)))
95     (None, 'RGB', (64, 64))
96     >>> _info(im.rotate(45))
97     (None, 'RGB', (128, 128))
98     >>> [_info(ch) for ch in im.split()]
99     [(None, 'L', (128, 128)), (None, 'L', (128, 128)), (None, 'L', (128, 128))]
100     >>> len(im.convert("1").tobitmap())
101     10456
102     >>> len(im.tobytes())
103     49152
104     >>> _info(im.transform((512, 512), Image.AFFINE, (1,0,0,0,1,0)))
105     (None, 'RGB', (512, 512))
106     >>> _info(im.transform((512, 512), Image.EXTENT, (32,32,96,96)))
107     (None, 'RGB', (512, 512))
108 
109     The ImageDraw module lets you draw stuff in raster images:
110 
111     >>> im = Image.new("L", (128, 128), 64)
112     >>> d = ImageDraw.ImageDraw(im)
113     >>> d.line((0, 0, 128, 128), fill=128)
114     >>> d.line((0, 128, 128, 0), fill=128)
115     >>> im.getextrema()
116     (64, 128)
117 
118     In 1.1.4, you can specify colors in a number of ways:
119 
120     >>> xy = 0, 0, 128, 128
121     >>> im = Image.new("RGB", (128, 128), 0)
122     >>> d = ImageDraw.ImageDraw(im)
123     >>> d.rectangle(xy, "#f00")
124     >>> im.getpixel((0, 0))
125     (255, 0, 0)
126     >>> d.rectangle(xy, "#ff0000")
127     >>> im.getpixel((0, 0))
128     (255, 0, 0)
129     >>> d.rectangle(xy, "rgb(255,0,0)")
130     >>> im.getpixel((0, 0))
131     (255, 0, 0)
132     >>> d.rectangle(xy, "rgb(100%,0%,0%)")
133     >>> im.getpixel((0, 0))
134     (255, 0, 0)
135     >>> d.rectangle(xy, "hsl(0, 100%, 50%)")
136     >>> im.getpixel((0, 0))
137     (255, 0, 0)
138     >>> d.rectangle(xy, "red")
139     >>> im.getpixel((0, 0))
140     (255, 0, 0)
141 
142     In 1.1.6, you can use the ImageMath module to do image
143     calculations.
144 
145     >>> im = ImageMath.eval("float(im + 20)", im=im.convert("L"))
146     >>> im.mode, im.size
147     ('F', (128, 128))
148 
149     PIL can do many other things, but I'll leave that for another
150     day.  If you're curious, check the handbook, available from:
151 
152         http://www.pythonware.com
153 
154     Cheers /F
155     """
156 
157 
158 def check_module(feature, module):
159     try:
160         __import__(module)
161     except ImportError:
162         print("***", feature, "support not installed")
163     else:
164         print("---", feature, "support ok")
165 
166 def check_codec(feature, codec):
167     if codec + "_encoder" not in dir(Image.core):
168         print("***", feature, "support not installed")
169     else:
170         print("---", feature, "support ok")
171 
172 
173 if __name__ == "__main__":
174     # check build sanity
175 
176     exit_status = 0
177 
178     print("-"*68)
179     #print("PIL", Image.VERSION, "TEST SUMMARY ")
180     print("PIL (Pillow) TEST SUMMARY ")
181     print("-"*68)
182     print("Python modules loaded from", os.path.dirname(Image.__file__))
183     print("Binary modules loaded from", os.path.dirname(Image.core.__file__))
184     print("-"*68)
185     check_module("PIL CORE", "_imaging")
186     check_module("TKINTER", "_imagingtk")
187     check_codec("JPEG", "jpeg")
188     check_codec("ZLIB (PNG/ZIP)", "zip")
189     check_codec("G4 TIFF", "group4")
190     check_module("FREETYPE2", "_imagingft")
191     check_module("LITTLECMS", "_imagingcms")
192     check_module("WEBP", "_webp")
193     print("-"*68)
194 
195     # use doctest to make sure the test program behaves as documented!
196     import doctest, selftest
197     print("Running selftest:")
198     status = doctest.testmod(selftest)
199     if status[0]:
200         print("*** %s tests of %d failed." % status)
201         exit_status = 1
202     else:
203         print("--- %s tests passed." % status[1])
204 
205     sys.exit(exit_status)
206 
207
```

Path: `PIL/WebPImagePlugin.py`
Content:
```
1 from PIL import Image
2 from PIL import ImageFile
3 from io import BytesIO
4 import _webp
5 
6 def _accept(prefix):
7     return prefix[:4] == b"RIFF" and prefix[8:16] == b"WEBPVP8 "
8 
9 class WebPImageFile(ImageFile.ImageFile):
10 
11     format = "WEBP"
12     format_description = "WebP image"
13 
14     def _open(self):
15         self.mode = "RGB"
16         data, width, height = _webp.WebPDecodeRGB(self.fp.read())
17         self.size = width, height
18         self.fp = BytesIO(data)
19         self.tile = [("raw", (0, 0) + self.size, 0, 'RGB')]
20 
21 def _save(im, fp, filename):
22     if im.mode != "RGB":
23         raise IOError("cannot write mode %s as WEBP" % im.mode)
24     quality = im.encoderinfo.get("quality", 80)
25     
26     data = _webp.WebPEncodeRGB(im.tobytes(), im.size[0], im.size[1], im.size[0] * 3, float(quality))
27     fp.write(data)
28 
29 Image.register_open("WEBP", WebPImageFile, _accept)
30 Image.register_save("WEBP", _save)
31 
32 Image.register_extension("WEBP", ".webp")
33 Image.register_mime("WEBP", "image/webp")
34
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/PIL/WebPImagePlugin.py b/PIL/WebPImagePlugin.py
--- a/PIL/WebPImagePlugin.py
+++ b/PIL/WebPImagePlugin.py
@@ -3,29 +3,55 @@
 from io import BytesIO
 import _webp
 
+
+_VALID_WEBP_MODES = {
+    "RGB": True,
+    "RGBA": True,
+    }
+
+_VP8_MODES_BY_IDENTIFIER = {
+    b"VP8 ": "RGB",
+    b"VP8X": "RGBA",
+    } 
+
+
 def _accept(prefix):
-    return prefix[:4] == b"RIFF" and prefix[8:16] == b"WEBPVP8 "
+    is_riff_file_format = prefix[:4] == b"RIFF"
+    is_webp_file = prefix[8:12] == b"WEBP"
+    is_valid_vp8_mode = prefix[12:16] in _VP8_MODES_BY_IDENTIFIER
+    
+    return is_riff_file_format and is_webp_file and is_valid_vp8_mode
+
 
 class WebPImageFile(ImageFile.ImageFile):
 
     format = "WEBP"
     format_description = "WebP image"
 
-    def _open(self):
-        self.mode = "RGB"
-        data, width, height = _webp.WebPDecodeRGB(self.fp.read())
+    def _open(self):                
+        data, width, height, self.mode = _webp.WebPDecode(self.fp.read())
         self.size = width, height
         self.fp = BytesIO(data)
-        self.tile = [("raw", (0, 0) + self.size, 0, 'RGB')]
+        self.tile = [("raw", (0, 0) + self.size, 0, self.mode)]
+
 
 def _save(im, fp, filename):
-    if im.mode != "RGB":
-        raise IOError("cannot write mode %s as WEBP" % im.mode)
+    image_mode = im.mode
+    if im.mode not in _VALID_WEBP_MODES:
+        raise IOError("cannot write mode %s as WEBP" % image_mode)
+    
     quality = im.encoderinfo.get("quality", 80)
     
-    data = _webp.WebPEncodeRGB(im.tobytes(), im.size[0], im.size[1], im.size[0] * 3, float(quality))
+    data = _webp.WebPEncode(
+        im.tobytes(),
+        im.size[0],
+        im.size[1],
+        float(quality),
+		im.mode
+        )
     fp.write(data)
 
+
 Image.register_open("WEBP", WebPImageFile, _accept)
 Image.register_save("WEBP", _save)
 
diff --git a/selftest.py b/selftest.py
--- a/selftest.py
+++ b/selftest.py
@@ -190,6 +190,14 @@
     check_module("FREETYPE2", "_imagingft")
     check_module("LITTLECMS", "_imagingcms")
     check_module("WEBP", "_webp")
+    try:
+        import _webp
+        if _webp.WebPDecoderBuggyAlpha():
+            print("***", "Transparent WEBP", "support not installed")
+        else:
+            print("---", "Transparent WEBP", "support ok")
+    except Exception:
+        pass
     print("-"*68)
 
     # use doctest to make sure the test program behaves as documented!

{"golden_diff": "diff --git a/PIL/WebPImagePlugin.py b/PIL/WebPImagePlugin.py\n--- a/PIL/WebPImagePlugin.py\n+++ b/PIL/WebPImagePlugin.py\n@@ -3,29 +3,55 @@\n from io import BytesIO\n import _webp\n \n+\n+_VALID_WEBP_MODES = {\n+    \"RGB\": True,\n+    \"RGBA\": True,\n+    }\n+\n+_VP8_MODES_BY_IDENTIFIER = {\n+    b\"VP8 \": \"RGB\",\n+    b\"VP8X\": \"RGBA\",\n+    } \n+\n+\n def _accept(prefix):\n-    return prefix[:4] == b\"RIFF\" and prefix[8:16] == b\"WEBPVP8 \"\n+    is_riff_file_format = prefix[:4] == b\"RIFF\"\n+    is_webp_file = prefix[8:12] == b\"WEBP\"\n+    is_valid_vp8_mode = prefix[12:16] in _VP8_MODES_BY_IDENTIFIER\n+    \n+    return is_riff_file_format and is_webp_file and is_valid_vp8_mode\n+\n \n class WebPImageFile(ImageFile.ImageFile):\n \n     format = \"WEBP\"\n     format_description = \"WebP image\"\n \n-    def _open(self):\n-        self.mode = \"RGB\"\n-        data, width, height = _webp.WebPDecodeRGB(self.fp.read())\n+    def _open(self):                \n+        data, width, height, self.mode = _webp.WebPDecode(self.fp.read())\n         self.size = width, height\n         self.fp = BytesIO(data)\n-        self.tile = [(\"raw\", (0, 0) + self.size, 0, 'RGB')]\n+        self.tile = [(\"raw\", (0, 0) + self.size, 0, self.mode)]\n+\n \n def _save(im, fp, filename):\n-    if im.mode != \"RGB\":\n-        raise IOError(\"cannot write mode %s as WEBP\" % im.mode)\n+    image_mode = im.mode\n+    if im.mode not in _VALID_WEBP_MODES:\n+        raise IOError(\"cannot write mode %s as WEBP\" % image_mode)\n+    \n     quality = im.encoderinfo.get(\"quality\", 80)\n     \n-    data = _webp.WebPEncodeRGB(im.tobytes(), im.size[0], im.size[1], im.size[0] * 3, float(quality))\n+    data = _webp.WebPEncode(\n+        im.tobytes(),\n+        im.size[0],\n+        im.size[1],\n+        float(quality),\n+\t\tim.mode\n+        )\n     fp.write(data)\n \n+\n Image.register_open(\"WEBP\", WebPImageFile, _accept)\n Image.register_save(\"WEBP\", _save)\n \ndiff --git a/selftest.py b/selftest.py\n--- a/selftest.py\n+++ b/selftest.py\n@@ -190,6 +190,14 @@\n     check_module(\"FREETYPE2\", \"_imagingft\")\n     check_module(\"LITTLECMS\", \"_imagingcms\")\n     check_module(\"WEBP\", \"_webp\")\n+    try:\n+        import _webp\n+        if _webp.WebPDecoderBuggyAlpha():\n+            print(\"***\", \"Transparent WEBP\", \"support not installed\")\n+        else:\n+            print(\"---\", \"Transparent WEBP\", \"support ok\")\n+    except Exception:\n+        pass\n     print(\"-\"*68)\n \n     # use doctest to make sure the test program behaves as documented!\n", "issue": "Add support for RGBA webp image encoding and decoding\nWould it be possible to wrap the `WebPEncodeRGBA` and `WebPDecodeRGBA` functionality of the webp library inside Pillow?\n\n", "before_files": [{"content": "# minimal sanity check\nfrom __future__ import print_function\nROOT = \".\"\n\nimport os, sys\nsys.path.insert(0, ROOT)\n\nfrom PIL import Image\nfrom PIL import ImageDraw\nfrom PIL import ImageFilter\nfrom PIL import ImageMath\n\ntry:\n    Image.core.ping\nexcept ImportError as v:\n    print(\"***\", v)\n    sys.exit()\nexcept AttributeError:\n    pass\n\ndef _info(im):\n    im.load()\n    return im.format, im.mode, im.size\n\ndef testimage():\n    \"\"\"\n    PIL lets you create in-memory images with various pixel types:\n\n    >>> im = Image.new(\"1\", (128, 128)) # monochrome\n    >>> _info(im)\n    (None, '1', (128, 128))\n    >>> _info(Image.new(\"L\", (128, 128))) # grayscale (luminance)\n    (None, 'L', (128, 128))\n    >>> _info(Image.new(\"P\", (128, 128))) # palette\n    (None, 'P', (128, 128))\n    >>> _info(Image.new(\"RGB\", (128, 128))) # truecolor\n    (None, 'RGB', (128, 128))\n    >>> _info(Image.new(\"I\", (128, 128))) # 32-bit integer\n    (None, 'I', (128, 128))\n    >>> _info(Image.new(\"F\", (128, 128))) # 32-bit floating point\n    (None, 'F', (128, 128))\n\n    Or open existing files:\n\n    >>> im = Image.open(os.path.join(ROOT, \"Images/lena.gif\"))\n    >>> _info(im)\n    ('GIF', 'P', (128, 128))\n    >>> _info(Image.open(os.path.join(ROOT, \"Images/lena.ppm\")))\n    ('PPM', 'RGB', (128, 128))\n    >>> try:\n    ...  _info(Image.open(os.path.join(ROOT, \"Images/lena.jpg\")))\n    ... except IOError as v:\n    ...  print(v)\n    ('JPEG', 'RGB', (128, 128))\n\n    PIL doesn't actually load the image data until it's needed,\n    or you call the \"load\" method:\n\n    >>> im = Image.open(os.path.join(ROOT, \"Images/lena.ppm\"))\n    >>> print(im.im) # internal image attribute\n    None\n    >>> a = im.load()\n    >>> type(im.im) # doctest: +ELLIPSIS\n    <... '...ImagingCore'>\n\n    You can apply many different operations on images.  Most\n    operations return a new image:\n\n    >>> im = Image.open(os.path.join(ROOT, \"Images/lena.ppm\"))\n    >>> _info(im.convert(\"L\"))\n    (None, 'L', (128, 128))\n    >>> _info(im.copy())\n    (None, 'RGB', (128, 128))\n    >>> _info(im.crop((32, 32, 96, 96)))\n    (None, 'RGB', (64, 64))\n    >>> _info(im.filter(ImageFilter.BLUR))\n    (None, 'RGB', (128, 128))\n    >>> im.getbands()\n    ('R', 'G', 'B')\n    >>> im.getbbox()\n    (0, 0, 128, 128)\n    >>> len(im.getdata())\n    16384\n    >>> im.getextrema()\n    ((61, 255), (26, 234), (44, 223))\n    >>> im.getpixel((0, 0))\n    (223, 162, 133)\n    >>> len(im.getprojection())\n    2\n    >>> len(im.histogram())\n    768\n    >>> _info(im.point(list(range(256))*3))\n    (None, 'RGB', (128, 128))\n    >>> _info(im.resize((64, 64)))\n    (None, 'RGB', (64, 64))\n    >>> _info(im.rotate(45))\n    (None, 'RGB', (128, 128))\n    >>> [_info(ch) for ch in im.split()]\n    [(None, 'L', (128, 128)), (None, 'L', (128, 128)), (None, 'L', (128, 128))]\n    >>> len(im.convert(\"1\").tobitmap())\n    10456\n    >>> len(im.tobytes())\n    49152\n    >>> _info(im.transform((512, 512), Image.AFFINE, (1,0,0,0,1,0)))\n    (None, 'RGB', (512, 512))\n    >>> _info(im.transform((512, 512), Image.EXTENT, (32,32,96,96)))\n    (None, 'RGB', (512, 512))\n\n    The ImageDraw module lets you draw stuff in raster images:\n\n    >>> im = Image.new(\"L\", (128, 128), 64)\n    >>> d = ImageDraw.ImageDraw(im)\n    >>> d.line((0, 0, 128, 128), fill=128)\n    >>> d.line((0, 128, 128, 0), fill=128)\n    >>> im.getextrema()\n    (64, 128)\n\n    In 1.1.4, you can specify colors in a number of ways:\n\n    >>> xy = 0, 0, 128, 128\n    >>> im = Image.new(\"RGB\", (128, 128), 0)\n    >>> d = ImageDraw.ImageDraw(im)\n    >>> d.rectangle(xy, \"#f00\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n    >>> d.rectangle(xy, \"#ff0000\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n    >>> d.rectangle(xy, \"rgb(255,0,0)\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n    >>> d.rectangle(xy, \"rgb(100%,0%,0%)\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n    >>> d.rectangle(xy, \"hsl(0, 100%, 50%)\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n    >>> d.rectangle(xy, \"red\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n\n    In 1.1.6, you can use the ImageMath module to do image\n    calculations.\n\n    >>> im = ImageMath.eval(\"float(im + 20)\", im=im.convert(\"L\"))\n    >>> im.mode, im.size\n    ('F', (128, 128))\n\n    PIL can do many other things, but I'll leave that for another\n    day.  If you're curious, check the handbook, available from:\n\n        http://www.pythonware.com\n\n    Cheers /F\n    \"\"\"\n\n\ndef check_module(feature, module):\n    try:\n        __import__(module)\n    except ImportError:\n        print(\"***\", feature, \"support not installed\")\n    else:\n        print(\"---\", feature, \"support ok\")\n\ndef check_codec(feature, codec):\n    if codec + \"_encoder\" not in dir(Image.core):\n        print(\"***\", feature, \"support not installed\")\n    else:\n        print(\"---\", feature, \"support ok\")\n\n\nif __name__ == \"__main__\":\n    # check build sanity\n\n    exit_status = 0\n\n    print(\"-\"*68)\n    #print(\"PIL\", Image.VERSION, \"TEST SUMMARY \")\n    print(\"PIL (Pillow) TEST SUMMARY \")\n    print(\"-\"*68)\n    print(\"Python modules loaded from\", os.path.dirname(Image.__file__))\n    print(\"Binary modules loaded from\", os.path.dirname(Image.core.__file__))\n    print(\"-\"*68)\n    check_module(\"PIL CORE\", \"_imaging\")\n    check_module(\"TKINTER\", \"_imagingtk\")\n    check_codec(\"JPEG\", \"jpeg\")\n    check_codec(\"ZLIB (PNG/ZIP)\", \"zip\")\n    check_codec(\"G4 TIFF\", \"group4\")\n    check_module(\"FREETYPE2\", \"_imagingft\")\n    check_module(\"LITTLECMS\", \"_imagingcms\")\n    check_module(\"WEBP\", \"_webp\")\n    print(\"-\"*68)\n\n    # use doctest to make sure the test program behaves as documented!\n    import doctest, selftest\n    print(\"Running selftest:\")\n    status = doctest.testmod(selftest)\n    if status[0]:\n        print(\"*** %s tests of %d failed.\" % status)\n        exit_status = 1\n    else:\n        print(\"--- %s tests passed.\" % status[1])\n\n    sys.exit(exit_status)\n\n", "path": "selftest.py"}, {"content": "from PIL import Image\nfrom PIL import ImageFile\nfrom io import BytesIO\nimport _webp\n\ndef _accept(prefix):\n    return prefix[:4] == b\"RIFF\" and prefix[8:16] == b\"WEBPVP8 \"\n\nclass WebPImageFile(ImageFile.ImageFile):\n\n    format = \"WEBP\"\n    format_description = \"WebP image\"\n\n    def _open(self):\n        self.mode = \"RGB\"\n        data, width, height = _webp.WebPDecodeRGB(self.fp.read())\n        self.size = width, height\n        self.fp = BytesIO(data)\n        self.tile = [(\"raw\", (0, 0) + self.size, 0, 'RGB')]\n\ndef _save(im, fp, filename):\n    if im.mode != \"RGB\":\n        raise IOError(\"cannot write mode %s as WEBP\" % im.mode)\n    quality = im.encoderinfo.get(\"quality\", 80)\n    \n    data = _webp.WebPEncodeRGB(im.tobytes(), im.size[0], im.size[1], im.size[0] * 3, float(quality))\n    fp.write(data)\n\nImage.register_open(\"WEBP\", WebPImageFile, _accept)\nImage.register_save(\"WEBP\", _save)\n\nImage.register_extension(\"WEBP\", \".webp\")\nImage.register_mime(\"WEBP\", \"image/webp\")\n", "path": "PIL/WebPImagePlugin.py"}], "after_files": [{"content": "# minimal sanity check\nfrom __future__ import print_function\nROOT = \".\"\n\nimport os, sys\nsys.path.insert(0, ROOT)\n\nfrom PIL import Image\nfrom PIL import ImageDraw\nfrom PIL import ImageFilter\nfrom PIL import ImageMath\n\ntry:\n    Image.core.ping\nexcept ImportError as v:\n    print(\"***\", v)\n    sys.exit()\nexcept AttributeError:\n    pass\n\ndef _info(im):\n    im.load()\n    return im.format, im.mode, im.size\n\ndef testimage():\n    \"\"\"\n    PIL lets you create in-memory images with various pixel types:\n\n    >>> im = Image.new(\"1\", (128, 128)) # monochrome\n    >>> _info(im)\n    (None, '1', (128, 128))\n    >>> _info(Image.new(\"L\", (128, 128))) # grayscale (luminance)\n    (None, 'L', (128, 128))\n    >>> _info(Image.new(\"P\", (128, 128))) # palette\n    (None, 'P', (128, 128))\n    >>> _info(Image.new(\"RGB\", (128, 128))) # truecolor\n    (None, 'RGB', (128, 128))\n    >>> _info(Image.new(\"I\", (128, 128))) # 32-bit integer\n    (None, 'I', (128, 128))\n    >>> _info(Image.new(\"F\", (128, 128))) # 32-bit floating point\n    (None, 'F', (128, 128))\n\n    Or open existing files:\n\n    >>> im = Image.open(os.path.join(ROOT, \"Images/lena.gif\"))\n    >>> _info(im)\n    ('GIF', 'P', (128, 128))\n    >>> _info(Image.open(os.path.join(ROOT, \"Images/lena.ppm\")))\n    ('PPM', 'RGB', (128, 128))\n    >>> try:\n    ...  _info(Image.open(os.path.join(ROOT, \"Images/lena.jpg\")))\n    ... except IOError as v:\n    ...  print(v)\n    ('JPEG', 'RGB', (128, 128))\n\n    PIL doesn't actually load the image data until it's needed,\n    or you call the \"load\" method:\n\n    >>> im = Image.open(os.path.join(ROOT, \"Images/lena.ppm\"))\n    >>> print(im.im) # internal image attribute\n    None\n    >>> a = im.load()\n    >>> type(im.im) # doctest: +ELLIPSIS\n    <... '...ImagingCore'>\n\n    You can apply many different operations on images.  Most\n    operations return a new image:\n\n    >>> im = Image.open(os.path.join(ROOT, \"Images/lena.ppm\"))\n    >>> _info(im.convert(\"L\"))\n    (None, 'L', (128, 128))\n    >>> _info(im.copy())\n    (None, 'RGB', (128, 128))\n    >>> _info(im.crop((32, 32, 96, 96)))\n    (None, 'RGB', (64, 64))\n    >>> _info(im.filter(ImageFilter.BLUR))\n    (None, 'RGB', (128, 128))\n    >>> im.getbands()\n    ('R', 'G', 'B')\n    >>> im.getbbox()\n    (0, 0, 128, 128)\n    >>> len(im.getdata())\n    16384\n    >>> im.getextrema()\n    ((61, 255), (26, 234), (44, 223))\n    >>> im.getpixel((0, 0))\n    (223, 162, 133)\n    >>> len(im.getprojection())\n    2\n    >>> len(im.histogram())\n    768\n    >>> _info(im.point(list(range(256))*3))\n    (None, 'RGB', (128, 128))\n    >>> _info(im.resize((64, 64)))\n    (None, 'RGB', (64, 64))\n    >>> _info(im.rotate(45))\n    (None, 'RGB', (128, 128))\n    >>> [_info(ch) for ch in im.split()]\n    [(None, 'L', (128, 128)), (None, 'L', (128, 128)), (None, 'L', (128, 128))]\n    >>> len(im.convert(\"1\").tobitmap())\n    10456\n    >>> len(im.tobytes())\n    49152\n    >>> _info(im.transform((512, 512), Image.AFFINE, (1,0,0,0,1,0)))\n    (None, 'RGB', (512, 512))\n    >>> _info(im.transform((512, 512), Image.EXTENT, (32,32,96,96)))\n    (None, 'RGB', (512, 512))\n\n    The ImageDraw module lets you draw stuff in raster images:\n\n    >>> im = Image.new(\"L\", (128, 128), 64)\n    >>> d = ImageDraw.ImageDraw(im)\n    >>> d.line((0, 0, 128, 128), fill=128)\n    >>> d.line((0, 128, 128, 0), fill=128)\n    >>> im.getextrema()\n    (64, 128)\n\n    In 1.1.4, you can specify colors in a number of ways:\n\n    >>> xy = 0, 0, 128, 128\n    >>> im = Image.new(\"RGB\", (128, 128), 0)\n    >>> d = ImageDraw.ImageDraw(im)\n    >>> d.rectangle(xy, \"#f00\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n    >>> d.rectangle(xy, \"#ff0000\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n    >>> d.rectangle(xy, \"rgb(255,0,0)\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n    >>> d.rectangle(xy, \"rgb(100%,0%,0%)\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n    >>> d.rectangle(xy, \"hsl(0, 100%, 50%)\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n    >>> d.rectangle(xy, \"red\")\n    >>> im.getpixel((0, 0))\n    (255, 0, 0)\n\n    In 1.1.6, you can use the ImageMath module to do image\n    calculations.\n\n    >>> im = ImageMath.eval(\"float(im + 20)\", im=im.convert(\"L\"))\n    >>> im.mode, im.size\n    ('F', (128, 128))\n\n    PIL can do many other things, but I'll leave that for another\n    day.  If you're curious, check the handbook, available from:\n\n        http://www.pythonware.com\n\n    Cheers /F\n    \"\"\"\n\n\ndef check_module(feature, module):\n    try:\n        __import__(module)\n    except ImportError:\n        print(\"***\", feature, \"support not installed\")\n    else:\n        print(\"---\", feature, \"support ok\")\n\ndef check_codec(feature, codec):\n    if codec + \"_encoder\" not in dir(Image.core):\n        print(\"***\", feature, \"support not installed\")\n    else:\n        print(\"---\", feature, \"support ok\")\n\n\nif __name__ == \"__main__\":\n    # check build sanity\n\n    exit_status = 0\n\n    print(\"-\"*68)\n    #print(\"PIL\", Image.VERSION, \"TEST SUMMARY \")\n    print(\"PIL (Pillow) TEST SUMMARY \")\n    print(\"-\"*68)\n    print(\"Python modules loaded from\", os.path.dirname(Image.__file__))\n    print(\"Binary modules loaded from\", os.path.dirname(Image.core.__file__))\n    print(\"-\"*68)\n    check_module(\"PIL CORE\", \"_imaging\")\n    check_module(\"TKINTER\", \"_imagingtk\")\n    check_codec(\"JPEG\", \"jpeg\")\n    check_codec(\"ZLIB (PNG/ZIP)\", \"zip\")\n    check_codec(\"G4 TIFF\", \"group4\")\n    check_module(\"FREETYPE2\", \"_imagingft\")\n    check_module(\"LITTLECMS\", \"_imagingcms\")\n    check_module(\"WEBP\", \"_webp\")\n    try:\n        import _webp\n        if _webp.WebPDecoderBuggyAlpha():\n            print(\"***\", \"Transparent WEBP\", \"support not installed\")\n        else:\n            print(\"---\", \"Transparent WEBP\", \"support ok\")\n    except Exception:\n        pass\n    print(\"-\"*68)\n\n    # use doctest to make sure the test program behaves as documented!\n    import doctest, selftest\n    print(\"Running selftest:\")\n    status = doctest.testmod(selftest)\n    if status[0]:\n        print(\"*** %s tests of %d failed.\" % status)\n        exit_status = 1\n    else:\n        print(\"--- %s tests passed.\" % status[1])\n\n    sys.exit(exit_status)\n\n", "path": "selftest.py"}, {"content": "from PIL import Image\nfrom PIL import ImageFile\nfrom io import BytesIO\nimport _webp\n\n\n_VALID_WEBP_MODES = {\n    \"RGB\": True,\n    \"RGBA\": True,\n    }\n\n_VP8_MODES_BY_IDENTIFIER = {\n    b\"VP8 \": \"RGB\",\n    b\"VP8X\": \"RGBA\",\n    } \n\n\ndef _accept(prefix):\n    is_riff_file_format = prefix[:4] == b\"RIFF\"\n    is_webp_file = prefix[8:12] == b\"WEBP\"\n    is_valid_vp8_mode = prefix[12:16] in _VP8_MODES_BY_IDENTIFIER\n    \n    return is_riff_file_format and is_webp_file and is_valid_vp8_mode\n\n\nclass WebPImageFile(ImageFile.ImageFile):\n\n    format = \"WEBP\"\n    format_description = \"WebP image\"\n\n    def _open(self):                \n        data, width, height, self.mode = _webp.WebPDecode(self.fp.read())\n        self.size = width, height\n        self.fp = BytesIO(data)\n        self.tile = [(\"raw\", (0, 0) + self.size, 0, self.mode)]\n\n\ndef _save(im, fp, filename):\n    image_mode = im.mode\n    if im.mode not in _VALID_WEBP_MODES:\n        raise IOError(\"cannot write mode %s as WEBP\" % image_mode)\n    \n    quality = im.encoderinfo.get(\"quality\", 80)\n    \n    data = _webp.WebPEncode(\n        im.tobytes(),\n        im.size[0],\n        im.size[1],\n        float(quality),\n\t\tim.mode\n        )\n    fp.write(data)\n\n\nImage.register_open(\"WEBP\", WebPImageFile, _accept)\nImage.register_save(\"WEBP\", _save)\n\nImage.register_extension(\"WEBP\", \".webp\")\nImage.register_mime(\"WEBP\", \"image/webp\")\n", "path": "PIL/WebPImagePlugin.py"}]}