mirror of
https://github.com/beetbox/beets.git
synced 2026-01-01 05:23:05 +01:00
Merge pull request #1394 from tomjaspers/fetchart-minwidth-ratio
Fetchart: minwidth and enforce_ratio options
This commit is contained in:
commit
7bdcb08ef5
3 changed files with 90 additions and 4 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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__)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue