diff --git a/beets/util/artresizer.py b/beets/util/artresizer.py index 1b6a5903e..919a10883 100644 --- a/beets/util/artresizer.py +++ b/beets/util/artresizer.py @@ -173,6 +173,46 @@ class ArtResizer(object): log.debug(u"artresizer: method is {0}", self.method) self.can_compare = self._can_compare() + def valid_size(self, size, enforce_ratio = False, minwidth = None): + """If size constraints exist, check whether the provided image size + matches them. + """ + # Check minimum size. + if minwidth and size[0] < minwidth: + log.debug('image too small ({} < {})', + size[0], minwidth) + return False + + # Check aspect ratio. + if enforce_ratio and size[0] != size[1]: + log.debug('image is not square ({} != {})', + size[0], size[1]) + return False + + return True + + def must_resize(self, size, maxwidth = None): + """Determine whether the provided image size means that the image + will need to be scaled to fit the maximum width. + """ + if not maxwidth: + return False + + if not size: + log.warning(u'Could not get size of image (please see ' + u'documentation for dependencies).') + return False + + if size[0] <= maxwidth: + log.debug('dump values ({} > {})', + size[0], maxwidth) + log.debug(u'Image does not need to be resized.') + return False + + log.debug('Image needs resizing ({} > {})', + size[0], maxwidth) + return True + def resize(self, maxwidth, path_in, path_out=None): """Manipulate an image file according to the method, returning a new path. For PIL or IMAGEMAGIC methods, resizes the image to a diff --git a/beetsplug/fetchart.py b/beetsplug/fetchart.py index 57d8e4c46..efa2f5bde 100644 --- a/beetsplug/fetchart.py +++ b/beetsplug/fetchart.py @@ -42,10 +42,6 @@ IMAGE_EXTENSIONS = ['png', 'jpg', 'jpeg'] CONTENT_TYPES = ('image/jpeg', 'image/png') DOWNLOAD_EXTENSION = '.jpg' -CANDIDATE_BAD = 0 -CANDIDATE_EXACT = 1 -CANDIDATE_DOWNSCALE = 2 - def _logged_get(log, *args, **kwargs): """Like `requests.get`, but logs the effective URL to the specified @@ -535,51 +531,6 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): self._log.debug('error fetching art: {}', exc) return None - def _is_valid_image_candidate(self, candidate): - """Determine whether the given candidate artwork is valid based on - its dimensions (width and ratio). - - Return `CANDIDATE_BAD` if the file is unusable. - Return `CANDIDATE_EXACT` if the file is usable as-is. - Return `CANDIDATE_DOWNSCALE` if the file must be resized. - """ - if not candidate: - return CANDIDATE_BAD - - if not (self.enforce_ratio or self.minwidth or self.maxwidth): - return CANDIDATE_EXACT - - # get_size returns None if no local imaging backend is available - size = ArtResizer.shared.get_size(candidate) - self._log.debug('image size: {}', size) - - if not size: - self._log.warning(u'Could not get size of image (please see ' - u'documentation for dependencies). ' - u'The configuration options `minwidth` and ' - u'`enforce_ratio` may be violated.') - return CANDIDATE_EXACT - - # Check minimum size. - if self.minwidth and size[0] < self.minwidth: - self._log.debug('image too small ({} < {})', - size[0], self.minwidth) - return CANDIDATE_BAD - - # Check aspect ratio. - if self.enforce_ratio and size[0] != size[1]: - self._log.debug('image is not square ({} != {})', - size[0], size[1]) - return CANDIDATE_BAD - - # Check maximum size. - if self.maxwidth and size[0] > self.maxwidth: - self._log.debug('image needs resizing ({} > {})', - size[0], self.maxwidth) - return CANDIDATE_DOWNSCALE - - return CANDIDATE_EXACT - 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 @@ -588,7 +539,7 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): are made. """ out = None - check = None + size = None # Local art. cover_names = self.config['cover_names'].as_str_seq() @@ -597,11 +548,21 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): if paths: for path in paths: candidate = self.fs_source.get(path, cover_names, cautious) - check = self._is_valid_image_candidate(candidate) - if check: - out = candidate - self._log.debug('found local image {}', out) - break + if not candidate: + continue + + # get_size returns None if no local imaging backend is available + size = ArtResizer.shared.get_size(candidate) + self._log.debug('image size: {}', size) + if size: + valid = ArtResizer.shared.valid_size(size, + self.enforce_ratio, self.minwidth) + if not valid: + continue + + out = candidate + self._log.debug('found local image {}', out) + break # Web art sources. remote_priority = self.config['remote_priority'].get(bool) @@ -610,13 +571,23 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): if self.maxwidth: url = ArtResizer.shared.proxy_url(self.maxwidth, url) candidate = self._fetch_image(url) - check = self._is_valid_image_candidate(candidate) - if check: - out = candidate - self._log.debug('using remote image {}', out) - break + if not candidate: + continue - if self.maxwidth and out and check == CANDIDATE_DOWNSCALE: + # get_size returns None if no local imaging backend is available + size = ArtResizer.shared.get_size(candidate) + self._log.debug('image size: {}', size) + if size: + valid = ArtResizer.shared.valid_size(size, + self.enforce_ratio, self.minwidth) + if not valid: + continue + + out = candidate + self._log.debug('using remote image {}', out) + break + + if self.maxwidth and out and ArtResizer.shared.must_resize(size, self.maxwidth): out = ArtResizer.shared.resize(self.maxwidth, out) return out