ImageConverter now uses generic context; #562

This commit is contained in:
Rhet Turnbull
2021-12-31 17:34:41 -08:00
parent cbe79ee98c
commit a3b2784f31
4 changed files with 20 additions and 47 deletions

View File

@@ -1,3 +1,3 @@
""" version info """ """ version info """
__version__ = "0.44.2" __version__ = "0.44.3"

View File

@@ -17,25 +17,25 @@ from wurlitzer import pipes
class ImageConversionError(Exception): class ImageConversionError(Exception):
"""Base class for exceptions in this module. """ """Base class for exceptions in this module."""
pass pass
class ImageConverter: class ImageConverter:
""" Convert images to jpeg. This class is a singleton """Convert images to jpeg. This class is a singleton
which will re-use the Core Image CIContext to avoid which will re-use the Core Image CIContext to avoid
creating a new context for every conversion. """ creating a new context for every conversion."""
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
""" create new object or return instance of already created singleton """ """create new object or return instance of already created singleton"""
if not hasattr(cls, "instance") or not cls.instance: if not hasattr(cls, "instance") or not cls.instance:
cls.instance = super().__new__(cls) cls.instance = super().__new__(cls)
return cls.instance return cls.instance
def __init__(self): def __init__(self):
""" return existing singleton or create a new one """ """return existing singleton or create a new one"""
if hasattr(self, "context"): if hasattr(self, "context"):
return return
@@ -47,13 +47,10 @@ class ImageConverter:
"workingFormat": Quartz.kCIFormatRGBAh, "workingFormat": Quartz.kCIFormatRGBAh,
} }
) )
mtldevice = Metal.MTLCreateSystemDefaultDevice() self.context = Quartz.CIContext.contextWithOptions_(context_options)
self.context = Quartz.CIContext.contextWithMTLDevice_options_(
mtldevice, context_options
)
def write_jpeg(self, input_path, output_path, compression_quality=1.0): def write_jpeg(self, input_path, output_path, compression_quality=1.0):
""" convert image to jpeg and write image to output_path """convert image to jpeg and write image to output_path
Args: Args:
input_path: path to input image (e.g. '/path/to/import/file.CR2') as str or pathlib.Path input_path: path to input image (e.g. '/path/to/import/file.CR2') as str or pathlib.Path
@@ -104,8 +101,11 @@ class ImageConverter:
if input_image is None: if input_image is None:
raise ImageConversionError(f"Could not create CIImage for {input_path}") raise ImageConversionError(f"Could not create CIImage for {input_path}")
output_colorspace = input_image.colorSpace() or Quartz.CGColorSpaceCreateWithName( output_colorspace = (
Quartz.CoreGraphics.kCGColorSpaceSRGB input_image.colorSpace()
or Quartz.CGColorSpaceCreateWithName(
Quartz.CoreGraphics.kCGColorSpaceSRGB
)
) )
output_options = NSDictionary.dictionaryWithDictionary_( output_options = NSDictionary.dictionaryWithDictionary_(
@@ -123,4 +123,3 @@ class ImageConverter:
raise ImageConversionError( raise ImageConversionError(
f"Error converting file {input_path} to jpeg at {output_path}: {error}" f"Error converting file {input_path} to jpeg at {output_path}: {error}"
) )

View File

@@ -2393,10 +2393,6 @@ def test_export_original_suffix_template():
assert sorted(files) == sorted(CLI_EXPORT_FILENAMES_ORIGINAL_SUFFIX_TEMPLATE) assert sorted(files) == sorted(CLI_EXPORT_FILENAMES_ORIGINAL_SUFFIX_TEMPLATE)
@pytest.mark.skipif(
"OSXPHOTOS_TEST_CONVERT" not in os.environ,
reason="Skip if running in Github actions, no GPU.",
)
def test_export_convert_to_jpeg(): def test_export_convert_to_jpeg():
"""test --convert-to-jpeg""" """test --convert-to-jpeg"""
import glob import glob
@@ -2420,10 +2416,6 @@ def test_export_convert_to_jpeg():
assert large_file.stat().st_size > 7000000 assert large_file.stat().st_size > 7000000
@pytest.mark.skipif(
"OSXPHOTOS_TEST_CONVERT" not in os.environ,
reason="Skip if running in Github actions, no GPU.",
)
def test_export_convert_to_jpeg_quality(): def test_export_convert_to_jpeg_quality():
"""test --convert-to-jpeg --jpeg-quality""" """test --convert-to-jpeg --jpeg-quality"""
import glob import glob
@@ -2455,10 +2447,6 @@ def test_export_convert_to_jpeg_quality():
assert large_file.stat().st_size < 1000000 assert large_file.stat().st_size < 1000000
@pytest.mark.skipif(
"OSXPHOTOS_TEST_CONVERT" not in os.environ,
reason="Skip if running in Github actions, no GPU.",
)
def test_export_convert_to_jpeg_skip_raw(): def test_export_convert_to_jpeg_skip_raw():
"""test --convert-to-jpeg""" """test --convert-to-jpeg"""
import glob import glob
@@ -6678,10 +6666,6 @@ def test_export_jpeg_ext_edited_movie():
assert f"{filename}_edited.{ext}".lower() in files assert f"{filename}_edited.{ext}".lower() in files
@pytest.mark.skipif(
"OSXPHOTOS_TEST_CONVERT" not in os.environ,
reason="Skip if running in Github actions, no GPU.",
)
def test_export_jpeg_ext_convert_to_jpeg(): def test_export_jpeg_ext_convert_to_jpeg():
"""test --jpeg-ext with --convert-to-jpeg""" """test --jpeg-ext with --convert-to-jpeg"""
import glob import glob
@@ -6713,10 +6697,6 @@ def test_export_jpeg_ext_convert_to_jpeg():
assert f"{filename}.jpg" in files assert f"{filename}.jpg" in files
@pytest.mark.skipif(
"OSXPHOTOS_TEST_CONVERT" not in os.environ,
reason="Skip if running in Github actions, no GPU.",
)
def test_export_jpeg_ext_convert_to_jpeg_movie(): def test_export_jpeg_ext_convert_to_jpeg_movie():
"""test --jpeg-ext with --convert-to-jpeg and a movie, shouldn't convert or change extensions, #366""" """test --jpeg-ext with --convert-to-jpeg and a movie, shouldn't convert or change extensions, #366"""
import glob import glob

View File

@@ -4,11 +4,6 @@ import os
import pytest import pytest
skip_test = "OSXPHOTOS_TEST_CONVERT" not in os.environ
pytestmark = pytest.mark.skipif(
skip_test, reason="Skip if running on GitHub actions, no GPU."
)
TEST_HEIC = "tests/test-images/IMG_3092.heic" TEST_HEIC = "tests/test-images/IMG_3092.heic"
TEST_RAW = "tests/test-images/IMG_0476_2.CR2" TEST_RAW = "tests/test-images/IMG_0476_2.CR2"
@@ -19,7 +14,7 @@ TEST_IMAGE_DOES_NOT_EXIST = "tests/test-images/NOT-A-FILE.heic"
def test_image_converter_singleton(): def test_image_converter_singleton():
""" test that ImageConverter is a singleton """ """test that ImageConverter is a singleton"""
from osxphotos.imageconverter import ImageConverter from osxphotos.imageconverter import ImageConverter
convert1 = ImageConverter() convert1 = ImageConverter()
@@ -29,7 +24,7 @@ def test_image_converter_singleton():
def test_image_converter(): def test_image_converter():
""" test conversion of different image types """ """test conversion of different image types"""
import pathlib import pathlib
import tempfile import tempfile
from osxphotos.imageconverter import ImageConverter from osxphotos.imageconverter import ImageConverter
@@ -50,7 +45,7 @@ def test_image_converter():
def test_image_converter_compression_quality(): def test_image_converter_compression_quality():
""" test conversion of different image types with custom compression quality """ """test conversion of different image types with custom compression quality"""
import pathlib import pathlib
import tempfile import tempfile
from osxphotos.imageconverter import ImageConverter from osxphotos.imageconverter import ImageConverter
@@ -69,7 +64,7 @@ def test_image_converter_compression_quality():
def test_image_converter_bad_compression_quality(): def test_image_converter_bad_compression_quality():
""" test illegal compression quality """ """test illegal compression quality"""
import pathlib import pathlib
import tempfile import tempfile
from osxphotos.imageconverter import ImageConverter from osxphotos.imageconverter import ImageConverter
@@ -86,7 +81,7 @@ def test_image_converter_bad_compression_quality():
def test_image_converter_bad_file(): def test_image_converter_bad_file():
""" Try to convert a file that's not an image """ """Try to convert a file that's not an image"""
import pathlib import pathlib
import tempfile import tempfile
from osxphotos.imageconverter import ImageConverter, ImageConversionError from osxphotos.imageconverter import ImageConverter, ImageConversionError
@@ -101,7 +96,7 @@ def test_image_converter_bad_file():
def test_image_converter_missing_file(): def test_image_converter_missing_file():
""" Try to convert a file that's not an image """ """Try to convert a file that's not an image"""
import pathlib import pathlib
import tempfile import tempfile
from osxphotos.imageconverter import ImageConverter from osxphotos.imageconverter import ImageConverter
@@ -113,4 +108,3 @@ def test_image_converter_missing_file():
outfile = pathlib.Path(tempdir.name) / f"{imgfile.stem}.jpeg" outfile = pathlib.Path(tempdir.name) / f"{imgfile.stem}.jpeg"
with pytest.raises(FileNotFoundError): with pytest.raises(FileNotFoundError):
converter.write_jpeg(imgfile, outfile) converter.write_jpeg(imgfile, outfile)