Source code for mg.utils.photo.bbox_fitter

# MG_GPL_HEADER_BEGIN
# 
# This file is part of Media Gallery, GNU GPLv2.
# 
# Media Gallery is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
# 
# Media Gallery 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
# General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Media Gallery; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# 
# MG_GPL_HEADER_END

__author__ = "Media Gallery contributors <mg@lists.ssji.net>"
__copyright__ = "(c) 2010"
__credits__ = ["Dimitri Refauvelet", "Nicolas Pouillon"]

from mg.utils.memoize import memoized
import unittest

__all__ = ['fit_resized']

@memoized
def fit_resized(src_size, dst_size, fill, center = None):
[docs] """ Gets the bounding box in the input and output image depending on source size, destination size, filling, cropping and center of interest in source image. :param src_size: Size of input image :param dst_size: Size of output image :param fill: Whether to fill the output or pad the output image to fit the output size. Filling cuts out the parts of the image not fitting the output viewport :param center: Coords of center of interest of image. May be ``None`` for normal centering. Only used if filling is enabled. """ src_w, src_h = src_size dst_w, dst_h = dst_size reduc_ratio_w = float(src_w) / dst_w reduc_ratio_h = float(src_h) / dst_h # print # print src_size, dst_size, fill, center if fill: reduc_ratio = min((reduc_ratio_w, reduc_ratio_h)) dst_sel_size = dst_size src_sel_size = dst_size[0] * reduc_ratio, dst_size[1] * reduc_ratio dst_top_left = (0,0) src_center = center or (src_size[0]/2, src_size[1]/2) src_top_left = ( src_center[0] - src_sel_size[0] / 2, src_center[1] - src_sel_size[1] / 2, ) src_top_left_bounds = ( src_size[0] - src_sel_size[0], src_size[1] - src_sel_size[1], ) # print 'src_top_left:', src_top_left # print 'src_top_left_bounds:', src_top_left_bounds src_top_left = ( min((max((src_top_left[0], 0)), src_top_left_bounds[0])), min((max((src_top_left[1], 0)), src_top_left_bounds[1])), ) else: reduc_ratio = max((reduc_ratio_w, reduc_ratio_h)) src_sel_size = src_size dst_sel_size = src_size[0] / reduc_ratio, src_size[1] / reduc_ratio dst_top_left = ( (dst_size[0] - dst_sel_size[0]) / 2, (dst_size[1] - dst_sel_size[1]) / 2, ) src_top_left = (0,0) # print 'src_sel_size:', src_sel_size # print 'dst_sel_size:', dst_sel_size # print 'src_top_left:', src_top_left # print 'dst_top_left:', dst_top_left # print 'reduc_ratio:', reduc_ratio_w, reduc_ratio_h, reduc_ratio return (tuple(map(int, src_top_left + src_sel_size)), tuple(map(int, dst_top_left + dst_sel_size))) class Tests(unittest.TestCase):
def test_identity_fill(self): src_bbox, dst_bbox = fit_resized( (100, 200), (100, 200), True) self.assertEqual(src_bbox, dst_bbox) self.assertEqual(src_bbox, (0,0,100,200)) def test_identity_fit(self): src_bbox, dst_bbox = fit_resized( (100, 200), (100, 200), False) self.assertEqual(src_bbox, dst_bbox) self.assertEqual(src_bbox, (0,0,100,200)) def test_simple_fill(self): src_bbox, dst_bbox = fit_resized( (100, 200), (40, 40), True) self.assertEqual(src_bbox, (0, 50, 100, 100)) self.assertEqual(dst_bbox, (0,0,40, 40)) def test_simple_fit(self): src_bbox, dst_bbox = fit_resized( (100, 200), (40, 40), False) self.assertEqual(src_bbox, (0,0,100,200)) self.assertEqual(dst_bbox, (10,0,20,40)) def test_left_fill(self): src_bbox, dst_bbox = fit_resized( (100, 200), (40, 40), True, (0,0)) self.assertEqual(src_bbox, (0,0,100,100)) self.assertEqual(dst_bbox, (0,0,40,40)) def test_right_fill(self): src_bbox, dst_bbox = fit_resized( (100, 200), (40, 40), True, (100,200)) self.assertEqual(src_bbox, (0,100,100,100)) self.assertEqual(dst_bbox, (0,0,40,40)) def test_top_fill(self): src_bbox, dst_bbox = fit_resized( (100, 200), (40, 20), True, (50,0)) self.assertEqual(src_bbox, (0,0,100,50)) self.assertEqual(dst_bbox, (0,0,40,20)) def test_bottom_fill(self): src_bbox, dst_bbox = fit_resized( (100, 200), (40, 20), True, (50,200)) self.assertEqual(src_bbox, (0,150,100,50)) self.assertEqual(dst_bbox, (0,0,40,20)) def test(): unittest.main() if __name__ == '__main__': test()