summaryrefslogtreecommitdiffstats
path: root/Demo/sgi
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1992-09-07 15:28:57 (GMT)
committerGuido van Rossum <guido@python.org>1992-09-07 15:28:57 (GMT)
commit4526f379bca5695b2144f1142f6a524d77bb7fe4 (patch)
tree04d0dce5bf7aefcf113af158b0abe6758a8fec95 /Demo/sgi
parent2de9b68fea0be67d731b275b38fa015d95702f69 (diff)
downloadcpython-4526f379bca5695b2144f1142f6a524d77bb7fe4.zip
cpython-4526f379bca5695b2144f1142f6a524d77bb7fe4.tar.gz
cpython-4526f379bca5695b2144f1142f6a524d77bb7fe4.tar.bz2
Fixed "clear()" and added "clearto(r, g, b)".
Added class RandomVinFile which supports random access and warming the cache. Added eofseen and errorseen methods to BasicVinFile. Use RGB mode for rgb8 data on entry level Indigo. Minor cosmetic changes.
Diffstat (limited to 'Demo/sgi')
-rwxr-xr-xDemo/sgi/video/VFile.py246
1 files changed, 217 insertions, 29 deletions
diff --git a/Demo/sgi/video/VFile.py b/Demo/sgi/video/VFile.py
index 0f72306..e5aea41 100755
--- a/Demo/sgi/video/VFile.py
+++ b/Demo/sgi/video/VFile.py
@@ -11,6 +11,9 @@
# BasicVoutFile: write a CMIF video file
# VinFile: BasicVinFile + Displayer
# VoutFile: BasicVoutFile + Displayer + Grabber
+#
+# XXX Future extension:
+# BasicVinoutFile: supports overwriting of individual frames
# Imported modules
@@ -25,6 +28,7 @@ import colorsys
Error = 'VFile.Error' # file format errors
CallError = 'VFile.CallError' # bad call
+AssertError = 'VFile.AssertError' # internal malfunction
# Constants returned by gl.getdisplaymode(), from <gl/get.h>
@@ -75,6 +79,61 @@ def choose_conversion(format):
raise Error, 'Unknown color system: ' + `format`
+# Inverses of the above
+
+def inv_grey(r, g, b):
+ y, i, q = colorsys.rgb_to_yiq(r, g, b)
+ return y, 0, 0
+
+def inv_yiq(r, g, b):
+ y, i, q = colorsys.rgb_to_yiq(r, g, b)
+ return y, i/1.2 + 0.5, q + 0.5
+
+def inv_hls(r, g, b):
+ h, l, s = colorsys.rgb_to_hls(r, g, b)
+ return l, h, s
+
+def inv_hsv(r, g, b):
+ h, s, v = colorsys.rgb_to_hsv(r, g, b)
+ return v, h, s
+
+def inv_rgb(r, g, b):
+ raise Error, 'Attempt to invert RGB colormap'
+
+def inv_rgb8(r, g, b):
+ r = int(r*7.0)
+ g = int(g*7.0)
+ b = int(b*7.0)
+ rgb = ((r&7) << 5) | ((b&3) << 3) | (g&7)
+ return rgb / 255.0, 0, 0
+
+
+# Choose one of the above based upon a color system name
+
+def choose_inverse(format):
+ try:
+ return eval('inv_' + format)
+ except:
+ raise Error, 'Unknown color system: ' + `format`
+
+
+# Predicate to see whether this is an entry level (non-XS) Indigo.
+# If so we can lrectwrite 8-bit wide pixels into a window in RGB mode
+
+def is_entry_indigo():
+ # XXX hack, hack. We should call gl.gversion() but that doesn't
+ # exist in earlier Python versions. Therefore we check the number
+ # of bitplanes *and* the size of the monitor.
+ xmax = gl.getgdesc(GL.GD_XPMAX)
+ if xmax <> 1024: return 0
+ ymax = gl.getgdesc(GL.GD_YPMAX)
+ if ymax != 768: return 0
+ r = gl.getgdesc(GL.GD_BITS_NORM_SNG_RED)
+ g = gl.getgdesc(GL.GD_BITS_NORM_SNG_GREEN)
+ b = gl.getgdesc(GL.GD_BITS_NORM_SNG_BLUE)
+ return (r, g, b) == (3, 3, 2)
+
+
# Routines to grab data, per color system (only a few really supported).
# (These functions are used via eval with a constructed argument!)
@@ -90,14 +149,10 @@ def grab_rgb8(w, h, pf):
raise Error, 'Sorry, can only grab rgb8 in single-buf rgbmode'
if pf <> 1 and pf <> 0:
raise Error, 'Sorry, can only grab rgb8 with packfactor 1'
- r = gl.getgdesc(GL.GD_BITS_NORM_SNG_RED)
- g = gl.getgdesc(GL.GD_BITS_NORM_SNG_GREEN)
- b = gl.getgdesc(GL.GD_BITS_NORM_SNG_BLUE)
- if (r, g, b) <> (3, 3, 2):
- raise Error, 'Sorry, can only grab rgb8 on 8-bit Indigo'
+ if not is_entry_indigo():
+ raise Error, 'Sorry, can only grab rgb8 on entry level Indigo'
# XXX Dirty Dirty here.
# XXX Set buffer to cmap mode, grab image and set it back.
- # XXX (Shouldn't be necessary???)
gl.cmode()
gl.gconfig()
gl.pixmode(GL.PM_SIZE, 8)
@@ -193,7 +248,7 @@ class VideoParams:
# Class to display video frames in a window.
# It is the caller's responsibility to ensure that the correct window
-# is current when using showframe(), initcolormap() and clear()
+# is current when using showframe(), initcolormap(), clear() and clearto()
class Displayer(VideoParams):
@@ -211,6 +266,8 @@ class Displayer(VideoParams):
# Internal flags
self.colormapinited = 0 # must initialize window
self.skipchrom = 0 # don't skip chrominance data
+ self.color0 = None # magic, used by clearto()
+ self.fixcolor0 = 0 # don't need to fix color0
return self
# setinfo() must reset some internal flags
@@ -219,12 +276,17 @@ class Displayer(VideoParams):
VideoParams.setinfo(values)
self.colormapinited = 0
self.skipchrom = 0
+ self.color0 = None
+ self.fixcolor0 = 0
# Show one frame, initializing the window if necessary
def showframe(self, data, chromdata):
if not self.colormapinited:
self.initcolormap()
+ if self.fixcolor0:
+ gl.mapcolor(self.color0)
+ self.fixcolor0 = 0
w, h, pf = self.width, self.height, self.packfactor
factor = self.magnify
if pf: factor = factor * pf
@@ -247,18 +309,28 @@ class Displayer(VideoParams):
gl.rectzoom(factor, factor)
gl.lrectwrite(self.xorigin, self.yorigin, \
self.xorigin + w - 1, self.yorigin + h - 1, data)
+ gl.gflush()
# Initialize the window: set RGB or colormap mode as required,
# fill in the colormap, and clear the window
def initcolormap(self):
+ self.colormapinited = 1
+ self.color0 = None
+ self.fixcolor0 = 0
if self.format == 'rgb':
gl.RGBmode()
gl.gconfig()
- self.colormapinited = 1
gl.RGBcolor(200, 200, 200) # XXX rather light grey
gl.clear()
return
+ if self.format == 'rgb8' and is_entry_indigo():
+ gl.RGBmode()
+ gl.gconfig()
+ gl.RGBcolor(200, 200, 200) # XXX rather light grey
+ gl.clear()
+ gl.pixmode(GL.PM_SIZE, 8)
+ return
gl.cmode()
gl.gconfig()
self.skipchrom = 0
@@ -269,29 +341,51 @@ class Displayer(VideoParams):
if not self.quiet:
sys.stderr.write('Initializing color map...')
self._initcmap()
- self.colormapinited = 1
- self.clear()
+ gl.clear()
if not self.quiet:
sys.stderr.write(' Done.\n')
- # Clear the window
+ # Clear the window to a default color
def clear(self):
if not self.colormapinited: raise CallError
- if self.offset == 0:
- gl.color(0x800)
- gl.clear()
- else:
+ if gl.getdisplaymode() in (DMRGB, DMRGBDOUBLE):
+ gl.RGBcolor(200, 200, 200) # XXX rather light grey
gl.clear()
+ return
+ gl.writemask(0xffffffff)
+ gl.clear()
+
+ # Clear the window to a given RGB color.
+ # This may steal the first color index used; the next call to
+ # showframe() will restore the intended mapping for that index
- # Do the hard work for initializing the colormap
+ def clearto(self, r, g, b):
+ if not self.colormapinited: raise CallError
+ if gl.getdisplaymode() in (DMRGB, DMRGBDOUBLE):
+ gl.RGBcolor(r, g, b)
+ gl.clear()
+ return
+ index = self.color0[0]
+ self.fixcolor0 = 1
+ gl.mapcolor(index, r, g, b)
+ gl.writemask(0xffffffff)
+ gl.clear()
+ gl.gflush()
+
+ # Do the hard work for initializing the colormap (internal).
+ # This also sets the current color to the first color index
+ # used -- the caller should never change this since it is used
+ # by clear() and clearto()
def _initcmap(self):
convcolor = choose_conversion(self.format)
maxbits = gl.getgdesc(GL.GD_BITS_NORM_SNG_CMODE)
if maxbits > 11:
maxbits = 11
- c0bits, c1bits, c2bits = self.c0bits, self.c1bits, self.c2bits
+ c0bits = self.c0bits
+ c1bits = self.c1bits
+ c2bits = self.c2bits
if c0bits+c1bits+c2bits > maxbits:
if self.fallback and c0bits < maxbits:
# Cannot display frames in this mode, use grey
@@ -310,10 +404,8 @@ class Displayer(VideoParams):
offset = self.offset
if maxbits <> 11:
offset = offset & ((1<<maxbits)-1)
- # XXX why is this here?
- # for i in range(512, MAXMAP):
- # gl.mapcolor(i, 0, 0, 0)
- # gl.gflush()
+ self.color0 = None
+ self.fixcolor0 = 0
for c0 in range(maxc0):
c0v = c0/float(maxc0-1)
for c1 in range(maxc1):
@@ -335,6 +427,11 @@ class Displayer(VideoParams):
int(gv*255.0), \
int(bv*255.0)
gl.mapcolor(index, r, g, b)
+ if self.color0 == None:
+ self.color0 = \
+ index, r, g, b
+ # Permanently make the first color index current
+ gl.color(self.color0[0])
gl.gflush() # send the colormap changes to the X server
@@ -379,6 +476,7 @@ def readfileheader(fp, filename):
filename + ': Unrecognized file header: ' + `line`[:20]
#
# Get color encoding info
+ # (The format may change to 'rgb' later when packfactor == 0)
#
if version <= 1.0:
format = 'grey'
@@ -412,6 +510,7 @@ def readfileheader(fp, filename):
chrompack = 0
offset = 0
else:
+ # XXX ought to check that the format is valid
try:
c0bits, c1bits, c2bits, chrompack, offset = rest
except:
@@ -424,10 +523,13 @@ def readfileheader(fp, filename):
x = eval(line[:-1])
except:
raise Error, filename + ': Bad (w,h,pf) info'
+ if type(x) <> type(()):
+ raise Error, filename + ': Bad (w,h,pf) info'
if len(x) == 3:
width, height, packfactor = x
if packfactor == 0 and version < 3.0:
format = 'rgb'
+ c0bits = 0
elif len(x) == 2 and version <= 1.0:
width, height = x
packfactor = 2
@@ -548,6 +650,8 @@ class BasicVinFile(VideoParams):
filename + ': Bad version: ' + `self.version`
self.framecount = 0
self.atframeheader = 1
+ self.eofseen = 0
+ self.errorseen = 0
try:
self.startpos = self.fp.tell()
self.canseek = 1
@@ -578,9 +682,11 @@ class BasicVinFile(VideoParams):
self.fp.seek(self.startpos)
self.framecount = 0
self.atframeheader = 1
+ self.eofseen = 0
+ self.errorseen = 0
def warmcache(self):
- pass
+ print '[BasicVinFile.warmcache() not implemented]'
def printinfo(self):
print 'File: ', self.filename
@@ -598,24 +704,36 @@ class BasicVinFile(VideoParams):
return t
def getnextframeheader(self):
+ if self.eofseen: raise EOFError
+ if self.errorseen: raise CallError
if not self.atframeheader: raise CallError
self.atframeheader = 0
try:
return self._readframeheader(self.fp)
except Error, msg:
+ self.errorseen = 1
# Patch up the error message
raise Error, self.filename + ': ' + msg
+ except EOFError:
+ self.eofseen = 1
+ raise EOFError
def getnextframedata(self, ds, cs):
+ if self.eofseen: raise EOFError
+ if self.errorseen: raise CallError
if self.atframeheader: raise CallError
if ds:
data = self.fp.read(ds)
- if len(data) < ds: raise EOFError
+ if len(data) < ds:
+ self.eofseen = 1
+ raise EOFError
else:
data = ''
if cs:
cdata = self.fp.read(cs)
- if len(cdata) < cs: raise EOFerror
+ if len(cdata) < cs:
+ self.eofseen = 1
+ raise EOFError
else:
cdata = ''
self.atframeheader = 1
@@ -623,6 +741,8 @@ class BasicVinFile(VideoParams):
return (data, cdata)
def skipnextframedata(self, ds, cs):
+ if self.eofseen: raise EOFError
+ if self.errorseen: raise CallError
if self.atframeheader: raise CallError
# Note that this won't raise EOFError for a partial frame
# since there is no easy way to tell whether a seek
@@ -636,6 +756,70 @@ class BasicVinFile(VideoParams):
self.framecount = self.framecount + 1
+# Derived class implementing random access
+
+class RandomVinFile(BasicVinFile):
+
+ def initfp(self, fp, filename):
+ self = BasicVinFile.initfp(self, fp, filename)
+ self.index = []
+ return self
+
+ def warmcache(self):
+ if len(self.index) == 0:
+ self.rewind()
+ while 1:
+ try: dummy = self.skipnextframe()
+ except EOFError: break
+ else:
+ print '[RandomVinFile.warmcache(): too late]'
+ self.rewind()
+
+ def getnextframeheader(self):
+ if self.framecount < len(self.index):
+ return self._getindexframeheader(self.framecount)
+ if self.framecount > len(self.index):
+ raise AssertError, \
+ 'managed to bypass index?!?'
+ rv = BasicVinFile.getnextframeheader(self)
+ if self.canseek:
+ pos = self.fp.tell()
+ self.index.append(rv, pos)
+ return rv
+
+ def getrandomframe(self, i):
+ t, ds, cs = self.getrandomframeheader(i)
+ data, cdata = self.getnextframedata()
+ return t, ds, cs
+
+ def getrandomframeheader(self, i):
+ if i < 0: raise ValueError, 'negative frame index'
+ if not self.canseek:
+ raise Error, self.filename + ': can\'t seek'
+ if i < len(self.index):
+ return self._getindexframeheader(i)
+ if len(self.index) > 0:
+ rv = self.getrandomframeheader(len(self.index)-1)
+ else:
+ self.rewind()
+ rv = self.getnextframeheader()
+ while i > self.framecount:
+ self.skipnextframedata()
+ rv = self.getnextframeheader()
+ return rv
+
+ def _getindexframeheader(self, i):
+ (rv, pos) = self.index[i]
+ self.fp.seek(pos)
+ self.framecount = i
+ self.atframeheader = 0
+ self.eofseen = 0
+ self.errorseen = 0
+ return rv
+
+
+# Basic class for writing CMIF video files
+
class BasicVoutFile(VideoParams):
def init(self, filename):
@@ -649,7 +833,7 @@ class BasicVoutFile(VideoParams):
self = VideoParams.init(self)
self.fp = fp
self.filename = filename
- self.version = 3.0 # In case anyone inquires
+ self.version = 3.0 # In case anyone inquries
self.headerwritten = 0
return self
@@ -692,7 +876,10 @@ class BasicVoutFile(VideoParams):
def writeframeheader(self, t, ds, cs):
if not self.headerwritten: self.writeheader()
if not self.atheader: raise CallError
- self.fp.write(`(t, ds, cs)` + '\n')
+ data = `(t, ds, cs)`
+ n = len(data)
+ if n < 63: data = data + ' '*(63-n)
+ self.fp.write(data + '\n')
self.atheader = 0
def writeframedata(self, data, cdata):
@@ -705,11 +892,11 @@ class BasicVoutFile(VideoParams):
# Classes that combine files with displayers and/or grabbers:
-class VinFile(BasicVinFile, Displayer):
+class VinFile(RandomVinFile, Displayer):
def initfp(self, fp, filename):
self = Displayer.init(self)
- return BasicVinFile.initfp(self, fp, filename)
+ return RandomVinFile.initfp(self, fp, filename)
def shownextframe(self):
t, data, cdata = self.getnextframe()
@@ -739,8 +926,9 @@ def test():
vin.initcolormap()
t0 = time.millitimer()
while 1:
- try: t = vin.shownextframe()
+ try: t, data, cdata = vin.getnextframe()
except EOFError: break
dt = t0 + t - time.millitimer()
if dt > 0: time.millisleep(dt)
+ vin.showframe(data, cdata)
time.sleep(2)