1

I'm currently writing a program that searches through an inputted folder and flags errors such as missing or empty files. One of the errors I need to check is if all of the .dpx images have the same resolution. However, I can't seem to find a way to check this. PIL can't open the file and I can't find a way to check the metadata. Any ideas?

This is the code I have for doing this at the moment:

im = Image.open(fullName)

if im.size != checkResolution:
    numErrors += 1
    reportMessages.append(ReportEntry(file, "WARNING",
                                      "Unusual Resolution"))

fullName is the path to the file. checkResolution is the correct resolution as a tuple. reportMessages simply collects error strings to be printed in a report later. Running the program at the moment returns:

Traceback (most recent call last):

   File "Program1V4", line 169, in <module>
     main(sys.argv[1:])

   File "Program1V4", line 108, in main
    im = Image.open(fullName)

  File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 1983, in open
    raise IOError("cannot identify image file")

 IOError: cannot identify image file
NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
Nick
  • 23
  • 6

2 Answers2

2

This may not be the most pythonic or fastest way (without using structs or ctypes - or doing it in c!), but I would pull the fields from the file header directly (don't forget to check for errors...):

# Open the DPX file 
fi = open(frame, 'r+b') 

# Retrieve the magic number from the file header - this idicates the endianness 
# of the numerical file data
magic_number = struct.unpack('I', currFile.read(4))[0] 

# Set the endianness for reading the values in
if not magic_number == 1481655379: # 'SDPX' in ASCII
    endianness = "<"
else:
    endianness = ">"

# Seek to x/y offset in header (1424 bytes in is the x pixel 
# count of the first image element, 1428 is the y count)
currFile.seek(1424, 0)

# Retrieve values (4 bytes each) from file header offset 
# according to file endianness
x_resolution = struct.unpack(endianness+"I", currFile.read(4))[0]
y_resolution = struct.unpack(endianness+"I", currFile.read(4))[0]

fi.close()

# Put the values into a tuple
image_resolution = (x_resolution, y_resolution)

# Print
print(image_resolution)

DPX has the potential to be quite a difficult format to parse if there are several image elements - the above code should give you what you are looking for for most use cases (single image element) without the overhead of importing a big old library.

It's well worth getting hold of the SMPTE standard for DPX and giving it a skim (last revision in 2014) as it lists all the offsets for the other goodies held within the header.

TwoTriads
  • 21
  • 3
0

Unfortunately Pillow/PIL doesn't understand the SMPTE Digital Picture Exchange Format yet.

However, ImageMagick supports it and ImageMagick can be controlled by Python or you simply call ImageMagick as an external command.

A bit more work but also possible is compiling a C library and then call it from Python. It would be interesting to know if ImageMagick is using this library under the hood or has its own implementation of the standard.

Community
  • 1
  • 1
NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104