Add option to stretch or crop

This commit is contained in:
twodoorcoupe
2024-06-21 12:58:06 +02:00
parent 9f5184a48a
commit c6ff9caa5a
6 changed files with 252 additions and 26 deletions

View File

@@ -55,46 +55,64 @@ class ResizeImage(ImageProcessor):
tags_direction = (setting['cover_tags_scale_up'], setting['cover_tags_scale_down']) tags_direction = (setting['cover_tags_scale_up'], setting['cover_tags_scale_down'])
file_direction = (setting['cover_file_scale_up'], setting['cover_file_scale_down']) file_direction = (setting['cover_file_scale_up'], setting['cover_file_scale_down'])
same_direction = tags_direction == file_direction and any(tags_direction) same_direction = tags_direction == file_direction and any(tags_direction)
return same_size and same_direction tags_resize_mode = (setting['cover_tags_stretch'], setting['cover_tags_crop'])
file_resize_mode = (setting['cover_file_stretch'], setting['cover_file_crop'])
same_resize_mode = tags_resize_mode == file_resize_mode
return same_size and same_direction and same_resize_mode
def run(self, image, target): def run(self, image, target):
start_time = time.time() start_time = time.time()
config = get_config() config = get_config()
target_width = image.info.width
target_height = image.info.height
if target == ProcessingTarget.TAGS: if target == ProcessingTarget.TAGS:
scale_up = config.setting['cover_tags_scale_up'] scale_up = config.setting['cover_tags_scale_up']
scale_down = config.setting['cover_tags_scale_down'] scale_down = config.setting['cover_tags_scale_down']
use_width = config.setting['cover_tags_resize_use_width'] use_width = config.setting['cover_tags_resize_use_width']
if use_width: target_width = config.setting['cover_tags_resize_target_width']
target_width = config.setting['cover_tags_resize_target_width']
use_height = config.setting['cover_tags_resize_use_height'] use_height = config.setting['cover_tags_resize_use_height']
if use_height: target_height = config.setting['cover_tags_resize_target_height']
target_height = config.setting['cover_tags_resize_target_height'] stretch = config.setting["cover_tags_stretch"]
crop = config.setting["cover_tags_crop"]
else: else:
scale_up = config.setting['cover_file_scale_up'] scale_up = config.setting['cover_file_scale_up']
scale_down = config.setting['cover_file_scale_down'] scale_down = config.setting['cover_file_scale_down']
use_width = config.setting['cover_file_resize_use_width'] use_width = config.setting['cover_file_resize_use_width']
if use_width: target_width = config.setting['cover_file_resize_target_width']
target_width = config.setting['cover_file_resize_target_width']
use_height = config.setting['cover_file_resize_use_height'] use_height = config.setting['cover_file_resize_use_height']
if use_height: target_height = config.setting['cover_file_resize_target_height']
target_height = config.setting['cover_file_resize_target_height'] stretch = config.setting["cover_file_stretch"]
crop = config.setting["cover_file_crop"]
if scale_down and (image.info.width > target_width or image.info.height > target_height): width_scale_factor = 1
aspect_ratio = Qt.AspectRatioMode.KeepAspectRatio width_resize = image.info.width
elif scale_up and (image.info.width < target_width or image.info.height < target_height): if use_width:
aspect_ratio = Qt.AspectRatioMode.KeepAspectRatioByExpanding width_scale_factor = target_width / image.info.width
else: width_resize = target_width
height_scale_factor = 1
height_resize = image.info.height
if use_height:
height_scale_factor = target_height / image.info.height
height_resize = target_height
if (width_scale_factor == 1 and height_scale_factor == 1
or ((width_scale_factor > 1 and height_scale_factor > 1) and not scale_up)
or ((width_scale_factor < 1 or height_scale_factor < 1) and not scale_down)):
# no resizing needed # no resizing needed
return return
qimage = image.get_result() qimage = image.get_result()
if use_width and use_height: if stretch:
scaled_image = qimage.scaled(target_width, target_height, aspect_ratio) scaled_image = qimage.scaled(width_resize, height_resize, Qt.AspectRatioMode.IgnoreAspectRatio)
elif use_width: elif crop:
scaled_image = qimage.scaledToWidth(target_width) scaled_image = qimage.scaled(width_resize, height_resize, Qt.AspectRatioMode.KeepAspectRatioByExpanding)
else: cutoff_width = (scaled_image.width() - width_resize) // 2
scaled_image = qimage.scaledToHeight(target_height) cutoff_height = (scaled_image.height() - height_resize) // 2
scaled_image = scaled_image.copy(cutoff_width, cutoff_height, width_resize, height_resize)
else: # keep aspect ratio
if use_width and use_height:
scaled_image = qimage.scaled(width_resize, height_resize, Qt.AspectRatioMode.KeepAspectRatio)
elif use_width:
scaled_image = qimage.scaledToWidth(width_resize)
else:
scaled_image = qimage.scaledToHeight(height_resize)
log.debug( log.debug(
"Resized cover art from %d x %d to %d x %d in %.2f ms", "Resized cover art from %d x %d to %d x %d in %.2f ms",

View File

@@ -181,12 +181,16 @@ BoolOption('setting', 'cover_tags_resize_use_width', True)
IntOption('setting', 'cover_tags_resize_target_width', DEFAULT_COVER_MAX_SIZE) IntOption('setting', 'cover_tags_resize_target_width', DEFAULT_COVER_MAX_SIZE)
BoolOption('setting', 'cover_tags_resize_use_height', True) BoolOption('setting', 'cover_tags_resize_use_height', True)
IntOption('setting', 'cover_tags_resize_target_height', DEFAULT_COVER_MAX_SIZE) IntOption('setting', 'cover_tags_resize_target_height', DEFAULT_COVER_MAX_SIZE)
BoolOption('setting', 'cover_tags_stretch', False)
BoolOption('setting', 'cover_tags_crop', False)
BoolOption('setting', 'cover_file_scale_up', False) BoolOption('setting', 'cover_file_scale_up', False)
BoolOption('setting', 'cover_file_scale_down', False) BoolOption('setting', 'cover_file_scale_down', False)
BoolOption('setting', 'cover_file_resize_use_width', True) BoolOption('setting', 'cover_file_resize_use_width', True)
IntOption('setting', 'cover_file_resize_target_width', DEFAULT_COVER_MAX_SIZE) IntOption('setting', 'cover_file_resize_target_width', DEFAULT_COVER_MAX_SIZE)
BoolOption('setting', 'cover_file_resize_use_height', True) BoolOption('setting', 'cover_file_resize_use_height', True)
IntOption('setting', 'cover_file_resize_target_height', DEFAULT_COVER_MAX_SIZE) IntOption('setting', 'cover_file_resize_target_height', DEFAULT_COVER_MAX_SIZE)
BoolOption('setting', 'cover_file_stretch', False)
BoolOption('setting', 'cover_file_crop', False)
# picard/ui/options/dialog.py # picard/ui/options/dialog.py
# Attached Profiles # Attached Profiles

View File

@@ -17,7 +17,7 @@ from picard.i18n import gettext as _
class Ui_CoverProcessingOptionsPage(object): class Ui_CoverProcessingOptionsPage(object):
def setupUi(self, CoverProcessingOptionsPage): def setupUi(self, CoverProcessingOptionsPage):
CoverProcessingOptionsPage.setObjectName("CoverProcessingOptionsPage") CoverProcessingOptionsPage.setObjectName("CoverProcessingOptionsPage")
CoverProcessingOptionsPage.resize(478, 361) CoverProcessingOptionsPage.resize(478, 423)
self.verticalLayout = QtWidgets.QVBoxLayout(CoverProcessingOptionsPage) self.verticalLayout = QtWidgets.QVBoxLayout(CoverProcessingOptionsPage)
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName("verticalLayout")
self.filtering = QtWidgets.QGroupBox(parent=CoverProcessingOptionsPage) self.filtering = QtWidgets.QGroupBox(parent=CoverProcessingOptionsPage)
@@ -161,6 +161,23 @@ class Ui_CoverProcessingOptionsPage(object):
self.px_label6.setObjectName("px_label6") self.px_label6.setObjectName("px_label6")
self.horizontalLayout_3.addWidget(self.px_label6) self.horizontalLayout_3.addWidget(self.px_label6)
self.verticalLayout_3.addWidget(self.tags_resize_height_widget) self.verticalLayout_3.addWidget(self.tags_resize_height_widget)
self.tags_resize_mode = QtWidgets.QWidget(parent=self.save_to_tags)
self.tags_resize_mode.setObjectName("tags_resize_mode")
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.tags_resize_mode)
self.verticalLayout_5.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_5.setSpacing(2)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.tags_keep = QtWidgets.QRadioButton(parent=self.tags_resize_mode)
self.tags_keep.setChecked(True)
self.tags_keep.setObjectName("tags_keep")
self.verticalLayout_5.addWidget(self.tags_keep)
self.tags_crop = QtWidgets.QRadioButton(parent=self.tags_resize_mode)
self.tags_crop.setObjectName("tags_crop")
self.verticalLayout_5.addWidget(self.tags_crop)
self.tags_stretch = QtWidgets.QRadioButton(parent=self.tags_resize_mode)
self.tags_stretch.setObjectName("tags_stretch")
self.verticalLayout_5.addWidget(self.tags_stretch)
self.verticalLayout_3.addWidget(self.tags_resize_mode)
self.horizontalLayout_7.addWidget(self.save_to_tags) self.horizontalLayout_7.addWidget(self.save_to_tags)
self.save_to_file = QtWidgets.QGroupBox(parent=self.resizing) self.save_to_file = QtWidgets.QGroupBox(parent=self.resizing)
self.save_to_file.setCheckable(False) self.save_to_file.setCheckable(False)
@@ -236,6 +253,23 @@ class Ui_CoverProcessingOptionsPage(object):
self.px_label4.setObjectName("px_label4") self.px_label4.setObjectName("px_label4")
self.horizontalLayout_4.addWidget(self.px_label4) self.horizontalLayout_4.addWidget(self.px_label4)
self.verticalLayout_4.addWidget(self.file_resize_height_widget) self.verticalLayout_4.addWidget(self.file_resize_height_widget)
self.file_resize_mode = QtWidgets.QWidget(parent=self.save_to_file)
self.file_resize_mode.setObjectName("file_resize_mode")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.file_resize_mode)
self.verticalLayout_6.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_6.setSpacing(2)
self.verticalLayout_6.setObjectName("verticalLayout_6")
self.file_keep = QtWidgets.QRadioButton(parent=self.file_resize_mode)
self.file_keep.setChecked(True)
self.file_keep.setObjectName("file_keep")
self.verticalLayout_6.addWidget(self.file_keep)
self.file_crop = QtWidgets.QRadioButton(parent=self.file_resize_mode)
self.file_crop.setObjectName("file_crop")
self.verticalLayout_6.addWidget(self.file_crop)
self.file_stretch = QtWidgets.QRadioButton(parent=self.file_resize_mode)
self.file_stretch.setObjectName("file_stretch")
self.verticalLayout_6.addWidget(self.file_stretch)
self.verticalLayout_4.addWidget(self.file_resize_mode)
self.horizontalLayout_7.addWidget(self.save_to_file) self.horizontalLayout_7.addWidget(self.save_to_file)
self.verticalLayout.addWidget(self.resizing) self.verticalLayout.addWidget(self.resizing)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
@@ -259,6 +293,9 @@ class Ui_CoverProcessingOptionsPage(object):
self.px_label5.setText(_("px")) self.px_label5.setText(_("px"))
self.tags_resize_height_label.setText(_("Height:")) self.tags_resize_height_label.setText(_("Height:"))
self.px_label6.setText(_("px")) self.px_label6.setText(_("px"))
self.tags_keep.setText(_("Keep aspect ratio"))
self.tags_crop.setText(_("Crop scaled overflow"))
self.tags_stretch.setText(_("Stretch/shrink to target"))
self.save_to_file.setTitle(_("Resize images saved to files")) self.save_to_file.setTitle(_("Resize images saved to files"))
self.file_scale_up.setText(_("Scale up")) self.file_scale_up.setText(_("Scale up"))
self.file_scale_down.setText(_("Scale down")) self.file_scale_down.setText(_("Scale down"))
@@ -266,3 +303,6 @@ class Ui_CoverProcessingOptionsPage(object):
self.px_label3.setText(_("px")) self.px_label3.setText(_("px"))
self.file_resize_height_label.setText(_("Height:")) self.file_resize_height_label.setText(_("Height:"))
self.px_label4.setText(_("px")) self.px_label4.setText(_("px"))
self.file_keep.setText(_("Keep aspect ratio"))
self.file_crop.setText(_("Crop scaled overflow"))
self.file_stretch.setText(_("Stretch/shrink to target"))

