import ctypes import sys from PIL import Image as PILImage from gamera.core import load_image as _load_image from gamera.core import init_gamera as _init from gamera.core import Image, RGB from gamera.plugins.pil_io import from_pil as _from_pil def gamera_init(): sys.modules['numpy'] = None result = _init() test_image = Image((0, 0), (5, 5), RGB) test_string = test_image._to_raw_string() try: sys.getrefcount except AttributeError: return result refcount = sys.getrefcount(test_string) if refcount >= 3: # no coverage # See: https://groups.yahoo.com/neo/groups/gamera-devel/conversations/topics/2068 raise RuntimeError('Memory leak in Gamera') else: assert refcount == 2 try: PILImage.fromstring = PILImage.frombytes # Gamera still uses fromstring(), which was deprecated, # and finally removed in Pillow 3.0.0. # https://pillow.readthedocs.io/en/3.0.x/releasenotes/3.0.0.html#deprecated-methods except AttributeError: pass return result def load_image(filename): pil_image = PILImage.open(filename) [xdpi, ydpi] = pil_image.info.get('dpi', (0, 0)) if xdpi <= 1 or ydpi <= 1: # not reliable dpi = None else: dpi = int(round( math.hypot(xdpi, ydpi) / math.hypot(1, 1) )) try: if pil_image.format == 'TIFF': # Gamera handles only a few TIFF color modes correctly. # https://bugs.debian.org/784374 gamera_modes = ['1', 'I;16', 'L', 'RGB'] elif pil_image.format == 'PNG': # Gamera doesn't handle 16-bit greyscale PNG images correctly. # https://groups.yahoo.com/neo/groups/gamera-devel/conversations/messages/2425 gamera_modes = ['1', 'L', 'RGB'] else: gamera_modes = [] if pil_image.mode not in gamera_modes: raise IOError # Gamera supports more TIFF compression formats that PIL. # https://mail.python.org/pipermail/image-sig/2003-July/002354.html image = _load_image(filename) except IOError: # Gamera supports importing only 8-bit and RGB from PIL: if pil_image.mode[:2] in {'1', '1;', 'I', 'I;', 'L;'}: pil_image = pil_image.convert('L') elif pil_image.mode not in {'RGB', 'L'}: pil_image = pil_image.convert('RGB') assert pil_image.mode in {'RGB', 'L'} try: # Gamera still uses tostring(), which was deprecated, # and finally removed in Pillow 3.0.0. # https://pillow.readthedocs.io/en/3.0.x/releasenotes/3.0.0.html#deprecated-methods pil_image.tostring = pil_image.tobytes except AttributeError: # no coverage pass image = _from_pil(pil_image) image.dpi = dpi return image def to_pil_rgb(image): # About 20% faster than the standard .to_pil() method of Gamera 3.2.6. buffer = ctypes.create_string_buffer(3 * image.ncols * image.nrows) image.to_buffer(buffer) return PILImage.frombuffer('RGB', (image.ncols, image.nrows), buffer, 'raw', 'RGB', 0, 1) path = 'didjvu/tests/data/ycbcr-jpeg.tiff' in_image = PILImage.open(path) if in_image.mode != 'RGB': in_image = in_image.convert('RGB') assert in_image.mode == 'RGB' gamera_init() gamera_image = load_image(path) out_image = to_pil_rgb(gamera_image) in_image.save('in.jpg') out_image.save('out.jpg')