Merge pull request #1394 from tomjaspers/fetchart-minwidth-ratio

Fetchart: minwidth and enforce_ratio options
This commit is contained in:
Tom Jaspers 2015-04-06 11:20:33 +02:00
commit 7bdcb08ef5
3 changed files with 90 additions and 4 deletions

View file

@ -300,7 +300,9 @@ class FetchArtPlugin(plugins.BeetsPlugin):
self.config.add({
'auto': True,
'minwidth': 0,
'maxwidth': 0,
'enforce_ratio': False,
'remote_priority': False,
'cautious': False,
'google_search': False,
@ -312,7 +314,10 @@ class FetchArtPlugin(plugins.BeetsPlugin):
# placing them in the filesystem.
self.art_paths = {}
self.minwidth = self.config['minwidth'].get(int)
self.maxwidth = self.config['maxwidth'].get(int)
self.enforce_ratio = self.config['enforce_ratio'].get(bool)
if self.config['auto']:
# Enable two import hooks when fetching is enabled.
self.import_stages = [self.fetch_art]
@ -397,6 +402,17 @@ class FetchArtPlugin(plugins.BeetsPlugin):
except (IOError, requests.RequestException):
self._log.debug(u'error fetching art')
def _is_valid_image_candidate(self, candidate):
if not candidate:
return False
if not (self.enforce_ratio or self.minwidth):
return True
size = ArtResizer.shared.get_size(candidate)
return size and size[0] >= self.minwidth and \
(not self.enforce_ratio or size[0] == size[1])
def art_for_album(self, album, paths, local_only=False):
"""Given an Album object, returns a path to downloaded art for the
album (or None if no art is found). If `maxwidth`, then images are
@ -412,9 +428,9 @@ class FetchArtPlugin(plugins.BeetsPlugin):
cautious = self.config['cautious'].get(bool)
if paths:
for path in paths:
# FIXME
out = self.fs_source.get(path, cover_names, cautious)
if out:
candidate = self.fs_source.get(path, cover_names, cautious)
if self._is_valid_image_candidate(candidate):
out = candidate
break
# Web art sources.
@ -424,7 +440,7 @@ class FetchArtPlugin(plugins.BeetsPlugin):
if self.maxwidth:
url = ArtResizer.shared.proxy_url(self.maxwidth, url)
candidate = self._fetch_image(url)
if candidate:
if self._is_valid_image_candidate(candidate):
out = candidate
break

View file

@ -38,9 +38,13 @@ file. The available options are:
Default: ``cover front art album folder``.
- **google_search**: Gather images from Google Image Search.
Default: ``no``.
- **minwidth**: Only images with a width bigger or equal to ``minwidth`` are
considered as valid album art candidates. Default: 0.
- **maxwidth**: A maximum image width to downscale fetched images if they are
too big. The resize operation reduces image width to at most ``maxwidth``
pixels. The height is recomputed so that the aspect ratio is preserved.
- **enforce_ratio**: Only images with a width:height ratio of 1:1 are
considered as valid album art candidates. Default: ``no``.
- **remote_priority**: Query remote sources every time and use local image only
as fallback.
Default: ``no``; remote (Web) art sources are only queried if no local art is

View file

@ -357,6 +357,72 @@ class ArtImporterTest(UseThePlugin):
self._fetch_art(True)
class ArtForAlbumTest(UseThePlugin):
""" Tests that fetchart.art_for_album respects the size
configuration (e.g., minwidth, enforce_ratio)
"""
IMG_225x225 = os.path.join(_common.RSRC, 'abbey.jpg')
IMG_348x348 = os.path.join(_common.RSRC, 'abbey-different.jpg')
IMG_500x490 = os.path.join(_common.RSRC, 'abbey-similar.jpg')
def setUp(self):
super(ArtForAlbumTest, self).setUp()
self.old_fs_source_get = self.plugin.fs_source.get
self.old_fetch_img = self.plugin._fetch_image
self.old_source_urls = self.plugin._source_urls
def fs_source_get(*_):
return self.image_file
def source_urls(_):
return ['']
def fetch_img(_):
return self.image_file
self.plugin.fs_source.get = fs_source_get
self.plugin._source_urls = source_urls
self.plugin._fetch_image = fetch_img
def tearDown(self):
self.plugin.fs_source.get = self.old_fs_source_get
self.plugin._source_urls = self.old_source_urls
self.plugin._fetch_image = self.old_fetch_img
super(ArtForAlbumTest, self).tearDown()
def _assertImageIsValidArt(self, image_file, should_exist):
self.assertExists(image_file)
self.image_file = image_file
local_artpath = self.plugin.art_for_album(None, [''], True)
remote_artpath = self.plugin.art_for_album(None, [], False)
self.assertEqual(local_artpath, remote_artpath)
if should_exist:
self.assertEqual(local_artpath, self.image_file)
self.assertExists(local_artpath)
return local_artpath
else:
self.assertIsNone(local_artpath)
def test_respect_minwidth(self):
self.plugin.minwidth = 300
self._assertImageIsValidArt(self.IMG_225x225, False)
self._assertImageIsValidArt(self.IMG_348x348, True)
def test_respect_enforce_ratio_yes(self):
self.plugin.enforce_ratio = True
self._assertImageIsValidArt(self.IMG_500x490, False)
self._assertImageIsValidArt(self.IMG_225x225, True)
def test_respect_enforce_ratio_no(self):
self.plugin.enforce_ratio = False
self._assertImageIsValidArt(self.IMG_500x490, True)
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)