#!/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( """"""%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( """"""%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( """""" %(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)