# Implement 'jpeg' interface using SGI's compression library

# XXX Options 'smooth' and 'optimize' are ignored.

# XXX It appears that compressing grayscale images doesn't work right;
# XXX the resulting file causes weirdness.

class error(Exception):
	pass

options = {'quality': 75, 'optimize': 0, 'smooth': 0, 'forcegray': 0}

comp = None
decomp = None

def compress(imgdata, width, height, bytesperpixel):
	global comp
	import cl
	if comp is None: comp = cl.OpenCompressor(cl.JPEG)
	if bytesperpixel == 1:
		format = cl.GRAYSCALE
	elif bytesperpixel == 4:
		format = cl.RGBX
	if options['forcegray']:
		iformat = cl.GRAYSCALE
	else:
		iformat = cl.YUV
	# XXX How to support 'optimize'?
	params = [cl.IMAGE_WIDTH, width, cl.IMAGE_HEIGHT, height, \
		  cl.ORIGINAL_FORMAT, format, \
		  cl.ORIENTATION, cl.BOTTOM_UP, \
		  cl.QUALITY_FACTOR, options['quality'], \
		  cl.INTERNAL_FORMAT, iformat, \
		 ]
	comp.SetParams(params)
	jpegdata = comp.Compress(1, imgdata)
	return jpegdata

def decompress(jpegdata):
	global decomp
	import cl
	if decomp is None: decomp = cl.OpenDecompressor(cl.JPEG)
	headersize = decomp.ReadHeader(jpegdata)
	params = [cl.IMAGE_WIDTH, 0, cl.IMAGE_HEIGHT, 0, cl.INTERNAL_FORMAT, 0]
	decomp.GetParams(params)
	width, height, format = params[1], params[3], params[5]
	if format == cl.GRAYSCALE or options['forcegray']:
		format = cl.GRAYSCALE
		bytesperpixel = 1
	else:
		format = cl.RGBX
		bytesperpixel = 4
	# XXX How to support 'smooth'?
	params = [cl.ORIGINAL_FORMAT, format, \
		  cl.ORIENTATION, cl.BOTTOM_UP, \
		  cl.FRAME_BUFFER_SIZE, width*height*bytesperpixel]
	decomp.SetParams(params)
	imgdata = decomp.Decompress(1, jpegdata)
	return imgdata, width, height, bytesperpixel

def setoption(name, value):
	if type(value) is not type(0):
		raise TypeError, 'jpeg.setoption: numeric options only'
	if name == 'forcegrey':
		name = 'forcegray'
	if not options.has_key(name):
		raise KeyError, 'jpeg.setoption: unknown option name'
	options[name] = int(value)

def test():
	import sys
	if sys.argv[1:2] == ['-g']:
		del sys.argv[1]
		setoption('forcegray', 1)
	if not sys.argv[1:]:
		sys.argv.append('/usr/local/images/data/jpg/asterix.jpg')
	for file in sys.argv[1:]:
		show(file)

def show(file):
	import gl, GL, DEVICE
	jpegdata = open(file, 'r').read()
	imgdata, width, height, bytesperpixel = decompress(jpegdata)
	gl.foreground()
	gl.prefsize(width, height)
	win = gl.winopen(file)
	if bytesperpixel == 1:
		gl.cmode()
		gl.pixmode(GL.PM_SIZE, 8)
		gl.gconfig()
		for i in range(256):
			gl.mapcolor(i, i, i, i)
	else:
		gl.RGBmode()
		gl.pixmode(GL.PM_SIZE, 32)
		gl.gconfig()
	gl.qdevice(DEVICE.REDRAW)
	gl.qdevice(DEVICE.ESCKEY)
	gl.qdevice(DEVICE.WINQUIT)
	gl.qdevice(DEVICE.WINSHUT)
	gl.lrectwrite(0, 0, width-1, height-1, imgdata)
	while 1:
		dev, val = gl.qread()
		if dev in (DEVICE.ESCKEY, DEVICE.WINSHUT, DEVICE.WINQUIT):
			break
		if dev == DEVICE.REDRAW:
			gl.lrectwrite(0, 0, width-1, height-1, imgdata)
	gl.winclose(win)
	# Now test the compression and write the result to a fixed filename
	newjpegdata = compress(imgdata, width, height, bytesperpixel)
	open('/tmp/j.jpg', 'w').write(newjpegdata)
