1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh#! /usr/bin/env python 2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""Test script for the imageop module. This has the side 4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh effect of partially testing the imgfile module as well. 5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Roger E. Masse 6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh""" 7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom test.test_support import verbose, unlink, import_module, run_unittest 9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimageop = import_module('imageop', deprecated=True) 11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport uu, os, unittest 12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehSIZES = (1, 2, 3, 4) 15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh_VALUES = (1, 2, 2**10, 2**15-1, 2**15, 2**15+1, 2**31-2, 2**31-1) 16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehVALUES = tuple( -x for x in reversed(_VALUES) ) + (0,) + _VALUES 17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehAAAAA = "A" * 1024 18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehMAX_LEN = 2**20 19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass InputValidationTests(unittest.TestCase): 22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _check(self, name, size=None, *extra): 24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh func = getattr(imageop, name) 25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for height in VALUES: 26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for width in VALUES: 27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh strlen = abs(width * height) 28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if size: 29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh strlen *= size 30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if strlen < MAX_LEN: 31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh data = "A" * strlen 32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh data = AAAAA 34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if size: 35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh arguments = (data, size, width, height) + extra 36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh arguments = (data, width, height) + extra 38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh func(*arguments) 40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except (ValueError, imageop.error): 41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def check_size(self, name, *extra): 44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for size in SIZES: 45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self._check(name, size, *extra) 46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def check(self, name, *extra): 48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self._check(name, None, *extra) 49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def test_input_validation(self): 51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check_size("crop", 0, 0, 0, 0) 52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check_size("scale", 1, 0) 53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check_size("scale", -1, -1) 54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check_size("tovideo") 55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check("grey2mono", 128) 56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check("grey2grey4") 57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check("grey2grey2") 58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check("dither2mono") 59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check("dither2grey2") 60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check("mono2grey", 0, 0) 61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check("grey22grey") 62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check("rgb2rgb8") # nlen*4 == len 63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check("rgb82rgb") 64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check("rgb2grey") 65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.check("grey2rgb") 66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef test_main(): 69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh run_unittest(InputValidationTests) 71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import imgfile 74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except ImportError: 75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Create binary test files 78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh uu.decode(get_qualified_path('testrgb'+os.extsep+'uue'), 'test'+os.extsep+'rgb') 79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh image, width, height = getimage('test'+os.extsep+'rgb') 81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Return the selected part of image, which should by width by height 83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # in size and consist of pixels of psize bytes. 84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'crop' 86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh newimage = imageop.crop (image, 4, width, height, 0, 0, 1, 1) 87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Return image scaled to size newwidth by newheight. No interpolation 89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # is done, scaling is done by simple-minded pixel duplication or removal. 90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Therefore, computer-generated images or dithered images will 91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # not look nice after scaling. 92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'scale' 94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh scaleimage = imageop.scale(image, 4, width, height, 1, 1) 95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Run a vertical low-pass filter over an image. It does so by computing 97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # each destination pixel as the average of two vertically-aligned source 98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # pixels. The main use of this routine is to forestall excessive flicker 99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # if the image two vertically-aligned source pixels, hence the name. 100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'tovideo' 102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh videoimage = imageop.tovideo (image, 4, width, height) 103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert an rgb image to an 8 bit rgb 105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'rgb2rgb8' 107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh greyimage = imageop.rgb2rgb8(image, width, height) 108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert an 8 bit rgb image to a 24 bit rgb image 110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'rgb82rgb' 112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh image = imageop.rgb82rgb(greyimage, width, height) 113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert an rgb image to an 8 bit greyscale image 115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'rgb2grey' 117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh greyimage = imageop.rgb2grey(image, width, height) 118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert an 8 bit greyscale image to a 24 bit rgb image 120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'grey2rgb' 122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh image = imageop.grey2rgb(greyimage, width, height) 123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert a 8-bit deep greyscale image to a 1-bit deep image by 125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # thresholding all the pixels. The resulting image is tightly packed 126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # and is probably only useful as an argument to mono2grey. 127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'grey2mono' 129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh monoimage = imageop.grey2mono (greyimage, width, height, 0) 130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # monoimage, width, height = getimage('monotest.rgb') 132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert a 1-bit monochrome image to an 8 bit greyscale or color image. 133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # All pixels that are zero-valued on input get value p0 on output and 134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # all one-value input pixels get value p1 on output. To convert a 135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # monochrome black-and-white image to greyscale pass the values 0 and 136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 255 respectively. 137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'mono2grey' 139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh greyimage = imageop.mono2grey (monoimage, width, height, 0, 255) 140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert an 8-bit greyscale image to a 1-bit monochrome image using a 142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # (simple-minded) dithering algorithm. 143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'dither2mono' 145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh monoimage = imageop.dither2mono (greyimage, width, height) 146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert an 8-bit greyscale image to a 4-bit greyscale image without 148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # dithering. 149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'grey2grey4' 151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh grey4image = imageop.grey2grey4 (greyimage, width, height) 152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert an 8-bit greyscale image to a 2-bit greyscale image without 154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # dithering. 155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'grey2grey2' 157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh grey2image = imageop.grey2grey2 (greyimage, width, height) 158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert an 8-bit greyscale image to a 2-bit greyscale image with 160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # dithering. As for dither2mono, the dithering algorithm is currently 161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # very simple. 162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'dither2grey2' 164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh grey2image = imageop.dither2grey2 (greyimage, width, height) 165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert a 4-bit greyscale image to an 8-bit greyscale image. 167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'grey42grey' 169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh greyimage = imageop.grey42grey (grey4image, width, height) 170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Convert a 2-bit greyscale image to an 8-bit greyscale image. 172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'grey22grey' 174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh image = imageop.grey22grey (grey2image, width, height) 175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Cleanup 177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh unlink('test'+os.extsep+'rgb') 178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef getimage(name): 180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """return a tuple consisting of 181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh image (in 'imgfile' format) width and height 182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import imgfile 184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sizes = imgfile.getsizes(name) 186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except imgfile.error: 187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh name = get_qualified_path(name) 188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sizes = imgfile.getsizes(name) 189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if verbose: 190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'imgfile opening test image: %s, sizes: %s' % (name, str(sizes)) 191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh image = imgfile.read(name) 193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return (image, sizes[0], sizes[1]) 194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef get_qualified_path(name): 196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ return a more qualified path to name""" 197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import sys 198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import os 199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh path = sys.path 200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh path = [os.path.dirname(__file__)] + path 202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except NameError: 203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for dir in path: 205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fullname = os.path.join(dir, name) 206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if os.path.exists(fullname): 207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return fullname 208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return name 209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == '__main__': 211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh test_main() 212