10c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi#! /usr/bin/env python 20c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 30c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi"""Test script for the imageop module. This has the side 40c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi effect of partially testing the imgfile module as well. 50c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi Roger E. Masse 60c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi""" 70c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 80c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yifrom test.test_support import verbose, unlink, import_module, run_unittest 90c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimageop = import_module('imageop', deprecated=True) 110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiimport uu, os, unittest 120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiSIZES = (1, 2, 3, 4) 150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi_VALUES = (1, 2, 2**10, 2**15-1, 2**15, 2**15+1, 2**31-2, 2**31-1) 160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiVALUES = tuple( -x for x in reversed(_VALUES) ) + (0,) + _VALUES 170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiAAAAA = "A" * 1024 180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill YiMAX_LEN = 2**20 190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiclass InputValidationTests(unittest.TestCase): 220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def _check(self, name, size=None, *extra): 240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi func = getattr(imageop, name) 250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for height in VALUES: 260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for width in VALUES: 270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi strlen = abs(width * height) 280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if size: 290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi strlen *= size 300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if strlen < MAX_LEN: 310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi data = "A" * strlen 320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi data = AAAAA 340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if size: 350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi arguments = (data, size, width, height) + extra 360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi else: 370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi arguments = (data, width, height) + extra 380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi func(*arguments) 400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except (ValueError, imageop.error): 410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def check_size(self, name, *extra): 440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for size in SIZES: 450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._check(name, size, *extra) 460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def check(self, name, *extra): 480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self._check(name, None, *extra) 490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi def test_input_validation(self): 510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check_size("crop", 0, 0, 0, 0) 520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check_size("scale", 1, 0) 530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check_size("scale", -1, -1) 540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check_size("tovideo") 550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check("grey2mono", 128) 560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check("grey2grey4") 570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check("grey2grey2") 580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check("dither2mono") 590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check("dither2grey2") 600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check("mono2grey", 0, 0) 610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check("grey22grey") 620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check("rgb2rgb8") # nlen*4 == len 630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check("rgb82rgb") 640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check("rgb2grey") 650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi self.check("grey2rgb") 660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef test_main(): 690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi run_unittest(InputValidationTests) 710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi import imgfile 740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except ImportError: 750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return 760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Create binary test files 780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi uu.decode(get_qualified_path('testrgb'+os.extsep+'uue'), 'test'+os.extsep+'rgb') 790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi image, width, height = getimage('test'+os.extsep+'rgb') 810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Return the selected part of image, which should by width by height 830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # in size and consist of pixels of psize bytes. 840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'crop' 860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi newimage = imageop.crop (image, 4, width, height, 0, 0, 1, 1) 870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Return image scaled to size newwidth by newheight. No interpolation 890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # is done, scaling is done by simple-minded pixel duplication or removal. 900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Therefore, computer-generated images or dithered images will 910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # not look nice after scaling. 920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'scale' 940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi scaleimage = imageop.scale(image, 4, width, height, 1, 1) 950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Run a vertical low-pass filter over an image. It does so by computing 970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # each destination pixel as the average of two vertically-aligned source 980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # pixels. The main use of this routine is to forestall excessive flicker 990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # if the image two vertically-aligned source pixels, hence the name. 1000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'tovideo' 1020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi videoimage = imageop.tovideo (image, 4, width, height) 1030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert an rgb image to an 8 bit rgb 1050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'rgb2rgb8' 1070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi greyimage = imageop.rgb2rgb8(image, width, height) 1080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert an 8 bit rgb image to a 24 bit rgb image 1100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'rgb82rgb' 1120c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi image = imageop.rgb82rgb(greyimage, width, height) 1130c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1140c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert an rgb image to an 8 bit greyscale image 1150c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1160c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'rgb2grey' 1170c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi greyimage = imageop.rgb2grey(image, width, height) 1180c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1190c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert an 8 bit greyscale image to a 24 bit rgb image 1200c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1210c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'grey2rgb' 1220c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi image = imageop.grey2rgb(greyimage, width, height) 1230c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1240c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert a 8-bit deep greyscale image to a 1-bit deep image by 1250c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # thresholding all the pixels. The resulting image is tightly packed 1260c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # and is probably only useful as an argument to mono2grey. 1270c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1280c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'grey2mono' 1290c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi monoimage = imageop.grey2mono (greyimage, width, height, 0) 1300c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1310c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # monoimage, width, height = getimage('monotest.rgb') 1320c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert a 1-bit monochrome image to an 8 bit greyscale or color image. 1330c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # All pixels that are zero-valued on input get value p0 on output and 1340c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # all one-value input pixels get value p1 on output. To convert a 1350c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # monochrome black-and-white image to greyscale pass the values 0 and 1360c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # 255 respectively. 1370c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1380c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'mono2grey' 1390c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi greyimage = imageop.mono2grey (monoimage, width, height, 0, 255) 1400c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1410c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert an 8-bit greyscale image to a 1-bit monochrome image using a 1420c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # (simple-minded) dithering algorithm. 1430c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1440c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'dither2mono' 1450c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi monoimage = imageop.dither2mono (greyimage, width, height) 1460c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1470c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert an 8-bit greyscale image to a 4-bit greyscale image without 1480c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # dithering. 1490c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1500c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'grey2grey4' 1510c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi grey4image = imageop.grey2grey4 (greyimage, width, height) 1520c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1530c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert an 8-bit greyscale image to a 2-bit greyscale image without 1540c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # dithering. 1550c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1560c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'grey2grey2' 1570c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi grey2image = imageop.grey2grey2 (greyimage, width, height) 1580c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1590c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert an 8-bit greyscale image to a 2-bit greyscale image with 1600c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # dithering. As for dither2mono, the dithering algorithm is currently 1610c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # very simple. 1620c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1630c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'dither2grey2' 1640c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi grey2image = imageop.dither2grey2 (greyimage, width, height) 1650c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1660c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert a 4-bit greyscale image to an 8-bit greyscale image. 1670c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1680c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'grey42grey' 1690c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi greyimage = imageop.grey42grey (grey4image, width, height) 1700c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1710c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Convert a 2-bit greyscale image to an 8-bit greyscale image. 1720c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1730c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'grey22grey' 1740c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi image = imageop.grey22grey (grey2image, width, height) 1750c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1760c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi # Cleanup 1770c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi unlink('test'+os.extsep+'rgb') 1780c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1790c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef getimage(name): 1800c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """return a tuple consisting of 1810c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi image (in 'imgfile' format) width and height 1820c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """ 1830c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi import imgfile 1840c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 1850c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sizes = imgfile.getsizes(name) 1860c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except imgfile.error: 1870c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi name = get_qualified_path(name) 1880c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi sizes = imgfile.getsizes(name) 1890c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if verbose: 1900c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi print 'imgfile opening test image: %s, sizes: %s' % (name, str(sizes)) 1910c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1920c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi image = imgfile.read(name) 1930c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return (image, sizes[0], sizes[1]) 1940c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 1950c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yidef get_qualified_path(name): 1960c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi """ return a more qualified path to name""" 1970c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi import sys 1980c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi import os 1990c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi path = sys.path 2000c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi try: 2010c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi path = [os.path.dirname(__file__)] + path 2020c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi except NameError: 2030c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi pass 2040c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi for dir in path: 2050c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi fullname = os.path.join(dir, name) 2060c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi if os.path.exists(fullname): 2070c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return fullname 2080c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi return name 2090c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi 2100c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yiif __name__ == '__main__': 2110c5958b1636c47ed7c284f859c8e805fd06a0e6Bill Yi test_main() 212