简体   繁体   中英

PIL/Image "TypeError: argument 5 must be str, not PosixPath" when trying to append frames to an image object

I'm trying to open a source image, read its frames and append these to a new image object. It works to a point, then I receive a TypeError . The "source images" are an existing TIFF, then a set of documents I've validated and converted to TIFF.

from PIL import Image, ImageSequence, TiffImagePlugin

def insert_into_tiff(image_source_path, passed_images, delete_file=False, delete_converted=True):

  # create a temporary image to hold all ensuing frames
  temp_image_path = TEMP_IMG / 'temp_{}'.format( Path(image_source_path).name )

  with TiffImagePlugin.AppendingTiffWriter(temp_image_path, True) as image_to_be_appended:

    # append frames from the original image
    append_tiff_sequences(image_source_path, image_to_be_appended)

    # append frames from each of the validated files / "passed_images"
    for p in passed_images:
      source_path = TEMP_IMG / p['new_name'] # the validated file
      append_tiff_sequences(source_path, image_to_be_appended)

def append_tiff_sequences(image_source_path, image_to_be_appended):

  print("append {} frames from {}".format(get_image_sequence_frame_count(image_source_path), image_source_path))

  # open the source file
  with Image.open(image_source_path) as additional_images:
    # iterate over it's frames
    for frame in ImageSequence.Iterator(additional_images):
      frame_copy = frame.copy() # copy the frame
      frame_copy.save(image_to_be_appended) # append to the temporary image
      image_to_be_appended.newFrame()
      frame_copy.close()

def get_image_sequence_frame_count(image_path):
  return Image.open(image_path).n_frames

There are 13 files in /TEMP_IMG :

/TEMP_IMG contents:

[PosixPath('/code/media/temp/RT170822001.tiff'), PosixPath('/code/media/temp/RT170822002.tiff'), PosixPath('/code/media/temp/RT170822003.tiff'), PosixPath('/code/media/temp/RT170822004.tiff'), PosixPath('/code/media/temp/RT170822005.tiff'), PosixPath('/code/media/temp/RT170822006.tiff'), PosixPath('/code/media/temp/RT170822007.tiff'), PosixPath('/code/media/temp/RT170822008.tiff'), PosixPath('/code/media/temp/RT170822009.tiff'), PosixPath('/code/media/temp/RT170822010.tiff'), PosixPath('/code/media/temp/RT170822011.tiff'), PosixPath('/code/media/temp/RT170822012.tiff'), PosixPath('/code/media/temp/RT170822013.tiff')]

The process is fine until it reaches file 12

append 1 frames from /code/media/unmarked/RT170822001.tiff
append 1 frames from /code/media/temp/RT170822001.tiff
append 2 frames from /code/media/temp/RT170822002.tiff
append 2 frames from /code/media/temp/RT170822003.tiff
append 1 frames from /code/media/temp/RT170822004.tiff
append 1 frames from /code/media/temp/RT170822005.tiff
append 1 frames from /code/media/temp/RT170822006.tiff
append 1 frames from /code/media/temp/RT170822007.tiff
append 2 frames from /code/media/temp/RT170822008.tiff
append 1 frames from /code/media/temp/RT170822009.tiff
append 1 frames from /code/media/temp/RT170822010.tiff
append 1 frames from /code/media/temp/RT170822011.tiff
append 1 frames from /code/media/temp/RT170822012.tiff

Where it fails with the following:

ERROR: test_scan_add_allows_valid_docs_and_screenshots_to_be_added_to_image (main_app.tests.test_EndToEnd.ImagesAvailableTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/code/main_app/tests/test_EndToEnd.py", line 355, in test_scan_add_allows_valid_docs_and_screenshots_to_be_added_to_image
 response = self.client.post( request_url, data)
File "/usr/local/lib/python3.10/site-packages/django/test/client.py", line 751, in post
 response = super().post(path, data=data, content_type=content_type, secure=secure, **extra)
File "/usr/local/lib/python3.10/site-packages/django/test/client.py", line 407, in post
 return self.generic('POST', path, post_data, content_type,
File "/usr/local/lib/python3.10/site-packages/django/test/client.py", line 473, in generic
 return self.request(**r)
File "/usr/local/lib/python3.10/site-packages/django/test/client.py", line 719, in request
 self.check_exception(response)
File "/usr/local/lib/python3.10/site-packages/django/test/client.py", line 580, in check_exception
 raise exc_value
File "/usr/local/lib/python3.10/site-packages/django/core/handlers/exception.py", line 47, in inner
 response = get_response(request)
File "/usr/local/lib/python3.10/site-packages/django/core/handlers/base.py", line 181, in _get_response
 response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.10/site-packages/django/views/generic/base.py", line 70, in view
 return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.10/site-packages/django/views/generic/base.py", line 98, in dispatch
 return handler(request, *args, **kwargs)
File "/code/main_app/views.py", line 187, in post
 processed_images = handle_additional_images(request.user, pk, documents, base64_image)
File "/code/main_app/helpers/processing.py", line 83, in handle_additional_images
 insert_into_tiff( existing_image_path, processed_images['passed'] )
File "/code/main_app/helpers/image_manipulation.py", line 118, in insert_into_tiff
 append_tiff_sequences(source_path, image_to_be_appended)
File "/code/main_app/helpers/image_manipulation.py", line 129, in append_tiff_sequences
 frame_copy.save(image_to_be_appended) # append to the temporary image
File "/usr/local/lib/python3.10/site-packages/PIL/Image.py", line 2300, in save
 save_handler(self, fp, filename)
File "/usr/local/lib/python3.10/site-packages/PIL/TiffImagePlugin.py", line 1810, in _save
 e = Image._getencoder(im.mode, "libtiff", a, encoderconfig)
File "/usr/local/lib/python3.10/site-packages/PIL/Image.py", line 458, in _getencoder
 return encoder(mode, *args + extra)
TypeError: argument 5 must be str, not PosixPath

If I use TiffImagePlugin.AppendingTiffWriter and append to the existing image / image_source_path (ie no temporary / intermediary image), it works fine but overwrites the existing image's first frame (I expect 17 frames, it completes with 16 and I can see the first frame is no longer there).

I have also used str(<path>) but that doesn't solve the issue either. I've not been able to figure out what argument 5 for the encoder is because in the source the encoder_name isn't clear in the source.

A senior dev solved it. The issue was this line:

temp_image_path = TEMP_IMG / 'temp_{}'.format( Path(image_source_path).name )

Using os.path.join instead solved the issue:

temp_image_path = os.path.join(TEMP_IMG, 'temp_{}'.format( Path(image_source_path).name ))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM