#!/usr/bin/python
#
#   imagepalettize - convert rgb or rgba textures to descent-usable paletted
#   textures (conversion with other apps won't handle (super-)transparency.)
#
#   Copyright (C) 2003 Matthew Mueller <donut@dakotacom.net>
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import os,sys,cStringIO
import Image
from optparse import OptionParser

parser = OptionParser()
parser.add_option("-d", "--directory", dest="directory",
		help="write palettized textures to DIR instead of .", default=os.curdir, metavar="DIR")
parser.add_option("-p", "--palette", dest="palfile",
		help="alternate palette to use (bad idea)", default=None, metavar="FILE")
#parser.add_option("-q", "--quiet",
#		action="store_false", dest="verbose", default=True,
#		help="don't print status messages to stdout")

(options, args) = parser.parse_args()


if options.palfile:
	paldata = open(options.palfile).read()
else:
	paldata = '\x00\x00\x0000((0 ((  (    \x18  \x18 (\x18((\x18(0 (0((0(00(080088088@@8HHHHHPH@PXPX`HX`hhphpxp\x80\x80x(88 00 ((  (\x18\x18 \x18\x18\x18\x18\x18\x10  \x10( \x180( \x18 \x18\x10\x18\x18\x10\x18 \x10\x10\x18\x08\x08\x08\x08\x10\x10\x08\x08\x10\x08\x08\x08\x00\x08\x08\x00\x00\x08\x00\x00\x00 (8\xf4\xf4\xf4\xec\xec\xec\xe4\xe4\xe4\xdc\xdc\xdc\xd4\xd4\xd4\xcc\xcc\xcc\xc4\xc4\xc4\xbc\xbc\xbc\xb4\xb4\xb4\xac\xac\xac\xa4\xa4\xa4\x9c\x9c\x9c\x94\x94\x94\x8c\x8c\x8c\x88\x88\x88\x80\x80\x80xxxppphhh```XXXPPPHHH@@@888000(((   \x18\x18\x18\x10\x10\x10\x0c\x0c\x0c\x04\x04\x04\xe0\xe0\xfc\xb0\xb0\xfc\x84\x84\xfcTT\xfc((\xfc\x00\x00\xfc\x00\x00\xe4\x00\x00\xcc\x00\x00\xb4\x00\x00\x9c\x00\x00\x84\x00\x00l\x00\x00T\x00\x00<\x00\x00$\x00\x00\x0c\xf8\xb0\xfc\xf4\x80\xfc\xf4T\xfc\xf0\x00\xfc\xd0\x00\xe0\xb4\x00\xc4\x98\x00\xac|\x00\x90`\x00tH\x00\\0\x00@\x1c\x00$\x08\x00\x0c\xec\xd8\xd8\xe4\xd0\xd0\xdc\xc8\xc8\xd4\xc0\xc0\xcc\xb8\xb8\xc4\xb0\xb0\xc0\xa8\xa8\xb8\xa0\xa0\xb0\x98\x98\xa8\x90\x90\xa0\x88\x88\x98\x80\x80\x94||\x88ll|``tTThLL\\@@T44H,,<$$0\x14\x14$\x08\x08\x18\x00\x00\x0c\x00\x00\xa4\x98|\x88|Tp`8XH\x1c<0\x0c$\x1c\x00\x0c\x08\x00\xc4\xf0\xb8\xa4\xd8\x94\x88\xc4tp\xac\\X\x98DD\x8004l\x1c$T\x10\x18@\x04\x0c(\x00\x04\x14\x00x\xfcx\x00\xfc\x00\x00\xe4\x00\x00\xd0\x00\x00\xb8\x00\x00\xa0\x00\x00\x8c\x00\x00t\x00\x00`\x00\x00H\x00\x004\x00\x00\x1c\x00\x00\x08\x00\xfc\xe4h\xe8\xc4P\xd4\xa8<\xc4\x8c,\xb0p\x1c\xa0T\x10\x8c<\x04l \x00P\x10\x004\x04\x00\x18\x00\x00\xfc\xfc\x00\xc0\xc0\x00\x88\x88\x00PP\x00\x18\x18\x00\xfc\xfc\xb8\xfc\xfcx\xfc\xfc8\xfc\xe88\xfc\xd0,\xfc\xbc$\xfc\xa4 \xfc\x88\x18\xfcp\x14\xfcT\x0c\xfc8\x08\xfc\x18\x04\xfc\x00\x00\xe8\x00\x00\xd8\x00\x00\xc8\x00\x00\xb8\x00\x00\xa8\x00\x00\x98\x00\x00\x88\x00\x00t\x00\x00d\x00\x00T\x00\x00@\x00\x000\x00\x00\x1c\x00\x00\x0c\x00\x00\xfc\xa4P\xfc|\x00\xcc\\\x00\xa0@\x00p(\x00D\x14\x00\x18\x04\x00\x8c\x8c\xdctt\xbc\\\\\x9cHH\x8000`  @\x10\x10$\xc0\xac\xac\xa4\x94\x94\x8c\x80|tld\\XPD@8,,$\x14\x14\x10\xbc\x88\xd8\x9cp\xb8\x80\\\x98dDxH0X0\x1c8\x14\x0c\x18h\xbcPX\xa4DL\x908@x04d($L\x1c\x1c8\x14\x10$\x0c\xfc\xb8\xb8\xfc\x88\x88\xfcXX\xfc((\xf8\xc8\xb8\xf4\xb0\x98\xf4\x98|\xbclT\x88D0T$\x18\xfc\xfc\xfc'