View File

@@ -50,12 +50,16 @@ class CoverProcessingOptionsPage(OptionsPage):
self.register_setting('cover_tags_resize_target_width') self.register_setting('cover_tags_resize_target_width')
self.register_setting('cover_tags_resize_use_height') self.register_setting('cover_tags_resize_use_height')
self.register_setting('cover_tags_resize_target_height') self.register_setting('cover_tags_resize_target_height')
self.register_setting('cover_tags_stretch')
self.register_setting('cover_tags_crop')
self.register_setting('cover_file_scale_up') self.register_setting('cover_file_scale_up')
self.register_setting('cover_file_scale_down') self.register_setting('cover_file_scale_down')
self.register_setting('cover_file_resize_use_width') self.register_setting('cover_file_resize_use_width')
self.register_setting('cover_file_resize_target_width') self.register_setting('cover_file_resize_target_width')
self.register_setting('cover_file_resize_use_height') self.register_setting('cover_file_resize_use_height')
self.register_setting('cover_file_resize_target_height') self.register_setting('cover_file_resize_target_height')
self.register_setting('cover_file_stretch')
self.register_setting('cover_file_crop')
tags_checkboxes = (self.ui.tags_resize_width_label, self.ui.tags_resize_height_label) tags_checkboxes = (self.ui.tags_resize_width_label, self.ui.tags_resize_height_label)
tags_at_least_one_checked = partial(self._ensure_at_least_one_checked, tags_checkboxes) tags_at_least_one_checked = partial(self._ensure_at_least_one_checked, tags_checkboxes)
@@ -96,12 +100,16 @@ class CoverProcessingOptionsPage(OptionsPage):
self.ui.tags_resize_width_value.setValue(config.setting['cover_tags_resize_target_width']) self.ui.tags_resize_width_value.setValue(config.setting['cover_tags_resize_target_width'])
self.ui.tags_resize_height_label.setChecked(config.setting['cover_tags_resize_use_height']) self.ui.tags_resize_height_label.setChecked(config.setting['cover_tags_resize_use_height'])
self.ui.tags_resize_height_value.setValue(config.setting['cover_tags_resize_target_height']) self.ui.tags_resize_height_value.setValue(config.setting['cover_tags_resize_target_height'])
self.ui.tags_stretch.setChecked(config.setting['cover_tags_stretch'])
self.ui.tags_crop.setChecked(config.setting['cover_tags_crop'])
self.ui.file_scale_up.setChecked(config.setting['cover_file_scale_up']) self.ui.file_scale_up.setChecked(config.setting['cover_file_scale_up'])
self.ui.file_scale_down.setChecked(config.setting['cover_file_scale_down']) self.ui.file_scale_down.setChecked(config.setting['cover_file_scale_down'])
self.ui.file_resize_width_label.setChecked(config.setting['cover_file_resize_use_width']) self.ui.file_resize_width_label.setChecked(config.setting['cover_file_resize_use_width'])
self.ui.file_resize_width_value.setValue(config.setting['cover_file_resize_target_width']) self.ui.file_resize_width_value.setValue(config.setting['cover_file_resize_target_width'])
self.ui.file_resize_height_label.setChecked(config.setting['cover_file_resize_use_height']) self.ui.file_resize_height_label.setChecked(config.setting['cover_file_resize_use_height'])
self.ui.file_resize_height_value.setValue(config.setting['cover_file_resize_target_height']) self.ui.file_resize_height_value.setValue(config.setting['cover_file_resize_target_height'])
self.ui.file_stretch.setChecked(config.setting['cover_file_stretch'])
self.ui.file_crop.setChecked(config.setting['cover_file_crop'])
def save(self): def save(self):
config = get_config() config = get_config()
@@ -114,12 +122,16 @@ class CoverProcessingOptionsPage(OptionsPage):
config.setting['cover_tags_resize_target_width'] = self.ui.tags_resize_width_value.value() config.setting['cover_tags_resize_target_width'] = self.ui.tags_resize_width_value.value()
config.setting['cover_tags_resize_use_height'] = self.ui.tags_resize_height_label.isChecked() config.setting['cover_tags_resize_use_height'] = self.ui.tags_resize_height_label.isChecked()
config.setting['cover_tags_resize_target_height'] = self.ui.tags_resize_height_value.value() config.setting['cover_tags_resize_target_height'] = self.ui.tags_resize_height_value.value()
config.setting['cover_tags_stretch'] = self.ui.tags_stretch.isChecked()
config.setting['cover_tags_crop'] = self.ui.tags_crop.isChecked()
config.setting['cover_file_scale_up'] = self.ui.file_scale_up.isChecked() config.setting['cover_file_scale_up'] = self.ui.file_scale_up.isChecked()
config.setting['cover_file_scale_down'] = self.ui.file_scale_down.isChecked() config.setting['cover_file_scale_down'] = self.ui.file_scale_down.isChecked()
config.setting['cover_file_resize_use_width'] = self.ui.file_resize_width_label.isChecked() config.setting['cover_file_resize_use_width'] = self.ui.file_resize_width_label.isChecked()
config.setting['cover_file_resize_target_width'] = self.ui.file_resize_width_value.value() config.setting['cover_file_resize_target_width'] = self.ui.file_resize_width_value.value()
config.setting['cover_file_resize_use_height'] = self.ui.file_resize_height_label.isChecked() config.setting['cover_file_resize_use_height'] = self.ui.file_resize_height_label.isChecked()
config.setting['cover_file_resize_target_height'] = self.ui.file_resize_height_value.value() config.setting['cover_file_resize_target_height'] = self.ui.file_resize_height_value.value()
config.setting['cover_file_stretch'] = self.ui.file_stretch.isChecked()
config.setting['cover_file_crop'] = self.ui.file_crop.isChecked()
register_options_page(CoverProcessingOptionsPage) register_options_page(CoverProcessingOptionsPage)

