diff options
Diffstat (limited to 'src/test/ImageTest.py')
-rw-r--r-- | src/test/ImageTest.py | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/src/test/ImageTest.py b/src/test/ImageTest.py new file mode 100644 index 0000000..f59d4ad --- /dev/null +++ b/src/test/ImageTest.py @@ -0,0 +1,583 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# libavg - Media Playback Engine. +# Copyright (C) 2003-2014 Ulrich von Zadow +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Current versions can be found at www.libavg.de +# + + +import shutil + +from libavg import avg, player +from testcase import * + +class ImageTestCase(AVGTestCase): + def __init__(self, testFuncName): + AVGTestCase.__init__(self, testFuncName) + + def testImageHRef(self): + def createXmlNode(pos): + node = player.createNode( + """<image pos="%s" href="rgb24-32x32.png"/>"""%str(pos)) + self.assertEqual(node.getMediaSize(), avg.Point2D(32, 32)) + return node + + def createDictNode(root, p): + node = avg.ImageNode(pos=p, href="rgb24-32x32.png", parent=root) + self.assertEqual(node.getMediaSize(), avg.Point2D(32, 32)) + self.assertEqual(node.size, avg.Point2D(32, 32)) + return node + + def addNodes(y): + xmlNode = createXmlNode((16, y)) + root.appendChild(xmlNode) + + createDictNode(root, (48, y)) + + noAttachNode = createXmlNode((80, y)) + noAttachNode.href = "rgb24alpha-32x32.png" + self.assertEqual(noAttachNode.getMediaSize(), avg.Point2D(32, 32)) + self.assertEqual(noAttachNode.size, avg.Point2D(32,32)) + root.appendChild(noAttachNode) + + attachNode = createXmlNode((112, y)) + root.appendChild(attachNode) + attachNode.href = "rgb24alpha-32x32.png" + self.assertEqual(attachNode.getMediaSize(), avg.Point2D(32, 32)) + self.assertEqual(attachNode.size, avg.Point2D(32,32)) + + def setUnicodeHref(): + if self._isCurrentDirWriteable(): + # Can't check unicode filenames into svn or the windows client breaks. + # So we rename the file locally. + shutil.copyfile("media/oe.png", u"media/ö.png") + node = createXmlNode((16, 16)) + root.appendChild(node) + node.href = u"ö.png" + os.remove(u"media/ö.png") + + def compareUnicode(): + if self._isCurrentDirWriteable(): + self.compareImage("testImgHRef3") + + root = self.loadEmptyScene() + addNodes(16) + self.start(False, + (lambda: self.compareImage("testImgHRef1"), + lambda: addNodes(48), + lambda: self.compareImage("testImgHRef2"), + setUnicodeHref, + compareUnicode + )) + + def testImagePos(self): + def createXmlNode(pos): + return player.createNode( + """<image pos="%s" href="rgb24-32x32.png"/>"""%str(pos)) + + def createDictNode(root, p): + return avg.ImageNode(pos=p, href="rgb24-32x32.png", parent=root) + + def illegalMove(node): + self.assertException(node.pos.x == 23) + self.assertException(node.pos.y == 23) + + def addNodes(y): + xmlNode = createXmlNode((16, y)) + root.appendChild(xmlNode) + createDictNode(root, (48, y)) + noAttachNode = createXmlNode((0, 0)) + noAttachNode.pos = avg.Point2D(80, y) + illegalMove(noAttachNode) + root.appendChild(noAttachNode) + attachNode = createXmlNode((0, 0)) + root.appendChild(attachNode) + attachNode.pos = avg.Point2D(112, y) + illegalMove(attachNode) + + root = self.loadEmptyScene() + addNodes(16) + self.start(False, + (lambda: self.compareImage("testImgPos1"), + lambda: addNodes(48), + lambda: self.compareImage("testImgPos2"), + )) + + def testImageSize(self): + def createXmlNode(pos, size): + return player.createNode( + """<image pos="%s" size="%s" href="rgb24-64x64.png"/>""" + %(str(pos), str(size))) + + def createDictNode(p, s): + return avg.ImageNode(pos=p, size=s, href="rgb24-64x64.png") + + def addNodes(y): + xmlNode = createXmlNode((16, y), (32, 32)) + self.assertEqual(xmlNode.size, avg.Point2D(32, 32)) + root.appendChild(xmlNode) + dictNode = createDictNode((48, y), (32, 32)) + self.assertEqual(dictNode.size, avg.Point2D(32, 32)) + root.appendChild(dictNode) + noAttachNode = createXmlNode((80, y), (0, 0)) + noAttachNode.size = avg.Point2D(32, 32) + self.assertEqual(noAttachNode.size, avg.Point2D(32, 32)) + root.appendChild(noAttachNode) + attachNode = createXmlNode((112, y), (0, 0)) + root.appendChild(attachNode) + attachNode.size = avg.Point2D(32, 32) + self.assertEqual(attachNode.size, avg.Point2D(32, 32)) + + root = self.loadEmptyScene() + addNodes(16) + self.start(False, + (lambda: self.compareImage("testImgSize1"), + lambda: addNodes(48), + lambda: self.compareImage("testImgSize2"), + )) + + def testImageWarp(self): + def createNode(p): + return avg.ImageNode(pos=p, href="rgb24-32x32.png", + maxtilewidth=16, maxtileheight=8) + + def moveVertex(node): + grid = node.getWarpedVertexCoords() + grid[0][1] = (grid[0][1][0]+0.25, grid[0][1][1]+0.25) + node.setWarpedVertexCoords(grid) + + def testEarlyAccessException(): + node = createNode((16, 16)) + root.appendChild(node) + self.assertException(node.getWarpedVertexCoords) + node.unlink() + + def addNode(): + self.node = createNode((16, 16)) + root.appendChild(self.node) + moveVertex(self.node) + + def changeHref(): + self.node.href = "rgb24-65x65.png" + grid = self.node.getWarpedVertexCoords() + self.assert_(len(grid) == 10) + self.assert_(len(grid[0]) == 6) + + + root = self.loadEmptyScene() + testEarlyAccessException() + self.start(False, + (lambda: addNode(), + lambda: self.compareImage("testImgWarp1"), + lambda: changeHref(), + lambda: self.compareImage("testImgWarp2"), + )) + + def testBitmap(self): + def getBitmap(node): + bmp = node.getBitmap() + self.assertEqual(bmp.getSize(), (65,65)) + self.assert_(bmp.getFormat() == avg.R8G8B8X8 or + bmp.getFormat() == avg.B8G8R8X8) + node.setBitmap(bmp) + self.assertEqual(node.getMediaSize(), (65,65)) + + def loadFromBitmap(p, orighref): + node = avg.ImageNode(pos=p, size=(32, 32), href=orighref) + bmp = avg.Bitmap('media/rgb24-65x65.png') + self.assertEqual(bmp.getSize(), (65,65)) + node.setBitmap(bmp) + self.assertEqual(node.getMediaSize(), (65,65)) + root.appendChild(node) + + def testStringConversion(): + bmp = avg.Bitmap('media/rgb24-65x65.png') + s = bmp.getPixels() + bmp1 = avg.Bitmap(bmp.getSize(), bmp.getFormat(), "sample") + bmp1.setPixels(s) + self.assert_(self.areSimilarBmps(bmp, bmp1, 0.01, 0.01)) + + def testCropRect(): + bmp = avg.Bitmap('media/rgb24-65x65.png') + bmp1 = avg.Bitmap(bmp, (32,32), (64,64)) + self.assert_(bmp1.getSize() == (32,32)) + node = avg.ImageNode(pos=(96,0), parent=root) + node.setBitmap(bmp1) + + def testBlt(): + srcBmp = avg.Bitmap('media/rgb24-65x65.png') + destBmp = avg.Bitmap((65,65), srcBmp.getFormat(), "bmp") + destBmp.blt(srcBmp, (0,0)) + destBmp.blt(srcBmp, (32,32)) + node = avg.ImageNode(pos=(96,32), size=(32,32), parent=root) + node.setBitmap(destBmp) + + def testResize(): + srcBmp = avg.Bitmap('media/rgb24-32x32.png') + destBmp = srcBmp.getResized((64,64)) + self.assert_(destBmp.getSize() == (64,64)) + node = avg.ImageNode(pos=(128,0), size=(32,32), parent=root) + node.setBitmap(destBmp) + + def testUnicode(): + if self._isCurrentDirWriteable(): + # Can't check unicode filenames into svn or the windows client breaks. + # So we rename the file locally. + shutil.copyfile("media/oe.png", u"media/ö.png") + avg.Bitmap(u"media/ö.png") + os.remove(u"media/ö.png") + + def testGetPixel(): + bmp = avg.Bitmap('media/rgb24-65x65.png') + self.assertEqual(bmp.getPixel((1,1)), (255,0,0,255)) + self.assertEqual(bmp.getPixel((33,1)), (0,255,0,255)) + bmp = avg.Bitmap('media/rgb24alpha-64x64.png') + self.assertEqual(bmp.getPixel((1,1)), (0,0,0,0)) + self.assertEqual(bmp.getPixel((63,1)), (83,255,83,142)) + bmp = avg.Bitmap('media/greyscale.png') + self.assertEqual(bmp.getPixel((1,1)), (255,255,255,255)) + self.assertEqual(bmp.getPixel((1,63)), (0,0,0,255)) + self.assertException(lambda: bmp.getPixel((64,0))) + + def setNullBitmap(): + node.setBitmap(None) + + def testSubBitmap(): + srcBmp = avg.Bitmap('media/rgb24-32x32.png') + destBmp = avg.Bitmap(srcBmp, (16,16), (32,32)) + self.assertEqual(srcBmp.getPixel((16,16)), destBmp.getPixel((0,0))) + self.assertException(lambda: avg.Bitmap(srcBmp, (16,16), (16,32))) + + node = avg.ImageNode(href="media/rgb24-65x65.png", size=(32, 32)) + getBitmap(node) + + root = self.loadEmptyScene() + node = avg.ImageNode(pos=(0,0), size=(32, 32), href="rgb24-65x65.png") + root.appendChild(node) + getBitmap(node) + self.assertEqual(node.size, (32,32)) + loadFromBitmap((32,0), "") + loadFromBitmap((64,0), "rgb24alpha-64x64.png") + testStringConversion() + testUnicode() + self.start(False, + (lambda: getBitmap(node), + lambda: loadFromBitmap((32,32), ""), + lambda: loadFromBitmap((64,32), "rgb24alpha-64x64.png"), + lambda: self.compareImage("testBitmap1"), + testCropRect, + lambda: self.compareImage("testBitmap2"), + testBlt, + lambda: self.compareImage("testBitmap3"), + testResize, + lambda: self.compareImage("testBitmap4"), + testGetPixel, + lambda: self.assertException(setNullBitmap), + testSubBitmap, + )) + + def testBitmapManager(self): + WAIT_TIMEOUT = 2000 + def expectException(returnValue, nextAction): + if isinstance(returnValue, Exception): + nextAction() + else: + raise RuntimeError("Expected exception, got %s (%s)" % ( + returnValue, type(returnValue))) + + def loadValidBitmap(): + def validBitmapCb(bitmap): + self.assert_(not isinstance(bitmap, Exception)) + player.setTimeout(0, loadBitmapWithPixelFormat) + + avg.BitmapManager.get().loadBitmap("media/rgb24alpha-64x64.png", + validBitmapCb) + + def loadBitmapWithPixelFormat(): + def validBitmapCb(bitmap): + self.assert_(not isinstance(bitmap, Exception)) + self.assert_(bitmap.getFormat() == avg.B5G6R5) + player.setTimeout(0, loadUnexistentBitmap) + + avg.BitmapManager.get().loadBitmap("media/rgb24alpha-64x64.png", + validBitmapCb, avg.B5G6R5) + + def loadUnexistentBitmap(): + avg.BitmapManager.get().loadBitmap("nonexistent.png", + lambda bmp: expectException( + returnValue=bmp, + nextAction=lambda: player.setTimeout(0, loadBrokenBitmap))) + + def loadBrokenBitmap(): + import tempfile + tempFileName = os.path.join(tempfile.gettempdir(), + "broken.png") + open(tempFileName, "w") + + def cleanupAndTestReturnValue(returnValue): + os.unlink(tempFileName) + expectException(returnValue=returnValue, nextAction=player.stop) + + avg.BitmapManager.get().loadBitmap(tempFileName, + cleanupAndTestReturnValue) + + def reportStuck(): + raise RuntimeError("BitmapManager didn't reply " + "within %dms timeout" % WAIT_TIMEOUT) + player.stop() + + for multithread in [False, True]: + self.loadEmptyScene() + if multithread: + avg.BitmapManager.get().setNumThreads(2) + player.setTimeout(WAIT_TIMEOUT, reportStuck) + player.setResolution(0, 0, 0, 0) + loadValidBitmap() + player.play() + avg.BitmapManager.get().setNumThreads(1) + + def testBitmapManagerException(self): + def bitmapCb(bitmap): + raise RuntimeError + + self.loadEmptyScene() + avg.BitmapManager.get().loadBitmap("rgb24alpha-64x64.png", bitmapCb), + self.assertException(player.play) + + def testBlendMode(self): + def isBlendMinMaxSupported(): + def tryInsertNode(): + try: + avg.ImageNode(href="rgb24-65x65.png", blendmode="min", parent=root) + except RuntimeError: + self.supported = False + root = self.loadEmptyScene() + self.supported = True + self.start(False, + (tryInsertNode, + )) + return self.supported + + + def setBlendMode(): + blendNode.blendmode="add" + + if not(isBlendMinMaxSupported()): + self.skip("Blend modes min and max not supported.") + return + root = self.loadEmptyScene() + avg.ImageNode(href="freidrehen.jpg", parent=root) + blendNode = avg.ImageNode(opacity=0.6, href="rgb24-65x65.png", parent=root) + avg.ImageNode(pos=(0,48), opacity=0.6, href="rgb24-65x65.png", blendmode="add", + parent=root) + avg.ImageNode(pos=(48,0), opacity=1, href="rgb24-65x65.png", blendmode="min", + parent=root) + avg.ImageNode(pos=(48,48), opacity=1, href="rgb24-65x65.png", blendmode="max", + parent=root) + + self.start(False, + (lambda: self.compareImage("testBlend1"), + setBlendMode, + lambda: self.compareImage("testBlend2") + )) + + def testImageMask(self): + def createNode(p): + node = avg.ImageNode(href="rgb24-65x65.png", maskhref="mask.png", + pos=p, size=(32, 32)) + root.appendChild(node) + + def setNoAttach(p): + node = avg.ImageNode(href="rgb24-65x65.png", pos=p, size=(32, 32)) + node.maskhref = "mask.png" + root.appendChild(node) + + def setAttach(p): + node = avg.ImageNode(href="rgb24-65x65.png", pos=p, size=(32, 32)) + root.appendChild(node) + node.maskhref = "mask.png" + + def changeHRef(): + node.maskhref = "mask2.png" + + def changeBaseHRef(): + node.href = "greyscale.png" + + def setMaskNotFound(): + node.maskhref = "nonexistentmask.png" + + root = self.loadEmptyScene() + createNode((0,0)) + node = root.getChild(0) + setNoAttach((32,0)) + setAttach((64,0)) + self.start(False, + (lambda: createNode((0, 32)), + lambda: setNoAttach((32,32)), + lambda: setAttach((64,32)), + lambda: self.compareImage("testImgMask1"), + changeHRef, + lambda: self.compareImage("testImgMask2"), + changeBaseHRef, + lambda: self.compareImage("testImgMask3"), + setMaskNotFound + )) + + def testImageMaskCanvas(self): + root = self.loadEmptyScene() + canvas = player.createCanvas(id="testcanvas", size=(64,64), mediadir="media") + avg.ImageNode(href="rgb24-64x64.png", parent=canvas.getRootNode()) + avg.RectNode(size=(160,120), fillcolor="FFFFFF", fillopacity=1, parent=root) + avg.ImageNode(href="canvas:testcanvas", maskhref="mask.png", parent=root) + self.start(False, + (lambda: self.compareImage("testImgMaskCanvas"),)) + + def testImageMaskPos(self): + def createNode(p): + node = avg.ImageNode(href="rgb24-65x65.png", maskhref="mask.png", + pos=p, size=(32, 32), maskpos=(32, 32)) + root.appendChild(node) + + def setNoAttach(p): + node = avg.ImageNode(href="rgb24-65x65.png", maskhref="mask.png", + pos=p, size=(32, 32)) + node.maskpos = (32, 32) + root.appendChild(node) + + def setAttach(p): + node = avg.ImageNode(href="rgb24-65x65.png", maskhref="mask.png", + pos=p, size=(32, 32)) + root.appendChild(node) + node.maskpos = (32, 32) + + root = self.loadEmptyScene() + createNode((0,0)) + setNoAttach((32,0)) + setAttach((64,0)) + self.start(False, + (lambda: createNode((0, 32)), + lambda: setNoAttach((32,32)), + lambda: setAttach((64,32)), + lambda: self.compareImage("testImgMaskPos") + )) + + def testImageMaskSize(self): + def createNode(p): + avg.ImageNode(href="rgb24-65x65.png", maskhref="mask.png", + pos=p, size=(32, 32), masksize=(48, 48), parent=root) + + def setNoAttach(p): + node = avg.ImageNode(href="rgb24-65x65.png", maskhref="mask.png", + pos=p, size=(32, 32)) + node.masksize = (48, 48) + root.appendChild(node) + + def setAttach(p): + node = avg.ImageNode(href="rgb24-65x65.png", maskhref="mask.png", + pos=p, size=(32, 32), parent=root) + node.masksize = (48, 48) + + def setPos(): + node.maskpos = (16, 16) + + def resetPos(): + node.maskpos = (0, 0) + node.masksize = (0, 0) + + root = self.loadEmptyScene() + createNode((0,0)) + node = root.getChild(0) + setNoAttach((32,0)) + setAttach((64,0)) + self.start(False, + (lambda: createNode((0, 32)), + lambda: setNoAttach((32,32)), + lambda: setAttach((64,32)), + lambda: self.compareImage("testImgMaskSize1"), + setPos, + lambda: self.compareImage("testImgMaskSize2"), + resetPos, + lambda: self.compareImage("testImgMaskSize3") + )) + + def testImageMipmap(self): + root = self.loadEmptyScene() + avg.ImageNode(size=(64,64), href="checker.png", mipmap=True, parent=root) + self.start(False, + (lambda: self.compareImage("testMipmap"),)) + + def testImageCompression(self): + def loadBitmap(): + bmp = avg.Bitmap("media/colorramp.png") + self.image.setBitmap(bmp) + + def relink(): + self.image.unlink(False) + root.appendChild(self.image) + + def checkAlpha(): + self.image.href="rgb24alpha-64x64.png" + + root = self.loadEmptyScene() + self.image = avg.ImageNode(href="rgb24-64x64.png", compression="B5G6R5", + parent=root) + self.assertEqual(self.image.compression, "B5G6R5") + self.start(False, + [lambda: self.compareImage("testTexCompression1"), + loadBitmap, + lambda: self.compareImage("testTexCompression2"), + relink, + lambda: self.compareImage("testTexCompression2"), + checkAlpha, + ]) + + def testSpline(self): + spline = avg.CubicSpline([(0,3),(1,2),(2,1),(3,0)]) + self.assertAlmostEqual(spline.interpolate(0), 3) + self.assertAlmostEqual(spline.interpolate(0.5), 2.5) + self.assertAlmostEqual(spline.interpolate(1), 2) + self.assertAlmostEqual(spline.interpolate(-1), 4) + self.assertAlmostEqual(spline.interpolate(4), -1) + + spline = avg.CubicSpline([(2,0),(4,1),(6,3),(8,6)]) + self.assertAlmostEqual(spline.interpolate(2), 0) + self.assert_(spline.interpolate(3) < 0.5) + self.assert_(spline.interpolate(3) > 0.0) + self.assert_(spline.interpolate(7) < 4.5) + self.assert_(spline.interpolate(7) > 4) + + +def imageTestSuite(tests): + availableTests = ( + "testImageHRef", + "testImagePos", + "testImageSize", + "testImageWarp", + "testBitmap", + "testBitmapManager", + "testBitmapManagerException", + "testBlendMode", + "testImageMask", + "testImageMaskCanvas", + "testImageMaskPos", + "testImageMaskSize", + "testImageMipmap", + "testImageCompression", + "testSpline", + ) + return createAVGTestSuite(availableTests, ImageTestCase, tests) |