jpeg.py 3.07 KB
Newer Older
1 2 3 4 5 6 7
# 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.

8 9
class error(Exception):
	pass
10 11 12 13 14 15 16 17

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

comp = None
decomp = None

def compress(imgdata, width, height, bytesperpixel):
	global comp
Guido van Rossum's avatar
Guido van Rossum committed
18 19
	import cl
	if comp is None: comp = cl.OpenCompressor(cl.JPEG)
20
	if bytesperpixel == 1:
Guido van Rossum's avatar
Guido van Rossum committed
21
		format = cl.GRAYSCALE
22
	elif bytesperpixel == 4:
Guido van Rossum's avatar
Guido van Rossum committed
23
		format = cl.RGBX
24
	if options['forcegray']:
Guido van Rossum's avatar
Guido van Rossum committed
25
		iformat = cl.GRAYSCALE
26
	else:
Guido van Rossum's avatar
Guido van Rossum committed
27
		iformat = cl.YUV
28
	# XXX How to support 'optimize'?
Guido van Rossum's avatar
Guido van Rossum committed
29 30 31 32 33
	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,
34 35 36 37 38 39 40
		 ]
	comp.SetParams(params)
	jpegdata = comp.Compress(1, imgdata)
	return jpegdata

def decompress(jpegdata):
	global decomp
Guido van Rossum's avatar
Guido van Rossum committed
41 42
	import cl
	if decomp is None: decomp = cl.OpenDecompressor(cl.JPEG)
43
	headersize = decomp.ReadHeader(jpegdata)
Guido van Rossum's avatar
Guido van Rossum committed
44
	params = [cl.IMAGE_WIDTH, 0, cl.IMAGE_HEIGHT, 0, cl.INTERNAL_FORMAT, 0]
45 46
	decomp.GetParams(params)
	width, height, format = params[1], params[3], params[5]
Guido van Rossum's avatar
Guido van Rossum committed
47 48
	if format == cl.GRAYSCALE or options['forcegray']:
		format = cl.GRAYSCALE
49 50
		bytesperpixel = 1
	else:
Guido van Rossum's avatar
Guido van Rossum committed
51
		format = cl.RGBX
52 53
		bytesperpixel = 4
	# XXX How to support 'smooth'?
Guido van Rossum's avatar
Guido van Rossum committed
54 55 56
	params = [cl.ORIGINAL_FORMAT, format,
		  cl.ORIENTATION, cl.BOTTOM_UP,
		  cl.FRAME_BUFFER_SIZE, width*height*bytesperpixel]
57 58 59 60 61
	decomp.SetParams(params)
	imgdata = decomp.Decompress(1, jpegdata)
	return imgdata, width, height, bytesperpixel

def setoption(name, value):
62
	if type(value) is not type(0):
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
		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)