Webp support (#80)

* Add basic webp support

Co-authored-by: Hugo Posnic <hugo.posnic@protonmail.com>
This commit is contained in:
olokelo 2021-06-29 22:37:52 +02:00 committed by GitHub
parent 21fe25205b
commit cbd3acaf92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 203 additions and 43 deletions

View File

@ -2,13 +2,13 @@
## Compress your images
Curtail (previously ImCompressor) is an useful image compressor, supporting PNG and JPEG file types.
Curtail (previously ImCompressor) is an useful image compressor, supporting PNG, JPEG and WEBP 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
PNG, JPEG, WEBP
## Screenshot
@ -56,6 +56,7 @@ Curtail uses a number of open source projects to work properly:
- [OptiPNG](http://optipng.sourceforge.net)
- [pngquant](https://pngquant.org)
- [Jpegoptim](https://github.com/tjko/jpegoptim)
- [libwebp](https://storage.googleapis.com/downloads.webmproject.org/releases/webp/index.html)
## Donations

View File

@ -44,6 +44,16 @@
}
]
},
{
"name": "libwebp",
"sources": [
{
"type": "archive",
"url": "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.2.0.tar.gz",
"sha256": "2fc8bbde9f97f2ab403c0224fb9ca62b2e6852cbc519e91ceaa7c153ffd88a0c"
}
]
},
{
"name": "curtail",
"builddir": true,

View File

@ -7,7 +7,7 @@
<name>Curtail</name>
<summary>Compress your images</summary>
<description>
<p>Curtail is an useful image compressor, supporting PNG and JPEG file types.</p>
<p>Curtail is an useful image compressor, supporting PNG, JPEG and WEBP file types.</p>
<p>It support both lossless and lossy compression modes with an option to whether keep or not metadata of images.</p>
</description>

View File

@ -30,11 +30,21 @@
<default>2</default>
<summary>PNG Lossless Compression Level</summary>
<description>Lossless compression level to use for PNG images.</description>
</key>
<key type="i" name="webp-lossless-level">
<default>4</default>
<summary>WEBP Lossless Compression Level</summary>
<description>Lossless compression level to use for WEBP images.</description>
</key>
<key type="i" name="jpg-lossy-level">
<default>90</default>
<summary>JPG Lossy Compression Level</summary>
<description>Lossy compression level to use for JPG images.</description>
</key>
<key type="i" name="webp-lossy-level">
<default>70</default>
<summary>WEBP Lossy Compression Level</summary>
<description>Lossy compression level to use for WEBP images.</description>
</key>
<key type="b" name="jpg-progressive">
<default>false</default>

3
debian/control vendored
View File

@ -22,7 +22,8 @@ Depends: ${misc:Depends},
python3,
optipng,
pngquant,
jpegoptim
jpegoptim,
webp
Description: Compress your images
Curtail (previously ImCompressor) is an useful image compressor, supporting PNG and JPEG file types.
It support both lossless and lossy compression modes with an option to whether keep or not metadata of images.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: curtail\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-12 19:14+0100\n"
"POT-Creation-Date: 2021-06-16 18:12+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"
@ -24,13 +24,14 @@ msgstr ""
#: data/com.github.huluti.Curtail.desktop.in:5
#: data/com.github.huluti.Curtail.appdata.xml.in:8 src/ui/window.ui:213
#: src/window.py:308
#: src/window.py:309
msgid "Compress your images"
msgstr ""
#: data/com.github.huluti.Curtail.appdata.xml.in:10
msgid ""
"Curtail is an useful image compressor, supporting PNG and JPEG file types."
"Curtail is an useful image compressor, supporting PNG, JPEG and WEBP file "
"types."
msgstr ""
#: data/com.github.huluti.Curtail.appdata.xml.in:11
@ -308,7 +309,7 @@ msgstr ""
msgid "Save the compressed image into a new file."
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:11 src/ui/preferences.ui:125
#: data/com.github.huluti.Curtail.gschema.xml:11 src/ui/preferences.ui:135
msgid "Keep metadata"
msgstr ""
@ -324,7 +325,7 @@ msgstr ""
msgid "Use lossy mode to compress images."
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:21 src/ui/preferences.ui:75
#: data/com.github.huluti.Curtail.gschema.xml:21 src/ui/preferences.ui:85
msgid "Suffix to append at end of new file"
msgstr ""
@ -332,7 +333,7 @@ msgstr ""
msgid "Suffix to append at end of new file."
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:26 src/ui/preferences.ui:167
#: data/com.github.huluti.Curtail.gschema.xml:26 src/ui/preferences.ui:177
msgid "PNG Lossy Compression Level"
msgstr ""
@ -348,27 +349,43 @@ msgstr ""
msgid "Lossless compression level to use for PNG images."
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:36 src/ui/preferences.ui:194
msgid "JPG Lossy Compression Level"
#: data/com.github.huluti.Curtail.gschema.xml:36
msgid "WEBP Lossless Compression Level"
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:37
msgid "Lossy compression level to use for JPG images."
msgid "Lossless compression level to use for WEBP images."
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:41
msgid "Enable progressive encoding for jpegs"
#: data/com.github.huluti.Curtail.gschema.xml:41 src/ui/preferences.ui:204
msgid "JPG Lossy Compression Level"
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:42
msgid "Optionally encode jpeg images progressively."
msgid "Lossy compression level to use for JPG images."
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:46 src/ui/preferences.ui:49
msgid "Enable dark theme"
#: data/com.github.huluti.Curtail.gschema.xml:46 src/ui/preferences.ui:217
msgid "WEBP Lossy Compression Level"
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:47
msgid "Lossy compression level to use for WEBP images."
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:51
msgid "Enable progressive encoding for jpegs"
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:52
msgid "Optionally encode jpeg images progressively."
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:56 src/ui/preferences.ui:59
msgid "Enable dark theme"
msgstr ""
#: data/com.github.huluti.Curtail.gschema.xml:57
msgid "Use dark theme for the windows."
msgstr ""
@ -380,7 +397,7 @@ msgstr ""
msgid "or"
msgstr ""
#: src/ui/window.ui:75 src/window.py:168
#: src/ui/window.ui:75 src/window.py:169
msgid "Browse your files"
msgstr ""
@ -392,33 +409,39 @@ msgstr ""
msgid "Lossy"
msgstr ""
#: src/ui/preferences.ui:22 src/ui/menu.ui:6
#: src/ui/preferences.ui:32 src/ui/menu.ui:6
msgid "Preferences"
msgstr ""
#: src/ui/preferences.ui:99
#: src/ui/preferences.ui:109
msgid "Save the compressed image into a new file"
msgstr ""
#: src/ui/preferences.ui:148
#: src/ui/preferences.ui:158
msgid "General"
msgstr ""
#: src/ui/preferences.ui:218
#: src/ui/preferences.ui:255
msgid "Compression"
msgstr ""
#: src/ui/preferences.ui:250
#: src/ui/preferences.ui:288
msgid ""
"PNG Lossless Compression Level\n"
"(the higher it is, the slower it is)"
msgstr ""
#: src/ui/preferences.ui:264
#: src/ui/preferences.ui:315
msgid ""
"WEBP Lossless Compression Level\n"
"(the higher it is, the slower it is)"
msgstr ""
#: src/ui/preferences.ui:329
msgid "Progressive Encode JPG"
msgstr ""
#: src/ui/preferences.ui:287
#: src/ui/preferences.ui:352
msgid "Advanced"
msgstr ""
@ -426,27 +449,27 @@ msgstr ""
msgid "About Curtail"
msgstr ""
#: src/window.py:88
#: src/window.py:89
msgid "Filename"
msgstr ""
#: src/window.py:89
#: src/window.py:90
msgid "Old Size"
msgstr ""
#: src/window.py:90
#: src/window.py:91
msgid "New Size"
msgstr ""
#: src/window.py:91
#: src/window.py:92
msgid "Savings"
msgstr ""
#: src/window.py:155
#: src/window.py:156
msgid "Images are saved with <b>'{}' suffix</b>."
msgstr ""
#: src/window.py:158
#: src/window.py:159
msgid "Images are <b>overwritten</b>."
msgstr ""
@ -458,27 +481,27 @@ msgstr ""
msgid "The file {} already exists. Do you want to compress the image anyway?"
msgstr ""
#: src/window.py:242
#: src/window.py:243
msgid "Format not supported"
msgstr ""
#: src/window.py:243
#: src/window.py:244
msgid "The format of {} is not supported."
msgstr ""
#: src/window.py:247
#: src/window.py:248
msgid "Path not valid"
msgstr ""
#: src/window.py:248
#: src/window.py:249
msgid "{} doesn't exist."
msgstr ""
#: src/window.py:307
#: src/window.py:308
msgid "translator-credits"
msgstr ""
#: src/window.py:309
#: src/window.py:310
msgid "Distributed under the GNU GPL(v3) license.\n"
msgstr ""
@ -490,10 +513,14 @@ msgstr ""
msgid "All images"
msgstr ""
#: src/tools.py:52
#: src/tools.py:53
msgid "PNG images"
msgstr ""
#: src/tools.py:56
#: src/tools.py:57
msgid "JPEG images"
msgstr ""
#: src/tools.py:61
msgid "WEBP images"
msgstr ""

View File

@ -71,6 +71,8 @@ class Compressor():
command = self.build_png_command(lossy, metadata)
elif file_type == 'jpg':
command = self.build_jpg_command(lossy, metadata)
elif file_type == 'webp':
command = self.build_webp_command(lossy, metadata)
self.run_command(command) # compress image
def command_finished(self, stdout, condition):
@ -139,5 +141,27 @@ class Compressor():
command = jpegoptim2.format(self.filename)
return command
def build_webp_command(self, lossy, metadata):
command = "cwebp " + self.filename
# cwebp doesn't preserve any metadata by default
if metadata:
command += " -metadata all"
if lossy:
quality = self._settings.get_int('webp-lossy-level')
else:
command += " -lossless"
quality = 100 # maximum cpu power for lossless
compression_level = self._settings.get_int('webp-lossless-level')
# multithreaded, (lossless) compression mode, quality, output
command += " -mt -m {}".format(compression_level)
command += " -q {}".format(quality)
command += " -o {}".format(self.new_filename)
return command
def feed(self, stdout, condition):
return True

View File

@ -34,7 +34,9 @@ class CurtailPrefsWindow(Gtk.Window):
entry_suffix = Gtk.Template.Child()
spin_png_lossy_level = Gtk.Template.Child()
spin_png_lossless_level = Gtk.Template.Child()
spin_webp_lossless_level = Gtk.Template.Child()
spin_jpg_lossy_level = Gtk.Template.Child()
spin_webp_lossy_level = Gtk.Template.Child()
toggle_jpg_progressive = Gtk.Template.Child()
toggle_dark_theme = Gtk.Template.Child()
@ -77,12 +79,24 @@ class CurtailPrefsWindow(Gtk.Window):
self.spin_png_lossless_level.connect('value-changed',
self.on_int_changed, 'png-lossless-level')
# WEBP Lossless Compression Level
self.spin_webp_lossless_level.set_value(
self._settings.get_int('webp-lossless-level'))
self.spin_webp_lossless_level.connect('value-changed',
self.on_int_changed, 'webp-lossless-level')
# JPG Lossy Compression Level
self.spin_jpg_lossy_level.set_value(
self._settings.get_int('jpg-lossy-level'))
self.spin_jpg_lossy_level.connect('value-changed',
self.on_int_changed, 'jpg-lossy-level')
# WEBP Lossy Compression Level
self.spin_webp_lossy_level.set_value(
self._settings.get_int('webp-lossy-level'))
self.spin_webp_lossy_level.connect('value-changed',
self.on_int_changed, 'webp-lossy-level')
# Progressively Encode JPG
self.toggle_jpg_progressive.set_active(self._settings.get_boolean('jpg-progressive'))
self.toggle_jpg_progressive.connect('notify::active', self.on_bool_changed,

View File

@ -47,6 +47,7 @@ def add_filechooser_filters(dialog):
all_images.set_name(_("All images"))
all_images.add_mime_type('image/jpeg')
all_images.add_mime_type('image/png')
all_images.add_mime_type('image/webp')
png_images = Gtk.FileFilter()
png_images.set_name(_("PNG images"))
@ -56,9 +57,14 @@ def add_filechooser_filters(dialog):
jpeg_images.set_name(_("JPEG images"))
jpeg_images.add_mime_type('image/jpeg')
webp_images = Gtk.FileFilter()
webp_images.set_name(_("WEBP images"))
webp_images.add_mime_type('image/webp')
dialog.add_filter(all_images)
dialog.add_filter(png_images)
dialog.add_filter(jpeg_images)
dialog.add_filter(webp_images)
def get_file_type(filename):
@ -68,6 +74,8 @@ def get_file_type(filename):
return 'jpg'
elif content_type == 'image/png':
return 'png'
elif content_type == 'image/webp':
return 'webp'
else:
return None
else:

View File

@ -12,11 +12,21 @@
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkAdjustment" id="webp_lossless_adj">
<property name="upper">6</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkAdjustment" id="png_lossy_adj">
<property name="upper">100</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkAdjustment" id="webp_lossy_adj">
<property name="upper">100</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<template class="CurtailPrefsWindow" parent="GtkWindow">
<property name="can-focus">False</property>
<property name="title" translatable="yes">Preferences</property>
@ -198,6 +208,33 @@
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="label" translatable="yes">WEBP Lossy Compression Level</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spin_webp_lossy_level">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="halign">end</property>
<property name="hexpand">True</property>
<property name="text">0</property>
<property name="adjustment">webp_lossy_adj</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spin_jpg_lossy_level">
<property name="visible">True</property>
@ -247,6 +284,7 @@
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">PNG Lossless Compression Level
(the higher it is, the slower it is)</property>
</object>
@ -255,6 +293,33 @@
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spin_webp_lossless_level">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="halign">end</property>
<property name="hexpand">True</property>
<property name="text">0</property>
<property name="adjustment">webp_lossless_adj</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">WEBP Lossless Compression Level
(the higher it is, the slower it is)</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
@ -265,7 +330,7 @@
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
@ -278,7 +343,7 @@
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
</object>

View File

@ -222,7 +222,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')
return file_type in ('png', 'jpg', 'webp')
else:
return False