View File

@@ -86,12 +86,16 @@ class ImageProcessorsTest(PicardTestCase):
'cover_tags_resize_target_width': 500, 'cover_tags_resize_target_width': 500,
'cover_tags_resize_use_height': True, 'cover_tags_resize_use_height': True,
'cover_tags_resize_target_height': 500, 'cover_tags_resize_target_height': 500,
'cover_tags_stretch': False,
'cover_tags_crop': False,
'cover_file_scale_up': True, 'cover_file_scale_up': True,
'cover_file_scale_down': True, 'cover_file_scale_down': True,
'cover_file_resize_use_width': True, 'cover_file_resize_use_width': True,
'cover_file_resize_target_width': 750, 'cover_file_resize_target_width': 750,
'cover_file_resize_use_height': True, 'cover_file_resize_use_height': True,
'cover_file_resize_target_height': 750, 'cover_file_resize_target_height': 750,
'cover_file_stretch': False,
'cover_file_crop': False,
'save_images_to_tags': True, 'save_images_to_tags': True,
'save_images_to_files': True, 'save_images_to_files': True,
} }
@@ -182,8 +186,8 @@ class ImageProcessorsTest(PicardTestCase):
def test_scale_up_both_dimensions(self): def test_scale_up_both_dimensions(self):
self.set_config_values(self.settings) self.set_config_values(self.settings)
self._check_resize_image((250, 250), (500, 500)) self._check_resize_image((250, 250), (500, 500))
self._check_resize_image((400, 500), (500, 625)) self._check_resize_image((400, 500), (400, 500))
self._check_resize_image((500, 250), (1000, 500)) self._check_resize_image((250, 150), (500, 300))
def test_scale_up_only_width(self): def test_scale_up_only_width(self):
settings = copy(self.settings) settings = copy(self.settings)
@@ -211,6 +215,64 @@ class ImageProcessorsTest(PicardTestCase):
self._check_resize_image((750, 750), (500, 500)) self._check_resize_image((750, 750), (500, 500))
self.set_config_values(self.settings) self.set_config_values(self.settings)
def test_stretch_both_dimensions(self):
settings = copy(self.settings)
settings["cover_tags_stretch"] = True
self.set_config_values(settings)
self._check_resize_image((1000, 100), (500, 500))
self._check_resize_image((200, 500), (500, 500))
self._check_resize_image((200, 2000), (500, 500))
self.set_config_values(self.settings)
def test_stretch_only_width(self):
settings = copy(self.settings)
settings["cover_tags_stretch"] = True
settings["cover_tags_resize_use_height"] = False
self.set_config_values(settings)
self._check_resize_image((1000, 100), (500, 100))
self._check_resize_image((200, 500), (500, 500))
self._check_resize_image((200, 2000), (500, 2000))
self.set_config_values(self.settings)
def test_stretch_only_height(self):
settings = copy(self.settings)
settings["cover_tags_stretch"] = True
settings["cover_tags_resize_use_width"] = False
self.set_config_values(settings)
self._check_resize_image((1000, 100), (1000, 500))
self._check_resize_image((200, 500), (200, 500))
self._check_resize_image((200, 2000), (200, 500))
self.set_config_values(self.settings)
def test_crop_both_dimensions(self):
settings = copy(self.settings)
settings["cover_tags_crop"] = True
self.set_config_values(settings)
self._check_resize_image((1000, 100), (500, 500))
self._check_resize_image((750, 1000), (500, 500))
self._check_resize_image((250, 1000), (500, 500))
self.set_config_values(self.settings)
def test_crop_only_width(self):
settings = copy(self.settings)
settings["cover_tags_crop"] = True
settings["cover_tags_resize_use_height"] = False
self.set_config_values(settings)
self._check_resize_image((1000, 100), (500, 100))
self._check_resize_image((750, 1000), (500, 1000))
self._check_resize_image((250, 1000), (500, 1000))
self.set_config_values(self.settings)
def test_crop_only_height(self):
settings = copy(self.settings)
settings["cover_tags_crop"] = True
settings["cover_tags_resize_use_width"] = False
self.set_config_values(settings)
self._check_resize_image((1000, 100), (1000, 500))
self._check_resize_image((750, 1000), (750, 500))
self._check_resize_image((250, 1000), (250, 500))
self.set_config_values(self.settings)
def test_identification_error(self): def test_identification_error(self):
image = create_fake_image(0, 0, "jpg") image = create_fake_image(0, 0, "jpg")
coverartimage = CoverArtImage() coverartimage = CoverArtImage()

View File

@@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>478</width> <width>478</width>
<height>361</height> <height>423</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -307,6 +307,51 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QWidget" name="tags_resize_mode" native="true">
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="tags_keep">
<property name="text">
<string>Keep aspect ratio</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="tags_crop">
<property name="text">
<string>Crop scaled overflow</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="tags_stretch">
<property name="text">
<string>Stretch/shrink to target</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@@ -468,6 +513,51 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QWidget" name="file_resize_mode" native="true">
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="file_keep">
<property name="text">
<string>Keep aspect ratio</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="file_crop">
<property name="text">
<string>Crop scaled overflow</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="file_stretch">
<property name="text">
<string>Stretch/shrink to target</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>