Repository: python-pillow/Pillow

Issue:
Webp images cannot be pickled
### What did you do?

I'm trying to pickle and unpickle webp images. My code works for other image formats, but fails for webp images. For example, run the following code with [this image](https://github.com/python-pillow/Pillow/files/4485578/image.zip) (compressed because GitHub doesn't support webp files):

```python
from PIL import Image
import pickle

image = Image.open('image.webp')
unpickled_image = pickle.loads(pickle.dumps(image))
resized_image = unpickled_image.resize((50, 50))
```

### What did you expect to happen?

A resized `Image` instance should have been created.

### What actually happened?

The following error was thrown:

```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/seppe/.local/lib/python3.7/site-packages/PIL/Image.py", line 1886, in resize
    self.load()
  File "/home/seppe/.local/lib/python3.7/site-packages/PIL/WebPImagePlugin.py", line 156, in load
    if self.__loaded != self.__logical_frame:
AttributeError: 'WebPImageFile' object has no attribute '_WebPImageFile__loaded'
```

### What are your OS, Python and Pillow versions?

* OS: Ubuntu 19.10
* Python: 3.7.5
* Pillow: 7.1.1


Discussion:

Resolving patch:
diff --git a/src/PIL/WebPImagePlugin.py b/src/PIL/WebPImagePlugin.py
--- a/src/PIL/WebPImagePlugin.py
+++ b/src/PIL/WebPImagePlugin.py
@@ -38,6 +38,8 @@ class WebPImageFile(ImageFile.ImageFile):
 
     format = "WEBP"
     format_description = "WebP image"
+    __loaded = 0
+    __logical_frame = 0
 
     def _open(self):
         if not _webp.HAVE_WEBPANIM:


Test patch:
diff --git a/Tests/test_pickle.py b/Tests/test_pickle.py
--- a/Tests/test_pickle.py
+++ b/Tests/test_pickle.py
@@ -1,11 +1,16 @@
 import pickle
 
+import pytest
 from PIL import Image
 
+from .helper import skip_unless_feature
 
-def helper_pickle_file(tmp_path, pickle, protocol=0, mode=None):
+
+def helper_pickle_file(
+    tmp_path, pickle, protocol=0, test_file="Tests/images/hopper.jpg", mode=None
+):
     # Arrange
-    with Image.open("Tests/images/hopper.jpg") as im:
+    with Image.open(test_file) as im:
         filename = str(tmp_path / "temp.pkl")
         if mode:
             im = im.convert(mode)
@@ -35,41 +40,30 @@ def helper_pickle_string(
         assert im == loaded_im
 
 
-def test_pickle_image(tmp_path):
-    # Act / Assert
-    for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1):
-        helper_pickle_string(pickle, protocol)
-        helper_pickle_file(tmp_path, pickle, protocol)
-
-
-def test_pickle_p_mode():
-    # Act / Assert
-    for test_file in [
-        "Tests/images/test-card.png",
-        "Tests/images/zero_bb.png",
-        "Tests/images/zero_bb_scale2.png",
-        "Tests/images/non_zero_bb.png",
-        "Tests/images/non_zero_bb_scale2.png",
-        "Tests/images/p_trns_single.png",
-        "Tests/images/pil123p.png",
-        "Tests/images/itxt_chunks.png",
-    ]:
-        for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1):
-            helper_pickle_string(pickle, protocol=protocol, test_file=test_file)
-
-
-def test_pickle_pa_mode(tmp_path):
-    # Act / Assert
-    for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1):
-        helper_pickle_string(pickle, protocol, mode="PA")
-        helper_pickle_file(tmp_path, pickle, protocol, mode="PA")
-
-
-def test_pickle_l_mode(tmp_path):
+@pytest.mark.parametrize(
+    ("test_file", "test_mode"),
+    [
+        ("Tests/images/hopper.jpg", None),
+        ("Tests/images/hopper.jpg", "L"),
+        ("Tests/images/hopper.jpg", "PA"),
+        pytest.param(
+            "Tests/images/hopper.webp", None, marks=skip_unless_feature("webp")
+        ),
+        ("Tests/images/test-card.png", None),
+        ("Tests/images/zero_bb.png", None),
+        ("Tests/images/zero_bb_scale2.png", None),
+        ("Tests/images/non_zero_bb.png", None),
+        ("Tests/images/non_zero_bb_scale2.png", None),
+        ("Tests/images/p_trns_single.png", None),
+        ("Tests/images/pil123p.png", None),
+        ("Tests/images/itxt_chunks.png", None),
+    ],
+)
+def test_pickle_image(tmp_path, test_file, test_mode):
     # Act / Assert
     for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1):
-        helper_pickle_string(pickle, protocol, mode="L")
-        helper_pickle_file(tmp_path, pickle, protocol, mode="L")
+        helper_pickle_string(pickle, protocol, test_file, test_mode)
+        helper_pickle_file(tmp_path, pickle, protocol, test_file, test_mode)
 
 
 def test_pickle_la_mode_with_palette(tmp_path):
@@ -88,3 +82,15 @@ def test_pickle_la_mode_with_palette(tmp_path):
 
         im.mode = "PA"
         assert im == loaded_im
+
+
+@skip_unless_feature("webp")
+def test_pickle_tell():
+    # Arrange
+    image = Image.open("Tests/images/hopper.webp")
+
+    # Act: roundtrip
+    unpickled_image = pickle.loads(pickle.dumps(image))
+
+    # Assert
+    assert unpickled_image.tell() == 0