mirror of
https://github.com/Huluti/Curtail.git
synced 2024-07-07 02:56:21 +03:00
Add support for SVG images
This commit is contained in:
parent
5fde80b40c
commit
0f7803a82c
|
@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
|
|||
## [1.7.0] - DEV
|
||||
|
||||
### Added
|
||||
- 🌟 SVG support.
|
||||
- New start screen with an AdwStatusPage.
|
||||
- Add debug information in about window.
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
## Compress your images
|
||||
|
||||
Curtail (previously ImCompressor) is an useful image compressor, supporting PNG, JPEG and WebP file types.
|
||||
Curtail (previously ImCompressor) is an useful image compressor, supporting PNG, JPEG, WebP and SVG file types.
|
||||
It support both lossless and lossy compression modes with an option to whether keep or not metadata of images.
|
||||
It is inspired by [Trimage](https://github.com/Kilian/Trimage) and [Image-Optimizer](https://github.com/GijsGoudzwaard/Image-Optimizer).
|
||||
|
||||
### Supported formats
|
||||
|
||||
PNG, JPEG, WebP
|
||||
PNG, JPEG, WebP, SVG
|
||||
|
||||
## Screenshot
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"python3-scour.json",
|
||||
{
|
||||
"name": "curtail",
|
||||
"builddir": true,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<name translatable="no">Curtail</name>
|
||||
<summary>Compress your images</summary>
|
||||
<description>
|
||||
<p>Optimize your images with Curtail, a useful image compressor that supports PNG, JPEG and WebP file types.</p>
|
||||
<p>Optimize your images with Curtail, a useful image compressor that supports PNG, JPEG, WebP and SVG file types.</p>
|
||||
<p>It supports both lossless and lossy compression modes with an option to whether keep or not metadata of images.</p>
|
||||
</description>
|
||||
<developer_name translatable="no">Hugo Posnic</developer_name>
|
||||
|
|
|
@ -53,8 +53,13 @@
|
|||
</key>
|
||||
<key type="b" name="jpg-progressive">
|
||||
<default>false</default>
|
||||
<summary>Enable progressive encoding for jpegs</summary>
|
||||
<summary>Enable progressive encoding for JPEG images.</summary>
|
||||
<description>Optionally encode jpeg images progressively.</description>
|
||||
</key>
|
||||
<key type="b" name="svg-maximum-level">
|
||||
<default>false</default>
|
||||
<summary>Enable maximum compression for SVG images.</summary>
|
||||
<description>Optionally enable maximum cleaning of SVG images.</description>
|
||||
</key>
|
||||
<key type="i" name="compression-timeout">
|
||||
<default>30</default>
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>"
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -199,6 +199,22 @@
|
|||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="no">SVG</property>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">SVG Maximum Compression Level</property>
|
||||
<property name="subtitle" translatable="yes">Can be more destructive for the image</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="toggle_svg_maximum_level">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: curtail\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-04-03 17:17+0200\n"
|
||||
"POT-Creation-Date: 2023-04-04 22:47+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -25,7 +25,7 @@ msgstr ""
|
|||
#: data/com.github.huluti.Curtail.appdata.xml.in:11
|
||||
msgid ""
|
||||
"Optimize your images with Curtail, a useful image compressor that supports "
|
||||
"PNG, JPEG and WebP file types."
|
||||
"PNG, JPEG, WebP and SVG file types."
|
||||
msgstr ""
|
||||
|
||||
#: data/com.github.huluti.Curtail.appdata.xml.in:12
|
||||
|
@ -559,7 +559,7 @@ msgid "Lossless compression level to use for WebP images."
|
|||
msgstr ""
|
||||
|
||||
#: data/com.github.huluti.Curtail.gschema.xml:56
|
||||
msgid "Enable progressive encoding for jpegs"
|
||||
msgid "Enable progressive encoding for JPEG images."
|
||||
msgstr ""
|
||||
|
||||
#: data/com.github.huluti.Curtail.gschema.xml:57
|
||||
|
@ -567,10 +567,18 @@ msgid "Optionally encode jpeg images progressively."
|
|||
msgstr ""
|
||||
|
||||
#: data/com.github.huluti.Curtail.gschema.xml:61
|
||||
msgid "Compression Timeout"
|
||||
msgid "Enable maximum compression for SVG images."
|
||||
msgstr ""
|
||||
|
||||
#: data/com.github.huluti.Curtail.gschema.xml:62
|
||||
msgid "Optionally enable maximum cleaning of SVG images."
|
||||
msgstr ""
|
||||
|
||||
#: data/com.github.huluti.Curtail.gschema.xml:66
|
||||
msgid "Compression Timeout"
|
||||
msgstr ""
|
||||
|
||||
#: data/com.github.huluti.Curtail.gschema.xml:67
|
||||
msgid "Compression timeout for each image."
|
||||
msgstr ""
|
||||
|
||||
|
@ -631,6 +639,14 @@ msgstr ""
|
|||
msgid "Progressive Encode JPG"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.ui:207
|
||||
msgid "SVG Maximum Compression Level"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/preferences.ui:208
|
||||
msgid "Can be more destructive for the image"
|
||||
msgstr ""
|
||||
|
||||
#: data/ui/menu.ui:10
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr ""
|
||||
|
@ -667,11 +683,11 @@ msgstr ""
|
|||
msgid "Main Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/compressor.py:86
|
||||
#: src/compressor.py:90
|
||||
msgid "Compression has reached the configured timeout of {} seconds."
|
||||
msgstr ""
|
||||
|
||||
#: src/compressor.py:90
|
||||
#: src/compressor.py:94
|
||||
msgid "An unknown error has occured"
|
||||
msgstr ""
|
||||
|
||||
|
@ -679,20 +695,24 @@ msgstr ""
|
|||
msgid "All images"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools.py:36
|
||||
#: src/tools.py:37
|
||||
msgid "PNG images"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools.py:40
|
||||
#: src/tools.py:41
|
||||
msgid "JPEG images"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools.py:44
|
||||
#: src/tools.py:45
|
||||
msgid "WebP images"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools.py:113 src/tools.py:121 src/tools.py:128 src/tools.py:135
|
||||
#: src/tools.py:163
|
||||
#: src/tools.py:49
|
||||
msgid "SVG images"
|
||||
msgstr ""
|
||||
|
||||
#: src/tools.py:121 src/tools.py:128 src/tools.py:135 src/tools.py:142
|
||||
#: src/tools.py:149 src/tools.py:179
|
||||
msgid "Version not found"
|
||||
msgstr ""
|
||||
|
||||
|
|
14
python3-scour.json
Normal file
14
python3-scour.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "python3-scour",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"scour\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/75/19/f519ef8aa2f379935a44212c5744e2b3a46173bf04e0110fb7f4af4028c9/scour-0.38.2.tar.gz",
|
||||
"sha256": "6881ec26660c130c5ecd996ac6f6b03939dd574198f50773f2508b81a68e0daf"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -49,11 +49,13 @@ class Compressor():
|
|||
self.png_lossless_level = self._settings.get_int('png-lossless-level')
|
||||
|
||||
self.jpg_lossy_level = self._settings.get_int('jpg-lossy-level')
|
||||
self.do_jpg_progressive = self._settings.get_boolean('jpg-progressive')
|
||||
self.jpg_progressive = self._settings.get_boolean('jpg-progressive')
|
||||
|
||||
self.webp_lossless_level = self._settings.get_int('webp-lossless-level')
|
||||
self.webp_lossy_level = self._settings.get_int('webp-lossy-level')
|
||||
|
||||
self.svg_maximum_level = self._settings.get_boolean('svg-maximum-level')
|
||||
|
||||
def compress_images(self):
|
||||
self.thread = threading.Thread(target=self._compress_images)
|
||||
self.thread.start()
|
||||
|
@ -68,6 +70,8 @@ class Compressor():
|
|||
command = self.build_jpg_command(result_item)
|
||||
elif file_type == 'webp':
|
||||
command = self.build_webp_command(result_item)
|
||||
elif file_type == 'svg':
|
||||
command = self.build_svg_command(result_item)
|
||||
self.run_command(command, result_item) # compress image
|
||||
GLib.idle_add(self.c_enable_compression, True)
|
||||
|
||||
|
@ -129,7 +133,7 @@ class Compressor():
|
|||
jpegoptim = 'jpegoptim --max={} -o -f "{}"'
|
||||
jpegoptim2 = 'jpegoptim -o -f "{}"'
|
||||
|
||||
if self.do_jpg_progressive:
|
||||
if self.jpg_progressive:
|
||||
jpegoptim += ' --all-progressive'
|
||||
jpegoptim2 += ' --all-progressive'
|
||||
|
||||
|
@ -174,3 +178,13 @@ class Compressor():
|
|||
|
||||
return command
|
||||
|
||||
def build_svg_command(self, result_item):
|
||||
command = 'scour -i {} -o {}'.format(result_item.filename,
|
||||
result_item.new_filename)
|
||||
|
||||
if self.svg_maximum_level:
|
||||
command += ' --enable-viewboxing --enable-id-stripping'
|
||||
command += ' --enable-comment-stripping --shorten-ids --indent=none'
|
||||
|
||||
return command
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ class CurtailPrefsWindow(Adw.PreferencesWindow):
|
|||
spin_jpg_lossy_level = Gtk.Template.Child()
|
||||
spin_webp_lossy_level = Gtk.Template.Child()
|
||||
toggle_jpg_progressive = Gtk.Template.Child()
|
||||
toggle_svg_maximum_level = Gtk.Template.Child()
|
||||
|
||||
_settings = Gio.Settings.new(SETTINGS_SCHEMA)
|
||||
|
||||
|
@ -113,6 +114,11 @@ class CurtailPrefsWindow(Adw.PreferencesWindow):
|
|||
self.toggle_jpg_progressive.connect('notify::active', self.on_bool_changed,
|
||||
'jpg-progressive')
|
||||
|
||||
# Maxium SVG compression
|
||||
self.toggle_svg_maximum_level.set_active(self._settings.get_boolean('svg-maximum-level'))
|
||||
self.toggle_svg_maximum_level.connect('notify::active', self.on_bool_changed,
|
||||
'svg-maximum-level')
|
||||
|
||||
def on_bool_changed(self, switch, state, key):
|
||||
self._settings.set_boolean(key, switch.get_active())
|
||||
# Additional actions
|
||||
|
|
29
src/tools.py
29
src/tools.py
|
@ -31,6 +31,7 @@ def add_filechooser_filters(dialog):
|
|||
all_images.add_mime_type('image/jpeg')
|
||||
all_images.add_mime_type('image/png')
|
||||
all_images.add_mime_type('image/webp')
|
||||
all_images.add_mime_type('image/svg+xml')
|
||||
|
||||
png_images = Gtk.FileFilter()
|
||||
png_images.set_name(_("PNG images"))
|
||||
|
@ -44,11 +45,16 @@ def add_filechooser_filters(dialog):
|
|||
webp_images.set_name(_("WebP images"))
|
||||
webp_images.add_mime_type('image/webp')
|
||||
|
||||
svg_images = Gtk.FileFilter()
|
||||
svg_images.set_name(_("SVG images"))
|
||||
svg_images.add_mime_type('image/svg+xml')
|
||||
|
||||
file_filters = Gio.ListStore.new(Gtk.FileFilter)
|
||||
file_filters.append(all_images)
|
||||
file_filters.append(png_images)
|
||||
file_filters.append(jpeg_images)
|
||||
file_filters.append(webp_images)
|
||||
file_filters.append(svg_images)
|
||||
|
||||
dialog.set_filters(file_filters)
|
||||
|
||||
|
@ -62,6 +68,8 @@ def get_file_type(filename):
|
|||
return 'png'
|
||||
elif content_type == 'image/webp':
|
||||
return 'webp'
|
||||
elif content_type == 'image/svg+xml':
|
||||
return 'svg'
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
|
@ -109,42 +117,51 @@ def debug_infos():
|
|||
try:
|
||||
jpegoptim = subprocess.check_output(['jpegoptim', '--version'])
|
||||
jpegoptim = extract_version(jpegoptim.decode('utf-8'))
|
||||
except Exception as err:
|
||||
except Exception:
|
||||
jpegoptim = _('Version not found')
|
||||
|
||||
# Oxipng
|
||||
try:
|
||||
oxipng = subprocess.check_output(['oxipng', '--version'])
|
||||
oxipng = extract_version(oxipng.decode('utf-8'))
|
||||
except Exception as err:
|
||||
except Exception:
|
||||
oxipng = _('Version not found')
|
||||
|
||||
# pngquant
|
||||
try:
|
||||
pngquant = subprocess.check_output(['pngquant', '--version'])
|
||||
pngquant = extract_version(pngquant.decode('utf-8'))
|
||||
except Exception as err:
|
||||
except Exception:
|
||||
pngquant = _('Version not found')
|
||||
|
||||
# Libwebp
|
||||
try:
|
||||
libwebp = subprocess.check_output(['cwebp', '-version'])
|
||||
libwebp = extract_version(libwebp.decode('utf-8'))
|
||||
except Exception as err:
|
||||
except Exception:
|
||||
libwebp = _('Version not found')
|
||||
|
||||
# Scour
|
||||
try:
|
||||
scour = subprocess.check_output(['scour', '--version'])
|
||||
scour = extract_version(scour.decode('utf-8'))
|
||||
except Exception:
|
||||
scour = _('Version not found')
|
||||
|
||||
debug = '''Python: {}\n
|
||||
Gtk: {}\n
|
||||
Jpegoptim: {}\n
|
||||
Oxipng: {}\n
|
||||
pngquant: {}\n
|
||||
Libwebp: {}\n'''.format(
|
||||
Libwebp: {}\n
|
||||
Scour: {}\n'''.format(
|
||||
python_version,
|
||||
gtk_version,
|
||||
jpegoptim,
|
||||
oxipng,
|
||||
pngquant,
|
||||
libwebp
|
||||
libwebp,
|
||||
scour
|
||||
)
|
||||
|
||||
return debug
|
||||
|
|
|
@ -226,7 +226,7 @@ class CurtailWindow(Gtk.ApplicationWindow):
|
|||
def check_extension(self, filename):
|
||||
file_type = get_file_type(filename)
|
||||
if file_type:
|
||||
return file_type in ('png', 'jpg', 'webp')
|
||||
return file_type in ('png', 'jpg', 'webp', 'svg')
|
||||
else:
|
||||
return False
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user