update comment
This commit is contained in:
homm 2014-11-07 11:48:47 +03:00
parent a51b176644
commit 4cf2f158b6
2 changed files with 103 additions and 23 deletions

View File

@ -1,29 +1,108 @@
from helper import unittest, PillowTestCase, hopper from helper import unittest, PillowTestCase, hopper
from PIL import Image from PIL.Image import (FLIP_LEFT_RIGHT, FLIP_TOP_BOTTOM, ROTATE_90, ROTATE_180,
ROTATE_270, TRANSPOSE)
FLIP_LEFT_RIGHT = Image.FLIP_LEFT_RIGHT
FLIP_TOP_BOTTOM = Image.FLIP_TOP_BOTTOM
ROTATE_90 = Image.ROTATE_90
ROTATE_180 = Image.ROTATE_180
ROTATE_270 = Image.ROTATE_270
class TestImageTranspose(PillowTestCase): class TestImageTranspose(PillowTestCase):
def test_sanity(self): def test_flip_left_right(self):
def transpose(mode):
im = hopper(mode)
out = im.transpose(FLIP_LEFT_RIGHT)
self.assertEqual(out.mode, mode)
self.assertEqual(out.size, im.size)
im = hopper() x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((x-2, 1)))
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((1, 1)))
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((x-2, y-2)))
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((1, y-2)))
im.transpose(FLIP_LEFT_RIGHT) for mode in ("L", "RGB"):
im.transpose(FLIP_TOP_BOTTOM) transpose(mode)
im.transpose(ROTATE_90) def test_flip_top_bottom(self):
im.transpose(ROTATE_180) def transpose(mode):
im.transpose(ROTATE_270) im = hopper(mode)
out = im.transpose(FLIP_TOP_BOTTOM)
self.assertEqual(out.mode, mode)
self.assertEqual(out.size, im.size)
x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, y-2)))
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((x-2, y-2)))
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((1, 1)))
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((x-2, 1)))
for mode in ("L", "RGB"):
transpose(mode)
def test_rotate_90(self):
def transpose(mode):
im = hopper(mode)
out = im.transpose(ROTATE_90)
self.assertEqual(out.mode, mode)
self.assertEqual(out.size, im.size[::-1])
x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, y-2)))
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((1, 1)))
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((x-2, y-2)))
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((x-2, 1)))
for mode in ("L", "RGB"):
transpose(mode)
def test_rotate_180(self):
def transpose(mode):
im = hopper(mode)
out = im.transpose(ROTATE_180)
self.assertEqual(out.mode, mode)
self.assertEqual(out.size, im.size)
x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((x-2, y-2)))
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((1, y-2)))
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((x-2, 1)))
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((1, 1)))
for mode in ("L", "RGB"):
transpose(mode)
def test_rotate_270(self):
def transpose(mode):
im = hopper(mode)
out = im.transpose(ROTATE_270)
self.assertEqual(out.mode, mode)
self.assertEqual(out.size, im.size[::-1])
x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((x-2, 1)))
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((x-2, y-2)))
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((1, 1)))
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((1, y-2)))
for mode in ("L", "RGB"):
transpose(mode)
def test_transpose(self):
def transpose(mode):
im = hopper(mode)
out = im.transpose(TRANSPOSE)
self.assertEqual(out.mode, mode)
self.assertEqual(out.size, im.size[::-1])
x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, 1)))
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((1, y-2)))
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((x-2, 1)))
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((x-2, y-2)))
for mode in ("L", "RGB"):
transpose(mode)
def test_roundtrip(self): def test_roundtrip(self):
im = hopper() im = hopper()
def transpose(first, second): def transpose(first, second):
@ -33,12 +112,13 @@ class TestImageTranspose(PillowTestCase):
im, transpose(FLIP_LEFT_RIGHT, FLIP_LEFT_RIGHT)) im, transpose(FLIP_LEFT_RIGHT, FLIP_LEFT_RIGHT))
self.assert_image_equal( self.assert_image_equal(
im, transpose(FLIP_TOP_BOTTOM, FLIP_TOP_BOTTOM)) im, transpose(FLIP_TOP_BOTTOM, FLIP_TOP_BOTTOM))
self.assert_image_equal(im, transpose(ROTATE_90, ROTATE_270)) self.assert_image_equal(im, transpose(ROTATE_90, ROTATE_270))
self.assert_image_equal(im, transpose(ROTATE_180, ROTATE_180)) self.assert_image_equal(im, transpose(ROTATE_180, ROTATE_180))
self.assert_image_equal(
im.transpose(TRANSPOSE), transpose(ROTATE_90, FLIP_TOP_BOTTOM))
self.assert_image_equal(
im.transpose(TRANSPOSE), transpose(ROTATE_270, FLIP_LEFT_RIGHT))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
# End of file

View File

@ -30,11 +30,11 @@
/* Undef if you don't need resampling filters */ /* Undef if you don't need resampling filters */
#define WITH_FILTERS #define WITH_FILTERS
/* Large images rotation is inefficient operation in terms of CPU cache. /* For large images rotation is an inefficient operation in terms of CPU cache.
One row in source image affects each column in destination. One row in the source image affects each column in destination.
Rotating in small chunks can speed up up to 8 times on modern CPU. Rotating in chunks that fit in the cache can speed up rotation
Chunk size of 128 requires only 65k of CPU cache and high enougth 8x on a modern CPU. A chunk size of 128 requires only 65k and is large enough
for overhead from extra loop have not been manifested. */ that the overhead from the extra loops are not apparent. */
#define ROTATE_CHUNK 128 #define ROTATE_CHUNK 128
#define COORD(v) ((v) < 0.0 ? -1 : ((int)(v))) #define COORD(v) ((v) < 0.0 ? -1 : ((int)(v)))