mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 08:39:17 +01:00
Refactor Candidate class in fetchart.py to improve
validation and resizing logic
This commit is contained in:
parent
b09806e0df
commit
66b459b8d0
1 changed files with 46 additions and 15 deletions
|
|
@ -67,10 +67,15 @@ class Candidate:
|
||||||
self.match = match
|
self.match = match
|
||||||
self.size = size
|
self.size = size
|
||||||
|
|
||||||
def _validate(self, plugin):
|
def _validate(self, plugin, skip_check_for=None):
|
||||||
"""Determine whether the candidate artwork is valid based on
|
"""Determine whether the candidate artwork is valid based on
|
||||||
its dimensions (width and ratio).
|
its dimensions (width and ratio).
|
||||||
|
|
||||||
|
`skip_check_for` is a check or list of checks to skip. This is used to
|
||||||
|
avoid redundant checks when the candidate has already been
|
||||||
|
validated for a particular operation without changing
|
||||||
|
plugin configuration.
|
||||||
|
|
||||||
Return `CANDIDATE_BAD` if the file is unusable.
|
Return `CANDIDATE_BAD` if the file is unusable.
|
||||||
Return `CANDIDATE_EXACT` if the file is usable as-is.
|
Return `CANDIDATE_EXACT` if the file is usable as-is.
|
||||||
Return `CANDIDATE_DOWNSCALE` if the file must be rescaled.
|
Return `CANDIDATE_DOWNSCALE` if the file must be rescaled.
|
||||||
|
|
@ -82,6 +87,11 @@ class Candidate:
|
||||||
if not self.path:
|
if not self.path:
|
||||||
return self.CANDIDATE_BAD
|
return self.CANDIDATE_BAD
|
||||||
|
|
||||||
|
if skip_check_for is None:
|
||||||
|
skip_check_for = []
|
||||||
|
if isinstance(skip_check_for, int):
|
||||||
|
skip_check_for = [skip_check_for]
|
||||||
|
|
||||||
if not (
|
if not (
|
||||||
plugin.enforce_ratio
|
plugin.enforce_ratio
|
||||||
or plugin.minwidth
|
or plugin.minwidth
|
||||||
|
|
@ -180,30 +190,51 @@ class Candidate:
|
||||||
plugin.cover_format,
|
plugin.cover_format,
|
||||||
)
|
)
|
||||||
|
|
||||||
if downscale:
|
if downscale and (not self.CANDIDATE_DOWNSCALE in skip_check_for):
|
||||||
return self.CANDIDATE_DOWNSCALE
|
return self.CANDIDATE_DOWNSCALE
|
||||||
elif downsize:
|
if reformat and (not self.CANDIDATE_REFORMAT in skip_check_for):
|
||||||
return self.CANDIDATE_DOWNSIZE
|
|
||||||
elif plugin.deinterlace:
|
|
||||||
return self.CANDIDATE_DEINTERLACE
|
|
||||||
elif reformat:
|
|
||||||
return self.CANDIDATE_REFORMAT
|
return self.CANDIDATE_REFORMAT
|
||||||
else:
|
if plugin.deinterlace and (
|
||||||
return self.CANDIDATE_EXACT
|
not self.CANDIDATE_DEINTERLACE in skip_check_for
|
||||||
|
):
|
||||||
|
return self.CANDIDATE_DEINTERLACE
|
||||||
|
if downsize and (not self.CANDIDATE_DOWNSIZE in skip_check_for):
|
||||||
|
return self.CANDIDATE_DOWNSIZE
|
||||||
|
return self.CANDIDATE_EXACT
|
||||||
|
|
||||||
def validate(self, plugin):
|
def validate(self, plugin, skip_check_for=None):
|
||||||
self.check = self._validate(plugin)
|
self.check = self._validate(plugin, skip_check_for)
|
||||||
return self.check
|
return self.check
|
||||||
|
|
||||||
def resize(self, plugin):
|
def resize(self, plugin):
|
||||||
if self.check == self.CANDIDATE_DOWNSCALE:
|
"""Resize the candidate artwork according to the plugin's
|
||||||
|
configuration until it is valid or no further resizing is
|
||||||
|
possible.
|
||||||
|
"""
|
||||||
|
# validate the candidate in case it hasn't been done yet
|
||||||
|
current_check = self.validate(plugin)
|
||||||
|
checks_performed = []
|
||||||
|
|
||||||
|
# we don't want to resize the image if it's valid or bad
|
||||||
|
while current_check not in [self.CANDIDATE_BAD, self.CANDIDATE_EXACT]:
|
||||||
|
self._resize(plugin, current_check)
|
||||||
|
checks_performed.append(current_check)
|
||||||
|
current_check = self.validate(
|
||||||
|
plugin, skip_check_for=checks_performed
|
||||||
|
)
|
||||||
|
|
||||||
|
def _resize(self, plugin, check=None):
|
||||||
|
"""Resize the candidate artwork according to the plugin's
|
||||||
|
configuration and the specified check.
|
||||||
|
"""
|
||||||
|
if check == self.CANDIDATE_DOWNSCALE:
|
||||||
self.path = ArtResizer.shared.resize(
|
self.path = ArtResizer.shared.resize(
|
||||||
plugin.maxwidth,
|
plugin.maxwidth,
|
||||||
self.path,
|
self.path,
|
||||||
quality=plugin.quality,
|
quality=plugin.quality,
|
||||||
max_filesize=plugin.max_filesize,
|
max_filesize=plugin.max_filesize,
|
||||||
)
|
)
|
||||||
elif self.check == self.CANDIDATE_DOWNSIZE:
|
elif check == self.CANDIDATE_DOWNSIZE:
|
||||||
# dimensions are correct, so maxwidth is set to maximum dimension
|
# dimensions are correct, so maxwidth is set to maximum dimension
|
||||||
self.path = ArtResizer.shared.resize(
|
self.path = ArtResizer.shared.resize(
|
||||||
max(self.size),
|
max(self.size),
|
||||||
|
|
@ -211,9 +242,9 @@ class Candidate:
|
||||||
quality=plugin.quality,
|
quality=plugin.quality,
|
||||||
max_filesize=plugin.max_filesize,
|
max_filesize=plugin.max_filesize,
|
||||||
)
|
)
|
||||||
elif self.check == self.CANDIDATE_DEINTERLACE:
|
elif check == self.CANDIDATE_DEINTERLACE:
|
||||||
self.path = ArtResizer.shared.deinterlace(self.path)
|
self.path = ArtResizer.shared.deinterlace(self.path)
|
||||||
elif self.check == self.CANDIDATE_REFORMAT:
|
elif check == self.CANDIDATE_REFORMAT:
|
||||||
self.path = ArtResizer.shared.reformat(
|
self.path = ArtResizer.shared.reformat(
|
||||||
self.path,
|
self.path,
|
||||||
plugin.cover_format,
|
plugin.cover_format,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue