home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Demo / sgi / video / Vcopy.py < prev    next >
Text File  |  1996-11-27  |  7KB  |  292 lines

  1. #! /usr/bin/env python
  2.  
  3. # Universal (non-interactive) CMIF video file copier.
  4.  
  5.  
  6. # Possibilities:
  7. #
  8. # - Manipulate the time base:
  9. #   = resample at a fixed rate
  10. #   = divide the time codes by a speed factor (to make it go faster/slower)
  11. #   = drop frames that are less than n msec apart (to accomodate slow players)
  12. # - Convert to a different format
  13. # - Magnify (scale) the image
  14.  
  15.  
  16. # Usage function (keep this up-to-date if you change the program!)
  17.  
  18. def usage():
  19.     print 'Usage: Vcopy [options] [infile [outfile]]'
  20.     print
  21.     print 'Options:'
  22.     print
  23.     print '-t type    : new image type (default unchanged)'
  24.     print
  25.     print '-M magnify : image magnification factor (default unchanged)'
  26.     print '-w width   : output image width (default height*4/3 if -h used)'
  27.     print '-h height  : output image height (default width*3/4 if -w used)'
  28.     print
  29.     print '-p pf      : new x and y packfactor (default unchanged)'
  30.     print '-x xpf     : new x packfactor (default unchanged)'
  31.     print '-y ypf     : new y packfactor (default unchanged)'
  32.     print
  33.     print '-m delta   : drop frames closer than delta msec (default 0)'
  34.     print '-r delta   : regenerate input time base delta msec apart'
  35.     print '-s speed   : speed change factor (default unchanged)'
  36.     print
  37.     print 'infile     : input file (default film.video)'
  38.     print 'outfile    : output file (default out.video)'
  39.  
  40.  
  41. import sys
  42. sys.path.append('/ufs/guido/src/video')
  43.  
  44. import VFile
  45. import imgconv
  46. import imageop
  47. import getopt
  48. import string
  49.  
  50.  
  51. # Global options
  52.  
  53. speed = 1.0
  54. mindelta = 0
  55. regen = None
  56. newpf = None
  57. newtype = None
  58. magnify = None
  59. newwidth = None
  60. newheight = None
  61.  
  62.  
  63. # Function to turn a string into a float
  64.  
  65. atof_error = 'atof_error' # Exception if it fails
  66.  
  67. def atof(s):
  68.     try:
  69.         return float(eval(s))
  70.     except:
  71.         raise atof_error
  72.  
  73.  
  74. # Main program -- mostly command line parsing
  75.  
  76. def main():
  77.     global speed, mindelta, regen, newpf, newtype, \
  78.            magnify, newwidth, newheight
  79.  
  80.     # Parse command line
  81.     try:
  82.         opts, args = getopt.getopt(sys.argv[1:], \
  83.               'M:h:m:p:r:s:t:w:x:y:')
  84.     except getopt.error, msg:
  85.         sys.stdout = sys.stderr
  86.         print 'Error:', msg, '\n'
  87.         usage()
  88.         sys.exit(2)
  89.  
  90.     xpf = ypf = None
  91.     
  92.     # Interpret options
  93.     try:
  94.         for opt, arg in opts:
  95.             if opt == '-M': magnify = atof(arg)
  96.             if opt == '-h': height = string.atoi(arg)
  97.             if opt == '-m': mindelta = string.atoi(arg)
  98.             if opt == '-p': xpf = ypf = string.atoi(arg)
  99.             if opt == '-r': regen = string.atoi(arg)
  100.             if opt == '-s': speed = atof(arg)
  101.             if opt == '-t': newtype = arg
  102.             if opt == '-w': newwidth = string.atoi(arg)
  103.             if opt == '-x': xpf = string.atoi(arg)
  104.             if opt == '-y': ypf = string.atoi(arg)
  105.     except string.atoi_error:
  106.         sys.stdout = sys.stderr
  107.         print 'Option', opt, 'requires integer argument'
  108.         sys.exit(2)
  109.     except atof_error:
  110.         sys.stdout = sys.stderr
  111.         print 'Option', opt, 'requires float argument'
  112.         sys.exit(2)
  113.  
  114.     if xpf or ypf:
  115.         newpf = (xpf, ypf)
  116.  
  117.     if newwidth or newheight:
  118.         if magnify:
  119.             sys.stdout = sys.stderr
  120.             print 'Options -w or -h are incompatible with -M'
  121.             sys.exit(2)
  122.         if not newheight:
  123.             newheight = newwidth * 3 / 4
  124.         elif not newwidth:
  125.             newwidth = newheight * 4 / 3
  126.  
  127.     # Check filename arguments
  128.     if len(args) < 1:
  129.         args.append('film.video')
  130.     if len(args) < 2:
  131.         args.append('out.video')
  132.     if len(args) > 2:
  133.         usage()
  134.         sys.exit(2)
  135.     if args[0] == args[1]:
  136.         sys.stderr.write('Input file can\'t be output file\n')
  137.         sys.exit(2)
  138.  
  139.     # Do the right thing
  140.     sts = process(args[0], args[1])
  141.  
  142.     # Exit
  143.     sys.exit(sts)
  144.  
  145.  
  146. # Copy one file to another
  147.  
  148. def process(infilename, outfilename):
  149.     global newwidth, newheight, newpf
  150.  
  151.     try:
  152.         vin = VFile.BasicVinFile(infilename)
  153.     except IOError, msg:
  154.         sys.stderr.write(infilename + ': I/O error: ' + `msg` + '\n')
  155.         return 1
  156.     except VFile.Error, msg:
  157.         sys.stderr.write(msg + '\n')
  158.         return 1
  159.     except EOFError:
  160.         sys.stderr.write(infilename + ': EOF in video file\n')
  161.         return 1
  162.  
  163.     try:
  164.         vout = VFile.BasicVoutFile(outfilename)
  165.     except IOError, msg:
  166.         sys.stderr.write(outfilename + ': I/O error: ' + `msg` + '\n')
  167.         return 1
  168.  
  169.     print '=== input file ==='
  170.     vin.printinfo()
  171.  
  172.     vout.setinfo(vin.getinfo())
  173.  
  174.     scale = 0
  175.     flip = 0
  176.     decompress = 0
  177.  
  178.     vinfmt = vin.format
  179.     if vinfmt == 'compress':
  180.         if not newtype or newtype == 'compress':
  181.             # compressed->compressed: copy compression header
  182.             vout.setcompressheader(vin.getcompressheader())
  183.         else:
  184.             # compressed->something else: go via rgb-24
  185.             decompress = 1
  186.             vinfmt = 'rgb'
  187.     elif newtype == 'compress':
  188.         # something else->compressed: not implemented
  189.         sys.stderr.write('Sorry, conversion to compressed not yet implemented\n')
  190.         return 1
  191.     if newtype:
  192.         vout.setformat(newtype)
  193.         try:
  194.             convert = imgconv.getconverter(vinfmt, vout.format)
  195.         except imgconv.error, msg:
  196.             sys.stderr.write(str(msg) + '\n')
  197.             return 1
  198.  
  199.     if newpf:
  200.         xpf, ypf = newpf
  201.         if not xpf: xpf = vin.xpf
  202.         if not ypf: ypf = vout.ypf
  203.         newpf = (xpf, ypf)
  204.         vout.setpf(newpf)
  205.  
  206.     if newwidth and newheight:
  207.         scale = 1
  208.  
  209.     if vin.upside_down <> vout.upside_down or \
  210.           vin.mirror_image <> vout.mirror_image:
  211.         flip = 1
  212.  
  213.     inwidth, inheight = vin.getsize()
  214.     inwidth = inwidth / vin.xpf
  215.     inheight = inheight / vin.ypf
  216.  
  217.     if magnify:
  218.         newwidth = int(vout.width * magnify)
  219.         newheight = int(vout.height * magnify)
  220.         scale = 1
  221.  
  222.     if scale:
  223.         vout.setsize(newwidth, newheight)
  224.     else:
  225.         newwidth, newheight = vout.getsize()
  226.  
  227.     if vin.packfactor <> vout.packfactor:
  228.         scale = 1
  229.  
  230.     if scale or flip:
  231.         if vout.bpp not in (8, 32):
  232.             sys.stderr.write('Can\'t scale or flip this type\n')
  233.             return 1
  234.  
  235.     newwidth = newwidth / vout.xpf
  236.     newheight = newheight / vout.ypf
  237.  
  238.     print '=== output file ==='
  239.     vout.printinfo()
  240.     vout.writeheader()
  241.  
  242.     told = 0
  243.     nin = 0
  244.     nout = 0
  245.     tin = 0
  246.     tout = 0
  247.  
  248.     while 1:
  249.         try:
  250.             tin, data, cdata = vin.getnextframe()
  251.         except EOFError:
  252.             break
  253.         if decompress:
  254.             data = vin.decompress(data)
  255.         nin = nin + 1
  256.         if regen:
  257.             tout = nin * regen
  258.         else:
  259.             tout = tin
  260.         tout = int(tout / speed)
  261.         if tout - told < mindelta:
  262.             continue
  263.         told = tout
  264.         if newtype:
  265.             data = convert(data, inwidth, inheight)
  266.         if scale:
  267.             data = imageop.scale(data, vout.bpp/8, \
  268.                   inwidth, inheight, newwidth, newheight)
  269.         if flip:
  270.             x0, y0 = 0, 0
  271.             x1, y1 = newwidth-1, newheight-1
  272.             if vin.upside_down <> vout.upside_down:
  273.                 y1, y0 = y0, y1
  274.             if vin.mirror_image <> vout.mirror_image:
  275.                 x1, x0 = x0, x1
  276.             data = imageop.crop(data, vout.bpp/8, \
  277.                   newwidth, newheight, x0, y0, x1, y1)
  278.         print 'Writing frame', nout
  279.         vout.writeframe(tout, data, cdata)
  280.         nout = nout + 1
  281.  
  282.     vout.close()
  283.     vin.close()
  284.  
  285.  
  286. # Don't forget to call the main program
  287.  
  288. try:
  289.     main()
  290. except KeyboardInterrupt:
  291.     print '[Interrupt]'
  292.