#palette = Image.ImagePalette.load("/home/donut/.gimp-1.2/palettes/Descent")
#paldata = palette[0]

palmap = {}
for i in range(0,256):
	rgb = paldata[i*3:i*3+3]
	palmap[rgb] = i

saveopts={'optimize':1}

for fn in args:
	i = Image.open(fn)
	#if i.mode == 'P':
	#	print fn,"already paletted"
	#	continue
	if i.mode == 'RGB':
		odata=cStringIO.StringIO()
		idata=i.tostring()
		for x in range(0,len(idata)/3):
			pixel=idata[x*3:x*3+3]
			if pixel not in palmap:
				print fn,'not representable by palette',repr(pixel)
				break
			idx = palmap[pixel]
			odata.write(chr(idx))
		odata=odata.getvalue()
		if len(odata)!=len(idata)/3:
			print 'foo1'
			continue
		if 'transparency' in saveopts:
			del saveopts['transparency']
	elif i.mode == 'RGBA':
		odata=cStringIO.StringIO()
		idata=i.tostring()
		for x in range(0,len(idata)/4):
			pixel=idata[x*4:x*4+4]
			if pixel=='\x00\x00\x00\x00':
				odata.write(chr(255))
			elif pixel=='\xFF\xFF\xFF\x00':
				odata.write(chr(254))
			elif pixel[3]=='\xFF' and pixel[0:3] in palmap:
				idx = palmap[pixel[0:3]]
				odata.write(chr(idx))
			else:
				print fn,'unhandled pixel',repr(pixel)
				break
		odata=odata.getvalue()
		if len(odata)!=len(idata)/4:
			print 'foo2'
			continue
		saveopts['transparency']=255 #doesn't actually do anything with current version of PIL, oh well.  Descent doesn't care either way.
	else:
		print fn,"unhandled mode",i.mode
		continue

	ip = Image.fromstring("P",i.size,odata)
	ip.putpalette(paldata)
	basefn = os.path.splitext(os.path.split(fn)[1])[0]
	newfn = os.path.join(options.directory,basefn+'.png')
	if os.path.exists(newfn):
		print newfn,'already exists!'
		continue
	ip.save(newfn,**saveopts)

