1
votes

I have created a batch job which opens .TIFF-files in a folder, resizes them, converts them to a .PNG-file and then saves them in a different folder. The batch job runs fine and the pictures get processed correctly, but at some specific picture (which I can open as a normal .TIFF-file), the process stops with the following error log:

    ---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
<ipython-input-3-499452368347> in <module>
     47                 target_size = (target_x, target_y)
     48                 print("Image gets converted from size " + str(img_size) + " to " + str(target_size))
---> 49                 resized_image = image.resize(target_size, Image.BICUBIC)
     50 
     51                 # Save the image as a PNG to the target_dir

C:\EigeneProgramme\Python38-64\lib\site-packages\PIL\Image.py in resize(self, size, resample, box, reducing_gap)
   1897 
   1898         if self.mode in ["LA", "RGBA"]:
-> 1899             im = self.convert(self.mode[:-1] + "a")
   1900             im = im.resize(size, resample, box)
   1901             return im.convert(self.mode)

C:\EigeneProgramme\Python38-64\lib\site-packages\PIL\Image.py in convert(self, mode, matrix, dither, palette, colors)
    891         """
    892 
--> 893         self.load()
    894 
    895         if not mode and self.mode == "P":

C:\EigeneProgramme\Python38-64\lib\site-packages\PIL\TiffImagePlugin.py in load(self)
   1085     def load(self):
   1086         if self.tile and self.use_load_libtiff:
-> 1087             return self._load_libtiff()
   1088         return super().load()
   1089 

C:\EigeneProgramme\Python38-64\lib\site-packages\PIL\TiffImagePlugin.py in _load_libtiff(self)
   1189 
   1190         if err < 0:
-> 1191             raise OSError(err)
   1192 
   1193         return Image.Image.load(self)

OSError: -2

This error seams really not self-explanatory and I don't find a proper solution online. Anyone can help?

This is the full (relevant) code:

 from PIL import Image
import os

# The directory which should be converted
source_dir = './Edge_Bands_Scan_Sorted/'
# The directory to which the converted files should be stored
target_dir = './Edge_Bands_Scan_Sorted_PNGs/'

# Create the target dir, if it does not exist already
if not os.path.exists(target_dir):
    os.makedirs(target_dir)

count = 0
valid = 0
# Iterate through all the files in the source_dir-directory
for subdir, dirs, files in os.walk(source_dir):
    for file in files:
        # Check if file is a TIFF-File:
        #if(file[-5:] == '.tiff' or file[-5:] == '.TIFF' ):
        if file.lower().endswith(".tiff"):
            file_path = os.path.join(subdir, file)
            #Print list of all files
                #print(file_path)
            # Extract edge band pattern name from the filepath
            # Get postion of last backslash and only get the text after this backslash
            last_backslash_position = file_path.rfind("\\")
            after_last_backslash = file_path[last_backslash_position + 1:]
            # Remove file ending
            after_last_backslash_without_ending = after_last_backslash[:-5]
            # Only the text before the first underscore is the REHAU Color Code
            first_underscore_position = after_last_backslash_without_ending.find("_")
            color_code = after_last_backslash_without_ending[:first_underscore_position]

            # open the files to write
            file = open(list_path, 'a')
            error_file = open(error_list_path, 'a')

            # Check if the colorcode is already converted
            if not color_code in converted_color_codes_list:
                try:
                    # Process the image
                    print("Loading image [{}] {}".format(count, file_path))
                    # Use PIl to load the image - there are problems with some images
                    image = Image.open(file_path)
                    # Get the image size
                    img_size = image.size
                    img_x = image.size[0]
                    img_y = image.size[1]

                    # Target width of the image
                    target_x = 1000
                    target_y = int(img_y * target_x / img_x)
                    target_size = (target_x, target_y)
                    print("Image [{}] gets converted from size {} to {} ".format( count, str(img_size), str(target_size)))
                    resized_image = image.resize(target_size, Image.BICUBIC)

                    # Save the image as a PNG to the target_dir
                    new_path = target_dir + color_code + '.png'
                    print("The converted image [{}]  gets saved to path {}".format( count, new_path))
                    resized_image.save(new_path, "PNG", optimize=True, compress_level=6)
                    
                    # If successful, add the color code to the list
                    # First add a new line
                    if existing_list:
                        file.write("\n")
                    # Then add the color code
                    file.write(color_code)
                    existing_list = True
                    valid += 1
                except OSError:
                    print("ERROR: Image [{}] at path {} could not be processed".format (count, file_path))
                    # If there occurs an error while processing, save the image name and path to the file
                    if existing_error_list:
                        error_file.write("\n")
                    # Then add the color code
                    error_file.write(color_code + " - " + file_path)
                    existing_error_list = True
            else:
                #Handle duplicate files 
                print("DUPLICATE: Image [{}] at path {} with color code {} is already converted".format(count, file_path, color_code))     

            count += 1
            # Close the file access again
            error_file.close()
            file.close()

        else:
            #Ignore other filetypes
            break
print("{}/{} were successfully converted".format(valid, count))

The folder contains around 2100 .tiff-images in a nested subdirectory system. 149 of them get not processed correctly, but the other one get processed fine. I do not see any difference between the pictures which get processed correctly and the ones who lead to an error.

This is an example path of a picture which gets processed correctly: ./Edge_Bands_Scan_Sorted/Wooden\TIFF\W_E_B_NG\1475B_W_E_B_NG.TIFF

This is an example path of a picture which gets not processed correctly: ./Edge_Bands_Scan_Sorted/Wooden\TIFF\W_E_B_NG\3200B_W_E_B_NG.TIFF

1
OSError 2 means the filename does not exist.John Gordon
Not sure if you realise but you don't need any Python for that. You can do it in Terminal with ImageMagick like this magick mogrify -resize 1024x768 -path OUTPUTDIRECTORY -format PNG *.TIFFMark Setchell
Thank you for your answers. The files exist because I create a list of files using python and then I loop through the files for subdir, dirs, files in os.walk(source_dir): for file in files: # Check if file is a TIFF-File: #if(file[-5:] == '.tiff' or file[-5:] == '.TIFF' ): if file.lower().endswith(".tiff"): file_path = os.path.join(subdir, file) ... image = Image.open(file_path) ... resized_image = image.resize(target_size, Image.BICUBIC) For some reason, the image can be loaded and the error occurs when I try to resize the imageMartin1997
Please show your code then, along with a long listing of the files you are processing.Mark Setchell
@MarkSetchell thank you I edited the question and added the codeMartin1997

1 Answers

2
votes

I am not altogether sure what's going on here. I think, but am by no means sure, the problem is that the file has 4 samples per pixel (i.e. RGBA) but the "Sample Format" tag only gives the type (i.e. unsigned integer) for 3 of the 4 samples and that is upsetting the library.

Here is tiffdump output with the contradictory fields highlighted:

tiffdump 3200B_W_E_B_NG.TIFF 
3200B_W_E_B_NG.TIFF:
Magic: 0x4949 <little-endian> Version: 0x2a <ClassicTIFF>
Directory 0: offset 9441002 (0x900eea) next 0 (0)
SubFileType (254) LONG (4) 1<0>
ImageWidth (256) LONG (4) 1<5477>
ImageLength (257) LONG (4) 1<1248>
BitsPerSample (258) SHORT (3) 4<8 8 8 8>
Compression (259) SHORT (3) 1<5>
Photometric (262) SHORT (3) 1<2>
StripOffsets (273) LONG (4) 1248<8 7558 15109 22684 30223 37769 45253 52740 60181 67699 75210 82702 90231 97784 105221 112698 120165 127581 135073 142615 150195 157794 165402 173003 ...>
Orientation (274) SHORT (3) 1<1>
SamplesPerPixel (277) SHORT (3) 1<4>           <--- 4 SAMPLES PER PIXEL
RowsPerStrip (278) LONG (4) 1<1>
StripByteCounts (279) LONG (4) 1248<7550 7551 7575 7539 7546 7484 7487 7441 7518 7511 7492 7529 7553 7437 7477 7467 7416 7492 7542 7580 7599 7608 7601 7565 ...>
XResolution (282) RATIONAL (5) 1<1600>
YResolution (283) RATIONAL (5) 1<1600>
PlanarConfig (284) SHORT (3) 1<1>
ResolutionUnit (296) SHORT (3) 1<2>
Predictor (317) SHORT (3) 1<2>
ExtraSamples (338) SHORT (3) 1<2>
SampleFormat (339) SHORT (3) 3<1 1 1>          <--- ONLY THREE FORMATS BUT 4 SAMPLES

As a workaround, it seems that tifffile can open the "unhappy" image, so you can use:

from tifffile import imread

# Open with "tifffile"
img = imread('3200B_W_E_B_NG.TIFF')

# Make into "PIL Image" and carry on as usual
pi = Image.fromarray(img)