Commit 5e044b70 authored by Guido van Rossum's avatar Guido van Rossum

- Separated grabbing (which isn't used much!) from VFile.

- Renamed old Vcopy.py to OldVcopy.py, some cosmetic changes to it (is
  it still needed?)
- Added new Vcopy.py which does everything that Vtime.py does but also
  format conversions, image scaling, and packfactors.
- VFile: make packfactor always a tuple; introduce set and get methods
  for pf, format, and calculate some derived values.
- Added new module GET.py to std library, use it instead of defining
  DM* in VFile.
- Get rid of C programs (new Python programs can do all that they do
  and they probably don't understand the current file format anyway).
parent b616ebe4
...@@ -59,9 +59,9 @@ Vtime.py Copy a video file, manipulating the time codes (e.g. ...@@ -59,9 +59,9 @@ Vtime.py Copy a video file, manipulating the time codes (e.g.
faster/slower, or regenerate time codes, or drop faster/slower, or regenerate time codes, or drop
frames too close apart) frames too close apart)
Vcopy.py selectively write frames from one movie file to another Vcopy.py Universal video file copying tool. Can manipulate the
usage: Vcopy [-t type] [-m treshold] [-a] infile outfile time codes, change the type, size, and packfactor.
commands: 'n' gets next frame; 'w' writes current frame Subsumes Vtime.py.
Vmkjpeg.py compress an rgb or grey video file to jpeg[grey] format Vmkjpeg.py compress an rgb or grey video file to jpeg[grey] format
......
This diff is collapsed.
# Class to grab frames from a window.
# (This has fewer user-settable parameters than Displayer.)
# It is the caller's responsibility to initialize the window and to
# ensure that it is current when using grabframe()
import gl, GL
import VFile
import GET
from VFile import Error
class VGrabber(VFile.VideoParams):
# XXX The init() method of VideoParams is just fine, for now
# Grab a frame.
# Return (data, chromdata) just like getnextframe().
def grabframe(self):
grabber = choose_grabber(self.format)
return grabber(self.width, self.height, self.packfactor)
# Choose one of the grabber functions below based upon a color system name
def choose_grabber(format):
try:
return eval('grab_' + format)
except:
raise Error, 'Unknown color system: ' + `format`
# Routines to grab data, per color system (only a few really supported).
# (These functions are used via eval with a constructed argument!)
def grab_rgb(w, h, pf):
if gl.getdisplaymode() <> GET.DMRGB:
raise Error, 'Sorry, can only grab rgb in single-buf rgbmode'
if pf <> (1, 1):
raise Error, 'Sorry, only grab rgb with packfactor (1,1)'
return gl.lrectread(0, 0, w-1, h-1), None
def grab_rgb8(w, h, pf):
if gl.getdisplaymode() <> GET.DMRGB:
raise Error, 'Sorry, can only grab rgb8 in single-buf rgbmode'
if pf <> (1, 1):
raise Error, 'Sorry, can only grab rgb8 with packfactor (1,1)'
if not VFile.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.
gl.cmode()
gl.gconfig()
gl.pixmode(GL.PM_SIZE, 8)
data = gl.lrectread(0, 0, w-1, h-1)
data = data[:w*h] # BUG FIX for python lrectread
gl.RGBmode()
gl.gconfig()
gl.pixmode(GL.PM_SIZE, 32)
return data, None
def grab_grey(w, h, pf):
raise Error, 'Sorry, grabbing grey not implemented'
def grab_yiq(w, h, pf):
raise Error, 'Sorry, grabbing yiq not implemented'
def grab_hls(w, h, pf):
raise Error, 'Sorry, grabbing hls not implemented'
def grab_hsv(w, h, pf):
raise Error, 'Sorry, grabbing hsv not implemented'
def grab_jpeg(w, h, pf):
# XXX Ought to grab rgb and compress it
raise Error, 'sorry, grabbing jpeg not implemented'
def grab_jpeggrey(w, h, pf):
raise Error, 'sorry, grabbing jpeggrey not implemented'
# Copy a video file, interactively, frame-by-frame. #! /ufs/guido/bin/sgi/python
# Universal (non-interactive) CMIF video file copier.
# Possibilities:
#
# - Manipulate the time base:
# = resample at a fixed rate
# = divide the time codes by a speed factor (to make it go faster/slower)
# = drop frames that are less than n msec apart (to accomodate slow players)
# - Convert to a different format
# - Magnify (scale) the image
# Usage function (keep this up-to-date if you change the program!)
def usage():
print 'Usage: Vcopy [options] [infile [outfile]]'
print
print 'Options:'
print
print '-t type : new image type (default unchanged)'
print
print '-M magnify : image magnification factor (default unchanged)'
print '-w width : output image width (default height*4/3 if -h used)'
print '-h height : output image height (default width*3/4 if -w used)'
print
print '-p pf : new x and y packfactor (default unchanged)'
print '-x xpf : new x packfactor (default 1 if -y used)'
print '-y ypf : new y packfactor (default 1 if -x used)'
print
print '-m delta : drop frames closer than delta msec (default 0)'
print '-r delta : regenerate input time base delta msec apart'
print '-s speed : speed change factor (default unchanged)'
print
print 'infile : input file (default film.video)'
print 'outfile : output file (default out.video)'
import sys import sys
import getopt sys.path.append('/ufs/guido/src/video')
from gl import *
from DEVICE import *
import VFile import VFile
import string import imgconv
import imageop import imageop
import getopt
import string
def report(time, iframe):
print 'Frame', iframe, ': t =', time
def usage(): # Global options
sys.stderr.write('usage: Vcopy [-t type] [-m treshold] [-a] infile outfile\n')
sys.stderr.write('-t Convert to other type\n') speed = 1.0
sys.stderr.write('-a Automatic\n') mindelta = 0
sys.stderr.write('-m Convert grey to mono with treshold\n') regen = None
sys.stderr.write('-d Convert grey to mono with dithering\n') newpf = None
sys.exit(2) newtype = None
magnify = None
def help(): newwidth = None
print 'Command summary:' newheight = None
print 'n get next image from input'
print 'w write current image to output'
# Function to turn a string into a float
atof_error = 'atof_error' # Exception if it fails
def atof(s):
try:
return float(eval(s))
except:
raise atof_error
# Main program -- mostly command line parsing
def main(): def main():
foreground() global speed, mindelta, regen, newpf, newtype, \
opts, args = getopt.getopt(sys.argv[1:], 't:am:d') magnify, newwidth, newheight
if len(args) <> 2:
# Parse command line
try:
opts, args = getopt.getopt(sys.argv[1:], \
'M:h:m:p:r:s:t:w:x:y:')
except getopt.error, msg:
sys.stdout = sys.stderr
print 'Error:', msg, '\n'
usage() usage()
[ifile, ofile] = args sys.exit(2)
print 'open film ', ifile
ifilm = VFile.VinFile().init(ifile) xpf = ypf = None
print 'open output ', ofile
ofilm = VFile.VoutFile().init(ofile)
ofilm.setinfo(ifilm.getinfo()) # Interpret options
try:
use_grabber = 0 for opt, arg in opts:
continuous = 0 if opt == '-M': magnify = atof(arg)
tomono = 0 if opt == '-h': height = string.atoi(arg)
tomonodither = 0 if opt == '-m': mindelta = string.atoi(arg)
for o, a in opts: if opt == '-p': xpf = ypf = string.atoi(arg)
if o == '-t': if opt == '-r': regen = string.atoi(arg)
ofilm.format = a if opt == '-s': speed = atof(arg)
use_grabber = 1 if opt == '-t': newtype = arg
if o == '-a': if opt == '-w': newwidth = string.atoi(arg)
continuous = 1 if opt == '-x': xpf = string.atoi(arg)
if o == '-m': if opt == '-y': ypf = string.atoi(arg)
if ifilm.format <> 'grey': except string.atoi_error:
print '-m only supported for greyscale' sys.stdout = sys.stderr
sys.exit(1) print 'Option', opt, 'requires integer argument'
tomono = 1 sys.exit(2)
treshold = string.atoi(a) except atof_error:
ofilm.format = 'mono' sys.stdout = sys.stderr
if o == '-d': print 'Option', opt, 'requires float argument'
if ifilm.format <> 'grey': sys.exit(2)
print '-m only supported for greyscale'
sys.exit(1) if xpf or ypf:
tomonodither = 1 if not xpf: xpf = 1
ofilm.format = 'mono' if not ypf: ypf = 1
newpf = (xpf, ypf)
ofilm.writeheader()
# if newwidth or newheight:
prefsize(ifilm.width, ifilm.height) if magnify:
w = winopen(ifile) sys.stdout = sys.stderr
qdevice(KEYBD) print 'Options -w or -h are incompatible with -M'
qdevice(ESCKEY) sys.exit(2)
qdevice(WINQUIT) if not newheight:
qdevice(WINSHUT) newheight = newwidth * 3 / 4
print 'qdevice calls done' elif not newwidth:
# newwidth = newheight * 4 / 3
help()
# # Check filename arguments
time, data, cdata = ifilm.getnextframe() if len(args) < 1:
ifilm.showframe(data, cdata) args.append('film.video')
iframe = 1 if len(args) < 2:
report(time, iframe) args.append('out.video')
# if len(args) > 2:
usage()
sys.exit(2)
if args[0] == args[1]:
sys.stderr.write('Input file can\'t be output file\n')
sys.exit(2)
# Do the right thing
sts = process(args[0], args[1])
# Exit
sys.exit(sts)
# Copy one file to another
def process(infilename, outfilename):
global newwidth, newheight
try:
vin = VFile.BasicVinFile().init(infilename)
except IOError, msg:
sys.stderr.write(infilename + ': I/O error: ' + `msg` + '\n')
return 1
except VFile.Error, msg:
sys.stderr.write(msg + '\n')
return 1
except EOFError:
sys.stderr.write(infilename + ': EOF in video file\n')
return 1
try:
vout = VFile.BasicVoutFile().init(outfilename)
except IOError, msg:
sys.stderr.write(outfilename + ': I/O error: ' + `msg` + '\n')
return 1
vout.setinfo(vin.getinfo())
scale = 0
flip = 0
if newtype:
vout.setformat(newtype)
try:
convert = imgconv.getconverter(vin.format, vout.format)
except imgconv.error, msg:
sys.stderr.write(str(msg) + '\n')
return 1
if newpf:
vout.setpf(newpf)
scale = 1
if newwidth and newheight:
scale = 1
if vin.upside_down <> vout.upside_down or \
vin.mirror_image <> vout.mirror_image:
flip = 1
inwidth, inheight = vin.getsize()
inwidth = inwidth / vin.xpf
inheight = inheight / vin.ypf
if magnify:
newwidth = int(vout.width * magnify)
newheight = int(vout.height * magnify)
scale = 1
if scale:
vout.setsize(newwidth, newheight)
else:
newwidth, newheight = vout.getsize()
if vin.packfactor <> vout.packfactor:
scale = 1
if scale or flip:
if vout.bpp not in (8, 32):
sys.stderr.write('Can\'t scale or flip this type\n')
return 1
newwidth = newwidth / vout.xpf
newheight = newheight / vout.ypf
vout.writeheader()
told = 0
nin = 0
nout = 0
tin = 0
tout = 0
while 1: while 1:
if continuous: try:
dev = KEYBD tin, data, cdata = vin.getnextframe()
else: except EOFError:
dev, val = qread()
if dev in (ESCKEY, WINQUIT, WINSHUT):
break break
if dev == REDRAW: nin = nin + 1
reshapeviewport() if regen:
elif dev == KEYBD: tout = nin * regen
if continuous:
c = '0'
else:
c = chr(val)
#XXX Debug
if c == 'R':
c3i(255,0,0)
clear()
if c == 'G':
c3i(0,255,0)
clear()
if c == 'B':
c3i(0,0,255)
clear()
if c == 'w' or continuous:
if use_grabber:
data, cdata = ofilm.grabframe()
if tomono:
data = imageop.grey2mono(data, \
ifilm.width, ifilm.height, \
treshold)
if tomonodither:
data = imageop.dither2mono(data, \
ifilm.width, ifilm.height)
ofilm.writeframe(time, data, cdata)
print 'Frame', iframe, 'written.'
if c == 'n' or continuous:
try:
time,data,cdata = ifilm.getnextframe()
ifilm.showframe(data, cdata)
iframe = iframe+1
report(time, iframe)
except EOFError:
print 'EOF'
if continuous:
break
ringbell()
elif dev == INPUTCHANGE:
pass
else: else:
print '(dev, val) =', (dev, val) tout = tin
ofilm.close() tout = int(tout / speed)
if tout - told < mindelta:
continue
told = tout
if newtype:
data = convert(data, inwidth, inheight)
if newwidth and newheight:
data = imageop.scale(data, vout.bpp/8, \
inwidth, inheight, newwidth, newheight)
if vin.upside_down <> vout.upside_down or \
vin.mirror_image <> vout.mirror_image:
x0, y0 = 0, 0
x1, y1 = newwidth-1, neheight-1
if vin.upside_down <> vout.upside_down:
y1, y0 = y0, y1
if vin.mirror_image <> vout.mirror_image:
x1, x0 = x0, x1
data = imageop.crop(data, vout.bpp/8, \
newwidth, newheight, x0, y0, x1, y1)
vout.writeframe(tout, data, cdata)
nout = nout + 1
vout.close()
vin.close()
# Don't forget to call the main program
main() try:
main()
except KeyboardInterrupt:
print '[Interrupt]'
...@@ -22,7 +22,7 @@ def rgb2jpeg(img, x, y): ...@@ -22,7 +22,7 @@ def rgb2jpeg(img, x, y):
def jpeggrey2grey(img, width, height): def jpeggrey2grey(img, width, height):
import jpeg import jpeg
data, width, height, bytesperpixel = jpeg.decompress(img) data, width, height, bytesperpixel = jpeg.decompress(img)
if bytesperpixel <> 1: raise RuntimeError, 'not grayscale jpeg' if bytesperpixel <> 1: raise RuntimeError, 'not greyscale jpeg'
return data return data
def jpeg2rgb(img, width, height): def jpeg2rgb(img, width, height):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment