# 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()