Repository: python-pillow/Pillow

Issue:
Manipulating .cr2 file crashes Python process (signal 11)
### What did you do?
I was trying to open and save .cr2 image in another format.

### What did you expect to happen?
I expected the file to be saved OR at least raise some kind of exception why it couldn't be done. Anything I could work with

### What actually happened?
Python process crashed with the following message:

`Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)`

### What are your OS, Python and Pillow versions?

* OS: macOS Mojave
* Python: 3.6.6
* Pillow: 6.0.0

```python
from PIL import Image

img = Image.open("file_1.cr2")
del img.tag_v2[700]

img.save("new_file.tif")
```

In Pillow 5.4.1 this file wasn't identified by Pillow as image and so the code just skipped this part. But in 6.0.0 Pillow does identify it as image but after that things blow up.

[image.CR2.zip](https://github.com/python-pillow/Pillow/files/3063455/image.CR2.zip)



Discussion:
Testing, this became readable with #3489

On my machine, when saving I get -
```python
OJPEGSetupEncode: OJPEG encoding not supported; use new-style JPEG compression instead.
Traceback (most recent call last):
  File "test.py", line 7, in <module>
    im.save("new_file.tif")
  File "PIL/Image.py", line 2007, in save
  File "PIL/TiffImagePlugin.py", line 1564, in _save
OSError: encoder error -2 when writing image file
```
I've tried to dig a little bit deeper and my code never even reaches `TiffImagePlugin._save()`. The most I could debug at the moment was that it crashes during `Image.save()` in here: 
https://github.com/python-pillow/Pillow/blob/ee063af32fb4178138a06691c70c8a9763676f5a/src/PIL/Image.py#L1973

It never comes out of `self._ensure_mutable()`
If you're looking for an immediate workaround, I can offer you this -

```python
from PIL import Image
im = Image.open('image.CR2')
im = im.transform(im.size, Image.AFFINE, [1.0, 0.0, 0.0, 0.0, 1.0, 0.0])
im.save('out.tif')
```
It seems that the process crash is specific to macOS because when running this same code and image on Debian system, everything seems to work the same way that @radarhere has described.

Can't be sure but this might be related to this github issue: #3677 
My current theory is this is related to #4034.
Testing before #4034, I was consistently getting a segfault. Now, I am consistently getting an `OSError`.
For the current form of this issue at least, the problem is that the image compression is 'tiff_jpeg'. Pillow [states this is obsolete](https://github.com/python-pillow/Pillow/blob/4634eafe3c695a014267eefdce830b4a825beed7/src/PIL/TiffImagePlugin.py#L114). It corresponds to [OJPEG](https://gitlab.com/libtiff/libtiff/-/blob/master/libtiff/tiff.h#L170), matching the error that is seen when the code for this issue is run -
> OJPEGSetupEncode: OJPEG encoding not supported; use new-style JPEG compression instead.

That error message comes from libtiff. So I've created PR #4627 to take the suggestion. As a workaround in the meantime, you could fix this specific situation by changing the compression manually.

```python
from PIL import Image

img = Image.open("file_1.cr2")
del img.tag_v2[700]
if img.info["compression"] == "tiff_jpeg":
    img.info["compression"] = "jpeg"

img.save("new_file.tif")
```

Resolving patch:
diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py
--- a/src/PIL/TiffImagePlugin.py
+++ b/src/PIL/TiffImagePlugin.py
@@ -1427,6 +1427,9 @@ def _save(im, fp, filename):
     compression = im.encoderinfo.get("compression", im.info.get("compression"))
     if compression is None:
         compression = "raw"
+    elif compression == "tiff_jpeg":
+        # OJPEG is obsolete, so use new-style JPEG compression instead
+        compression = "jpeg"
 
     libtiff = WRITE_LIBTIFF or compression != "raw"
 


Test patch:
diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py
--- a/Tests/test_file_libtiff.py
+++ b/Tests/test_file_libtiff.py
@@ -448,6 +448,14 @@ def test_compressions(self, tmp_path):
         assert size_compressed > size_jpeg
         assert size_jpeg > size_jpeg_30
 
+    def test_tiff_jpeg_compression(self, tmp_path):
+        im = hopper("RGB")
+        out = str(tmp_path / "temp.tif")
+        im.save(out, compression="tiff_jpeg")
+
+        with Image.open(out) as reloaded:
+            assert reloaded.info["compression"] == "jpeg"
+
     def test_quality(self, tmp_path):
         im = hopper("RGB")
         out = str(tmp_path / "temp.tif")