pipasgrey 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #!/usr/bin/env python
  2. # $URL: http://pypng.googlecode.com/svn/trunk/code/pipasgrey $
  3. # $Rev: 187 $
  4. # pipasgrey
  5. # Convert image to grey (L, or LA), but only if that involves no colour
  6. # change.
  7. def asgrey(out, inp, quiet=False):
  8. """Convert image to greyscale, but only when no colour change. This
  9. works by using the input G channel (green) as the output L channel
  10. (luminance) and checking that every pixel is grey as we go. A non-grey
  11. pixel will raise an error, but if `quiet` is true then the grey pixel
  12. check is suppressed.
  13. """
  14. from array import array
  15. import png
  16. r = png.Reader(file=inp)
  17. _,_,pixels,info = r.asDirect()
  18. if info['greyscale']:
  19. w = png.Writer(**info)
  20. return w.write(out, pixels)
  21. planes = info['planes']
  22. targetplanes = planes - 2
  23. alpha = info['alpha']
  24. width = info['size'][0]
  25. typecode = 'BH'[info['bitdepth'] > 8]
  26. # Values per target row
  27. vpr = width * (targetplanes)
  28. def iterasgrey():
  29. for i,row in enumerate(pixels):
  30. row = array(typecode, row)
  31. targetrow = array(typecode, [0]*vpr)
  32. # Copy G (and possibly A) channel.
  33. green = row[0::planes]
  34. if alpha:
  35. targetrow[0::2] = green
  36. targetrow[1::2] = row[3::4]
  37. else:
  38. targetrow = green
  39. # Check R and B channel match.
  40. if not quiet and (
  41. green != row[0::planes] or green != row[2::planes]):
  42. raise ValueError('Row %i contains non-grey pixel.' % i)
  43. yield targetrow
  44. info['greyscale'] = True
  45. del info['planes']
  46. w = png.Writer(**info)
  47. w.write(out, iterasgrey())
  48. def main(argv=None):
  49. from getopt import getopt
  50. import sys
  51. if argv is None:
  52. argv = sys.argv
  53. argv = argv[1:]
  54. opt,argv = getopt(argv, 'q')
  55. quiet = False
  56. for o,v in opt:
  57. if o == '-q':
  58. quiet = True
  59. if len(argv) > 0:
  60. f = open(argv[0], 'rb')
  61. else:
  62. f = sys.stdin
  63. return asgrey(sys.stdout, f, quiet)
  64. if __name__ == '__main__':
  65. main()