[Image-SIG] GeoTIFF? (and patch)

Greg Couch gregc@cgl.ucsf.EDU
Wed, 18 Apr 2001 17:00:00 -0700 (PDT)


Here's an alternative patch to add image resolution and several other
TIFF tags to TIFF files.  Here you would add various entries to the
Image.save's options parameter to place them in a TIFF file.  The ones
I added are: "resolution unit", "resolution", "x resolution", "y resolution",
"software", "date time", "artist", and "copyright".  TIFF images already
supported an image "description" option.  The resolutions are correctly
written as TIFF rational values.

Please cc any replies directly to me as I do not normally read this
mailing list.

	Greg Couch
	UCSF Computer Graphics Lab
	gregc@cgl.ucsf.edu

===================================================================
RCS file: RCS/TiffImagePlugin.py,v
retrieving revision 1.1
diff -c -r1.1 TiffImagePlugin.py
*** TiffImagePlugin.py	2001/04/18 21:40:09	1.1
--- TiffImagePlugin.py	2001/04/18 23:54:25
***************
*** 66,77 ****
--- 66,84 ----
  SAMPLESPERPIXEL = 277
  ROWSPERSTRIP = 278
  STRIPBYTECOUNTS = 279
+ X_RESOLUTION = 282
+ Y_RESOLUTION = 283
  PLANAR_CONFIGURATION = 284
+ RESOLUTION_UNIT = 296
+ SOFTWARE = 305
+ DATE_TIME = 306
+ ARTIST = 315
  PREDICTOR = 317
  COLORMAP = 320
  EXTRASAMPLES = 338
  SAMPLEFORMAT = 339
  JPEGTABLES = 347
+ COPYRIGHT = 33432
  IPTC_NAA_CHUNK = 33723 # newsphoto properties
  PHOTOSHOP_CHUNK = 34377 # photoshop properties
  
***************
*** 313,318 ****
--- 320,328 ----
  		if tag == STRIPOFFSETS:
  		    stripoffsets = len(directory)
  		    typ = 4 # to avoid catch-22
+ 		elif tag in (X_RESOLUTION, Y_RESOLUTION):
+ 		    # identify rational data fields
+ 		    typ = 5
  		else:
  		    typ = 3
  		    for v in value:
***************
*** 329,335 ****
  	    elif len(data) < 4:
  		append((tag, typ, len(value), data + (4-len(data))*"\0", ""))
  	    else:
! 		append((tag, typ, len(value), o32(offset), data))
  		offset = offset + len(data)
  		if offset & 1:
  		    offset = offset + 1 # word padding
--- 339,348 ----
  	    elif len(data) < 4:
  		append((tag, typ, len(value), data + (4-len(data))*"\0", ""))
  	    else:
! 		count = len(value)
! 		if typ == 5:
! 		    count = count / 2	# adjust for rational data field
! 		append((tag, typ, count, o32(offset), data))
  		offset = offset + len(data)
  		if offset & 1:
  		    offset = offset + 1 # word padding
***************
*** 551,556 ****
--- 564,579 ----
      "LAB": ("LAB", 8, 1, (8,8,8), None),
  }
  
+ def _cvt_res(value):
+     # convert value to TIFF rational number -- (numerator, denominator)
+     if type(value) in (type([]), type(())):
+ 	assert(len(value) % 2 == 0)
+ 	return value
+     if type(value) == type(1):
+ 	return (value, 1)
+     value = float(value)
+     return (int(value * 65536), 65536)
+ 
  def _save(im, fp, filename):
  
      try:
***************
*** 566,573 ****
--- 589,626 ----
      ifd[IMAGEWIDTH] = im.size[0]
      ifd[IMAGELENGTH] = im.size[1]
  
+     # additions written by Greg Couch, gregc@cgl.ucsf.edu
+     # inspired by image-sig posting from Kevin Cazabon, kcazabon@home.com
+     if hasattr(im, 'tag'):
+ 	# preserve tags from original TIFF image file
+ 	for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION):
+ 	    if im.tag.tagdata.has_key(key):
+ 		ifd[key] = im.tag.tagdata.get(key)
      if im.encoderinfo.has_key("description"):
  	ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"]
+     if im.encoderinfo.has_key("resolution"):
+ 	ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] \
+ 				= _cvt_res(im.encoderinfo["resolution"])
+     if im.encoderinfo.has_key("x resolution"):
+ 	ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo["x resolution"])
+     if im.encoderinfo.has_key("y resolution"):
+ 	ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo["y resolution"])
+     if im.encoderinfo.has_key("resolution unit"):
+ 	unit = im.encoderinfo["resolution unit"]
+ 	if unit == "inch":
+ 		ifd[RESOLUTION_UNIT] = 2
+ 	elif unit == "cm" or unit == "centimeter":
+ 		ifd[RESOLUTION_UNIT] = 3
+ 	else:
+ 		ifd[RESOLUTION_UNIT] = 1
+     if im.encoderinfo.has_key("software"):
+ 	ifd[SOFTWARE] = im.encoderinfo["software"]
+     if im.encoderinfo.has_key("date time"):
+ 	ifd[DATE_TIME] = im.encoderinfo["date time"]
+     if im.encoderinfo.has_key("artist"):
+ 	ifd[ARTIST] = im.encoderinfo["artist"]
+     if im.encoderinfo.has_key("copyright"):
+ 	ifd[COPYRIGHT] = im.encoderinfo["copyright"]
  
      if bits != (1,):
  	ifd[BITSPERSAMPLE] = bits