Added mono, grey2 and grey4 formats
diff --git a/Demo/sgi/video/VFile.py b/Demo/sgi/video/VFile.py
index 5c05ed0..3d2bd8c 100755
--- a/Demo/sgi/video/VFile.py
+++ b/Demo/sgi/video/VFile.py
@@ -22,6 +22,7 @@
import gl
import GL
import colorsys
+import imageop
# Exception raised for various occasions
@@ -50,6 +51,12 @@
def conv_grey(l, x, y):
return colorsys.yiq_to_rgb(l, 0, 0)
+def conv_grey4(l, x, y):
+ return colorsys.yiq_to_rgb(l*17, 0, 0)
+
+def conv_mono(l, x, y):
+ return colorsys.yiq_to_rgb(l*255, 0, 0)
+
def conv_yiq(y, i, q):
return colorsys.yiq_to_rgb(y, (i-0.5)*1.2, q-0.5)
@@ -73,7 +80,7 @@
raise Error, 'Attempt to make RGB colormap (jpeg)'
conv_jpeggrey = conv_grey
-conv_mono = conv_grey
+conv_grey2 = conv_grey
# Choose one of the above based upon a color system name
@@ -144,6 +151,15 @@
b = gl.getgdesc(GL.GD_BITS_NORM_SNG_BLUE)
return (r, g, b) == (3, 3, 2)
+#
+# Predicate function to see whether this machine supports pixmode(PM_SIZE)
+# with values 1 or 4.
+#
+# XXX Temporarily disabled, since it is unclear which machines support
+# XXX which pixelsizes.
+#
+def support_packed_pixels():
+ return 0 # To be architecture-dependent
# Routines to grab data, per color system (only a few really supported).
# (These functions are used via eval with a constructed argument!)
@@ -215,7 +231,7 @@
# Essential parameters
self.format = 'grey' # color system used
# Choose from: grey, rgb, rgb8, hsv, yiq, hls, jpeg, jpeggrey,
- # mono
+ # mono, grey2, grey4
self.width = 0 # width of frame
self.height = 0 # height of frame
self.packfactor = 1 # expansion using rectzoom
@@ -264,6 +280,26 @@
print 'Bits: ', self.c0bits, self.c1bits, self.c2bits
print 'Offset: ', self.offset
+ # Calculate data size, if possible
+ def calcframesize(self):
+ if self.format == 'rgb':
+ return self.width*self.height*4
+ if self.format in ('jpeg', 'jpeggrey'):
+ raise CallError
+ if type(self.packfactor) == type(()):
+ xpf, ypf = self.packfactor
+ else:
+ xpf = ypf = self.packfactor
+ if ypf < 0: ypf = -ypf
+ size = (self.width/xpf)*(self.height/ypf)
+ if self.format == 'grey4':
+ size = (size+1)/2
+ elif self.format == 'grey2':
+ size = (size+3)/4
+ elif self.format == 'mono':
+ size = (size+7)/8
+ return size
+
# Class to display video frames in a window.
# It is the caller's responsibility to ensure that the correct window
@@ -287,6 +323,7 @@
self.skipchrom = 0 # don't skip chrominance data
self.color0 = None # magic, used by clearto()
self.fixcolor0 = 0 # don't need to fix color0
+ self.mustunpack = (not support_packed_pixels())
return self
# setinfo() must reset some internal flags
@@ -306,34 +343,65 @@
def showpartframe(self, data, chromdata, (x,y,w,h)):
pf = self.packfactor
+ pmsize = 8
+ if pf:
+ if type(pf) == type(()):
+ xpf, ypf = pf
+ else:
+ xpf = ypf = pf
+ if ypf < 0:
+ gl.pixmode(GL.PM_TTOB, 1)
+ ypf = -ypf
+ if xpf < 0:
+ gl.pixmode(GL.PM_RTOL, 1)
+ xpf = -xpf
+ else:
+ xpf = ypf = 1
if self.format in ('jpeg', 'jpeggrey'):
import jpeg
data, width, height, bytes = jpeg.decompress(data)
if self.format == 'jpeg':
b = 4
- p = 1
+ xp = yp = 1
else:
b = 1
- p = pf
- if (width, height, bytes) <> (w/p, h/p, b):
+ xp = xpf
+ yp = ypf
+ if (width, height, bytes) <> (w/xp, h/yp, b):
raise Error, 'jpeg data has wrong size'
- elif self.format == 'mono':
- import imageop
- data = imageop.mono2grey(data, w, h, 0x20, 0xdf)
+ elif self.format in ('mono', 'grey4'):
+ if self.mustunpack:
+ if self.format == 'mono':
+ data = imageop.mono2grey(data, \
+ w/xpf, h/ypf, 0x20, 0xdf)
+ elif self.format == 'grey4':
+ data = imageop.grey42grey(data, \
+ w/xpf, h/ypf)
+ else:
+ # We don't need to unpack, the hardware
+ # can do it.
+ if self.format == 'mono':
+ pmsize = 1
+ else:
+ pmsize = 4
+ elif self.format == 'grey2':
+ data = imageop.grey22grey(data, w/xpf, h/ypf)
if not self.colormapinited:
self.initcolormap()
if self.fixcolor0:
gl.mapcolor(self.color0)
self.fixcolor0 = 0
- factor = self.magnify
- if pf: factor = factor * pf
+ xfactor = yfactor = self.magnify
+ if pf:
+ xfactor = xfactor * xpf
+ yfactor = yfactor * ypf
if chromdata and not self.skipchrom:
cp = self.chrompack
- cx = int(x*factor*cp) + self.xorigin
- cy = int(y*factor*cp) + self.yorigin
+ cx = int(x*xfactor*cp) + self.xorigin
+ cy = int(y*yfactor*cp) + self.yorigin
cw = (w+cp-1)/cp
ch = (h+cp-1)/cp
- gl.rectzoom(factor*cp, factor*cp)
+ gl.rectzoom(xfactor*cp, yfactor*cp)
gl.pixmode(GL.PM_SIZE, 16)
gl.writemask(self.mask - ((1 << self.c0bits) - 1))
gl.lrectwrite(cx, cy, cx + cw - 1, cy + ch - 1, \
@@ -341,14 +409,14 @@
#
if pf:
gl.writemask((1 << self.c0bits) - 1)
- gl.pixmode(GL.PM_SIZE, 8)
- w = w/pf
- h = h/pf
- x = x/pf
- y = y/pf
- gl.rectzoom(factor, factor)
- x = int(x*factor)+self.xorigin
- y = int(y*factor)+self.yorigin
+ gl.pixmode(GL.PM_SIZE, pmsize)
+ w = w/xpf
+ h = h/ypf
+ x = x/xpf
+ y = y/ypf
+ gl.rectzoom(xfactor, yfactor)
+ x = int(x*xfactor)+self.xorigin
+ y = int(y*yfactor)+self.yorigin
gl.lrectwrite(x, y, x + w - 1, y + h - 1, data)
gl.gflush()
@@ -422,7 +490,10 @@
# by clear() and clearto()
def _initcmap(self):
- convcolor = choose_conversion(self.format)
+ if self.format in ('mono', 'grey4') and self.mustunpack:
+ convcolor = conv_grey
+ else:
+ convcolor = choose_conversion(self.format)
maxbits = gl.getgdesc(GL.GD_BITS_NORM_SNG_CMODE)
if maxbits > 11:
maxbits = 11
@@ -496,7 +567,7 @@
# Read a CMIF video file header.
-# Return (version, values) where version is 0.0, 1.0, 2.0 or 3.0,
+# Return (version, values) where version is 0.0, 1.0, 2.0 or 3.[01],
# and values is ready for setinfo().
# Raise Error if there is an error in the info
@@ -513,6 +584,8 @@
version = 2.0
elif line == 'CMIF video 3.0\n':
version = 3.0
+ elif line == 'CMIF video 3.1\n':
+ version = 3.1
else:
# XXX Could be version 0.0 without identifying header
raise Error, \
@@ -537,19 +610,19 @@
else:
format = 'grey'
offset = 0
- elif version == 3.0:
+ elif version in (3.0, 3.1):
line = fp.readline()
try:
format, rest = eval(line[:-1])
except:
- raise Error, filename + ': Bad 3.0 color info'
+ raise Error, filename + ': Bad 3.[01] color info'
if format == 'xrgb8':
format = 'rgb8' # rgb8 upside-down, for X
if format in ('rgb', 'jpeg'):
c0bits = c1bits = c2bits = 0
chrompack = 0
offset = 0
- elif format in ('grey', 'jpeggrey', 'mono'):
+ elif format in ('grey', 'jpeggrey', 'mono', 'grey2', 'grey4'):
c0bits = rest
c1bits = c2bits = 0
chrompack = 0
@@ -559,7 +632,7 @@
try:
c0bits, c1bits, c2bits, chrompack, offset = rest
except:
- raise Error, filename + ': Bad 3.0 color info'
+ raise Error, filename + ': Bad 3.[01] color info'
#
# Get frame geometry info
#
@@ -580,7 +653,13 @@
packfactor = 2
else:
raise Error, filename + ': Bad (w,h,pf) info'
- if packfactor > 1:
+ if type(packfactor) == type(()):
+ xpf, ypf = packfactor
+ xpf = abs(xpf)
+ ypf = abs(ypf)
+ width = (width/xpf) * xpf
+ height = (height/ypf) * ypf
+ elif packfactor > 1:
width = (width / packfactor) * packfactor
height = (height / packfactor) * packfactor
#
@@ -629,11 +708,11 @@
try:
t, datasize, chromdatasize = x = eval(line[:-1])
except:
- raise Error, 'Bad 3.0 frame header'
+ raise Error, 'Bad 3.[01] frame header'
return x
-# Write a CMIF video file header (always version 3.0)
+# Write a CMIF video file header (always version 3.1)
def writefileheader(fp, values):
(format, width, height, packfactor, \
@@ -641,13 +720,13 @@
#
# Write identifying header
#
- fp.write('CMIF video 3.0\n')
+ fp.write('CMIF video 3.1\n')
#
# Write color encoding info
#
if format in ('rgb', 'jpeg'):
data = (format, 0)
- elif format in ('grey', 'jpeggrey', 'mono'):
+ elif format in ('grey', 'jpeggrey', 'mono', 'grey2', 'grey4'):
data = (format, c0bits)
else:
data = (format, (c0bits, c1bits, c2bits, chrompack, offset))
@@ -691,7 +770,7 @@
self._readframeheader = readv1frameheader
elif self.version == 2.0:
self._readframeheader = readv2frameheader
- elif self.version == 3.0:
+ elif self.version in (3.0, 3.1):
self._readframeheader = readv3frameheader
else:
raise Error, \
@@ -950,6 +1029,14 @@
self.fp.close()
del self.fp
+ def prealloc(self, nframes):
+ if not self.headerwritten: raise CallError
+ data = '\xff' * self.calcframesize()
+ pos = self.fp.tell()
+ for i in range(nframes):
+ self.fp.write(data)
+ self.fp.seek(pos)
+
def setinfo(self, values):
if self.headerwritten: raise CallError
VideoParams.setinfo(self, values)