#!/usr/bin/env python
"""
A wrapper function for t2p and ghostscript to rotate tiff g4 bitmaps
"""

import re,os,sys,string,operator,math


def getbbox(tx):
	mat = re.search(r"\n%%\s*BoundingBox:?\s*(\d+)\s+(\d+)\s+(\d+)\s+(\d+)",tx)
	return tuple(map(lambda a,mat=mat:int(mat.group(a)),range(1,5)))


def addrotatecode(tx,angle,clippath=None):
	"""
	tx is the postscript source (including a bounding box definition),
	angle the rotation angle in radians"""

	bbox = getbbox(tx)
	
	# compute to shift the center of the transformed bounding box to
	# the center of a letter page
	sa,ca = math.sin(angle),math.cos(angle)
	if not clippath:
		mx,my = bbox[2]+bbox[0],bbox[3]+bbox[1]
		x0s = bbox[0]*ca+bbox[1]*sa
		y0s = -bbox[0]*sa+bbox[1]*ca
		mxs = mx*ca+my*sa
		mys = -mx*sa+my*ca
		cxs = (mxs+x0s)/2
		cys = (mys+y0s)/2
		dx = 558/2.-cxs
		dy = 757/2.-cys
	else:
		apath = map(lambda a:(a[0]*72.0/300.0,a[1]*72.0/300.0),clippath)
		a = apath[0]
		# Threshing in the additional 10 is supposed to keep a little
		# lower edge
		dx,dy = a[0]*ca+a[1]*sa,a[1]*ca-a[0]*sa
		for a in apath[1:]:
			dx = min(a[0]*ca+a[1]*sa,dx)
			dy = min(a[1]*ca-a[0]*sa,dy)
		dx = -dx
		dy = -dy
	code = re.sub(r"\n\t+","\n",
		"""%f %f translate
		%f rotate
		"""%(dx,dy,
		-angle/2.0/3.14159*360.0))
	return re.sub("(100 dict begin)",r"\1\n%s"%code,tx)


def addclippath(tx,clippath):
	apath = map(lambda a:"%f %f"%(a[0]*72.0/300.0,a[1]*72.0/300.0),clippath)
	code = ("%s moveto "%apath[0])+\
		reduce(operator.add,map(lambda a:"%s lineto "%a,apath[1:]))+\
		"closepath clip"
	return re.sub("(100 dict begin)",r"\1\n%s"%code,tx)


def rotate(tifffname,angle,clippath):
	if not os.path.exists(tifffname):
		sys.stderr.write("unrotate.py: %s not found\n"%tifffname)
		return
	os.system("tiffproc -setres 300 %s"%tifffname)
	tx = os.popen("t2p -R 0 %s"%tifffname).read()
	if clippath:
		tx = addclippath(tx,clippath)
		tx = addrotatecode(tx,angle,clippath=clippath)
	else:
		tx = addrotatecode(tx,angle)
	sa,ca = math.sin(angle),math.cos(angle)
	transpath = []
	for a in clippath:
		transpath.append((ca*a[0]+sa*a[1],ca*a[1]-sa*a[0]))
	x0 = int(reduce(lambda a,b:min(a,b),map(lambda a:a[0],transpath)))
	x1 = int(reduce(lambda a,b:max(a,b),map(lambda a:a[0],transpath)))
	y0 = int(reduce(lambda a,b:min(a,b),map(lambda a:a[1],transpath)))
	y1 = int(reduce(lambda a,b:max(a,b),map(lambda a:a[1],transpath)))
	
	os.system("cp %s orig/%s"%(tifffname,tifffname))
	#open("test.ps","w").write(tx)
	os.popen(("gs -q -dNOPAUSE -sDEVICE=tiffg4 -r300x300 -g%dx%d"%(
		x1-x0,y1-y0))+
		" -sOutputFile=%s -"%tifffname,"w").write(tx)
	try:
		os.chmod(tifffname,0664)
	except os.error:
		pass


usage = """unrotate <fname> <angle> <clipx1>,<clipy1> ... <clipxn>,<clipyn>
  where angle is in radian and the clippath in pixels"""

if __name__=="__main__":
	import sys
	clippatha = sys.argv[3:]
	clippath = []
	for a in clippatha:
		clippath.append(map(float,string.split(a,",")))
	
	rotate(sys.argv[1],float(sys.argv[2]),clippath)
