huluti / curtail Goto Github PK
View Code? Open in Web Editor NEWSimple & useful image compressor.
License: GNU General Public License v3.0
Simple & useful image compressor.
License: GNU General Public License v3.0
When saving into a new file is enabled it is possible to set empty new file suffix, which leads to incorrect compression for JPEG (file is overwritten with 0 bytes file).
Besides that, "Save the compressed file into a new file" option seems redundant. As I imagine it, there should be just one option controlling the suffix, and when the suffix is empty, Curtail should switch to overwrite mode.
If you create a 0 bytes file and name it test.jpg
, test.jpeg
or test.png
, Curtail will accept it. Currently, how it is handled exactly, depends on the JPEG or PNG compressor but it can also lead to division by 0 when calculating savings. Also stuck spinner in a tree view.
Curtail should display an error for empty files, before passing them to the compressor.
In addition to #64, I would also like to note that empty file has application/x-zerosize
mimetype. This can be used to filter them out.
It stopped responding when it started working with ~150 files on my Intel i7-6700K PC.
Also, happens every time I try.
I know it says "lossless", but lossy would be much more useful since the common case for compression is to prepare the image for sharing. Lossless only shaves off about 10% off most images, and it does so very slowly. Thus is doesn't really do much for most users.
FileOptimier which I use using WINE does a bit better of a job compressing PNG images, please add these PNG compression features into ImCompressor.
Would be nice if Curtail could support Mozjpeg instead of Jpegoptim.
Thanks for the great app!
I accidentally discovered that I can compress an already compressed image and get even further reduction in size. And I can keep doing that over and over again. See below for an example:
Is this behaviour intentional or is there perhaps a way to get the maximum compression possible at once rather than having to repeat the process? Thanks again!
Hi. Trying to update Curtail (which was installed without a problem previously) on Arch but it gives the error.
ninja: Entering directory `/home/taylantatli/.cache/paru/clone/curtail/src/build'
ninja: no work to do.
1/3 Validate desktop file OK 0.02s
2/3 Validate schema file OK 0.01s
3/3 Validate appstream file FAIL 5.71s exit status 1
>>> MALLOC_PERTURB_=60 /usr/bin/appstream-util validate data/com.github.huluti.Curtail.appdata.xml
Ok: 2
Expected Fail: 0
Fail: 1
Unexpected Pass: 0
Skipped: 0
Timeout: 0
As I understand, almost all Curtail logic is tightly coupled with its UI in CurtailWindow and CurtailPrefsWindow. Compressor class is not good too because it mixes JPEG and PNG compression steps and adding more types will not be easy in the future. How about reworking Curtail architecture to something like this:
Some examples and explanations:
compress
method and abstract get_mime_type
class method that indicates what types can be compressed with it. All concrete compressors inherit from it.from abc import ABC, abstractmethod
class CompressionError(Exception):
pass
class Compressor(ABC):
def __init__(self, settings_manager):
self.settings = settings_manager
@classmethod
@abstractmethod
def get_mime_type(cls):
pass
@abstractmethod
def compress(self, file_in, file_out):
pass
class JPEGCompressor(Compressor):
@classmethod
def get_mime_type(cls):
return 'image/jpeg'
def compress(self, file_in, file_out):
raise NotImplementedError()
# etc...
compress
method in a separate process. It also handles compression errors. EDIT: I can't yet describe how exactly the manager should notify the main window about compression completion.class CompressionManager:
def __init__(self, settings_manager):
self.settings = settings_manager
self.compressors = {}
def register_compressor(self, ConcreteCompressor):
mime_type = ConcreteCompressor.get_mime_type()
if mime_type not in self.compressors:
self.compressors[mime_type] = ConcreteCompressor(self.settings)
def compress(self, file_in, file_out):
file_mime_type = get_file_mime_type(file_in)
try:
# Should be launched in a separate process
self.compressors[file_mime_type].compress(file_in, file_out)
except KeyError:
# No suitable compressor
...
except CompressionError:
# Internal compression error
...
# manager = CompressionManager(settings_manager)
# manager.register_compressor(JPEGCompressor)
# manager.compress("hello.jpg", "world.jpg") -> ok, has suitable compressor
# manager.compress("hello.tiff", "world.tiff") -> no suitable compressor
Input Checker is a small helper class (or function) to preprocess/prevalidate incoming filenames, for example for their existence, and pass them to the Manager. To be defined.
All settings related operations and errors are handled by Settings Manager. Also it can have some kind of access control so for example Compression Manager have access to getters, but not setters. To be defined.
It's probably well beyond what you intended Curtail for, but how do you feel about creating WebP files from PNG and JPEG? It would mess up the logics of the app a little, because the "overwrite existing files" option would become irrelevant though.
I tried to compress this image and it does not do anything. I tested JPG images and they do compress.
I got the app from the AUR and I am on Manjaro
The current summary "Simple & useful image compressor" isn't great (not a call to action, very generic adjectives).
I'd suggest something like "Compress your images".
More general guidance here: https://gitlab.gnome.org/GNOME/Initiatives/-/wikis/App-Metadata
Currently Curtail will add '-min' suffix to the newly created files which prevents using this app for purposes other than comparison so it's really bad.
For example, I wanted to use it to optimize assets of some app but new files need to have the same name - an option for replacing original files is necessary.
If a file named {filename}{suffix}
already exists in the target directory, Curtail will replace it without any warning.
In addition to that, for PNG:
{filename}{suffix}.bak
backup file will be created. If it already exists, it will be replaced by a new one;Leaving aside the strange logic of the backup file creation, this could potentially cause loss of important user data. I expect Curtail to just show a file conflict dialog in such cases without any implicit backup files, as Nautilus file manager does, for example.
I am using Curtail 1.0.0 from Flathub.
Hey, would be cool if in addition to flatpak, AppImages are provided.
They allow to start apolication by simple click to a single binary. More info https://appimage.org/
Edited by Huluti:
Possible packaging formats:
Contributors: don't hesitate to post here to track progress.
OptiPNG is slow and hasn't seen a release since 2017. Oxipng is faster, multi-threaded, still receives updates, and has better compression in my experience.
I'm using Curtail a lot lately and I love it.
However, one thing that breaks my workflow and file management is that optimizing the image updates its time stamp, so I can't rely anymore on that parameter for searching, filtering or organizing my images by date. The time I optimized a picture is usually not relevant at all for that, while the time it was taken or created is.
Could Curtail implement something that copies or keeps the original time stamp?
I think this should be the default, but if there are some use cases for having the date updated, then this could become an option.
Seeing as the app is already in Circle, it needs a new icon that conforms to the HIG as soon as possible (alongside the new name).
Any preferences in terms of color/metaphor?
I set my PNG compression level to 7 since I want the max compression but it does take a long time. Please add a indicator next to the file letting the user know ImCompressor is compressing the image.
Maybe a percentage, meter, or a spinning indicator. When it is done I think a checkmark will be a nice indicator to let you know united 1.png compression is done.
Is it possible to add more loseless compression options for PNG files? I am comparing ImCompessor to FileOptimizer which is a great file compressor program for windows which works in Wine but I would always prefer to use a native linux application over using Windows apps in Wine.
ImCompressor JPG compression is the same as FileCompressor with the tests I have done with the same image. However FileOptimizer compression has a better loseless compression on PNG files especially for big images.
For example, when I compress the PNG file in the link below using ImCompressor it will become 1,194,081 bytes in size. With FileOptimizer it will become 951,995 bytes in size.
https://pngriver.com/wp-content/uploads/2018/04/Download-Electronic-Arts-PNG-Image.png
https://nikkhokkho.sourceforge.io/static.php?page=FileOptimizer
HI! A new release will be out soon (no date yet) with some cool new features to fix #6 and #13:
In order to have a good release I need some help of the translators to update their translations and ideally, it would be nice if some people test the new version from the source code to detect possible bugs.
TODO before 0.6 release:
Thank's in advance! π
The current name is a bit weird, would you be interested in help with finding a better one?
This blog post has some tips for app naming: https://puri.sm/posts/librem-5-app-design-tutorial-naming-your-app
HI! A new release will be out soon to fix #19.
In order to have a good release I need some help of the translators to update their translations (very few changes) and ideally, it would be nice if some people test the new version from the source code to detect possible bugs.
TODO before 0.8 release:
Thank's in advance! π
I've left a comment on the AUR page for ImCompressor but reading the meson build log it looks like the real problem may lay in the appdata.xml
Here's the relevant part of the meson build log:
1/3 Validate desktop file OK 0.01s
--- command ---
12:29:21 /usr/bin/desktop-file-validate data/com.github.huluti.ImCompressor.desktop
-------
2/3 Validate appstream file FAIL 0.62s (exit status 1)
--- command ---
12:29:21 /usr/bin/appstream-util validate data/com.github.huluti.ImCompressor.appdata.xml
--- stdout ---
data/com.github.huluti.ImCompressor.appdata.xml: FAILED:
β’ style-invalid : <ul> cannot start a description [(null)]
β’ style-invalid : Not enough <p> tags for a good description [0/1]
--- stderr ---
Validation of files failed
-------
3/3 Validate schema file OK 0.01s
--- command ---
12:29:21 /usr/bin/glib-compile-schemas --strict --dry-run /var/tmp/pamac-build-adrian/imcompressor/src/ImCompressor-0.8.3/data
-------
Summary of Failures:
2/3 Validate appstream file FAIL 0.62s (exit status 1)
Ok: 2
Expected Fail: 0
Fail: 1
Unexpected Pass: 0
Skipped: 0
Timeout: 0
My installed verson of appstream-util is 0.7.18.
Although from my reading it's complaining about perfectly valid tags for a description...
HI! A new release will be out soon to fix #20 and going a little further.
In order to have a good release I need some help of the translators to update their translations (very few changes) and ideally, it would be nice if some people test the new version from the source code to detect possible bugs.
TODO before 0.7 release:
Thank's in advance! π
Should be version sort I would think. Maybe somebody else can confirm that it's not just my system. I'm seeing 9.97% come before 97.84%.
Currently, Curtail has one view to open files and select the compression mode (home view) and another to show the information about the compressed files in the table (tree view). The user switches between them using back and forward buttons located in the header bar.
I don't think it's necessary to have a separate view just for opening a file or switching compression mode. Views can be combined into one by slightly changing the layout:
After this, back and forward buttons can be safely removed without loss of functionality.
Here are quick mockups:
After launching ![]() |
After compressing ![]() |
---|
It takes quite long to close them all. This reminds me about Windows 9x error messages.
Maybe add a checkbox to not show "Compression not useful" messages in Preferences?
If I drag and drop files from a different hard disk I get a 'path not valid' error.
If I try to use the file browser instead it opens at /home/myself but ignores any symlinked folders. I have several of my home's subfolders symlinked to a secondary home on a raid array to free up space on my small nvme system drive. The array is mounted at /data in fstab.
Basically Curtail only sees files in my /home and won't follow symlinks.
Workaround: copy files to /home/myself for processing, then copy back.
Version: 1.1.0
Installed with: Flatpak (Flathub) - handled by manjaro's Pamac GUI installer
Running on: manjaro linux
(note: I had imcompressor installed via AUR and it seems whoever looks after the AUR package swapped in Curtail - slightly confusing at first, especially when the build failed. So I installed Curtail from Flatpak instead. Curtail is looking fantastic, I appreciate it's a WIP at the moment.)
On two separate clean installs, using the Flatpak, AUR and official repo versions of Curtail on Manjaro KDE 21.0.5, whenever I drag-&-drop jpg files, I get an error message saying path not valid. BUT on a clean install of KDE Neon it works fine. Any ideas why that would be happening?
Hello!
I'm trying to hack on ImCompressor and add a super simple feature (i.e., set the progressive encoding flat for jpegoptim and a toggle in the preference pane. I can add a PR if I end up getting that far π ). I think I have everything ready to test, but I'm really new to desktop software and am a bit stuck with the build steps. I've managed to get meson to build and ninja to install but at a loss for the next steps to run the build.
Any pointers or any other documentation I ought to look at to help get me going again?
Thank you for your time and an app I use daily in my work for the web π₯°
Hello, thank you very much for developing this great application.
The "problem" I am having is that I am using Manjaro and I am trying to install your application via AUR using yay (Additionally I am using virtualenv).
I know that you do not support this installation method, but I believe the solution is quite simple, and maybe you can consider making the change.
Basically the problem is that during the build, the meson is taking the path of the python that points to virtualenv and not the python that is installed on my computer.
A more detailed explanation can be seen here rmarquis/pacaur#400 and here Jguer/yay#76.
So to solve the problem I have 2 suggestions.
#!/usr/bin/python3
or
find_installation
command in src/meson.build:15, it should pass the /usr/bin/python3
path, not the python name.I hope you can consider my points, and thanks in advance for your time reading this issue.
Hello,
I actually want to know one thing, gnome software (flatpak (1.2.2)) say it's only english since french isn't here, but in po file i see french, can you help me (to fix / finish) the translation by explaining where i can find what this file miss to actually work (i will translate what the file miss).
Thanks
HI! A new release will be out soon with some new features and fixes.
In order to have a good release I need some help of the translators to update their translations and ideally, it would be nice if some people test the new version from the source code to detect possible bugs (as there are some logic changes).
TODO before 1.1 release:
Thank's in advance! βοΈ
Hello,
It might be nice to be able to choose where the compressed images will be saved and if there will be a suffix or not and/or be able to change the suffix in the file name.
I think that the "Keep Metadata" setting should on the main menu right under the loseless/lossy option and by default the keep metadata should be disabled. The reason for this is if you are compressing images that you want the metadata, and you have the new image no being saved as a new file, you will accidentally delete the metadata.
This way if you want to disable the metadata, you will need to enable it before you start compressing data just like you have to enable lossy compression before you begin compressing.
So currently it's useless for jpg's, or even harmful when saving to the same file.
Previously reported in #77 (comment), but this may be different from #77, as here there is no error message in XFCE.
Drag and Drop works with Cozy in Manjaro XFCE. This is most likely the relevant source line https://github.com/geigi/cozy/blob/ad6832f221621cbb7f8beebe68949702e1dd92e1/cozy/ui/main_view.py#L634
For example, JPEG image picture.jpg
renamed to just picture
or even picture.png
is still JPEG image and should be treated as such. If I try to open this renamed file with GIMP, for example, it correctly detects the JPEG image type. Some other compressors like https://tinypng.com/ could handle this correctly too (it even changes the compressed file extension to the correct one).
Currently, Curtail fails to process such files or process them incorrectly, but it can do better by guessing file content type with Gio. Based on my experiments, if Gio.content_type_guess
is passed only data parameter (without filename), it will correctly detect JPEG type for described cases.
The downside of this approach, is that it requires reading some file contents even before compressing and may affect performance. Also, different platforms use different content type systems and comparing them should be handled with extra care. From Gio docs:
On UNIX it is a MIME type like text/plain or image/png. On Win32 it is an extension string like .doc, .txt or a perceived string like audio. Such strings can be looked up in the registry at HKEY_CLASSES_ROOT. On macOS it is a Uniform Type Identifier such as com.apple.application.
But it looks like there are functions in Gio for this β Gio.content_type_is_a
and its wrapper Gio.content_type_is_mime_type
.
First of all congratulations on the great app.
Looks great!
But what I lack with all "simple, user-friendly" apps is that you can't adjust anything. I would like to use an app with which you can quickly and easily compress images.
With it it should be able to "lossless" as well as "lossy", if possible also the strength of the compression and so on.
take a look at the web interface of kraken.io, for example.
https://kraken.io/web-interface
I think this is a very good example that settings don't have to be complicated.
Too bad that this is only SASS.
Maybe I'll find some features of it in your app soon.
Please take this as honest constructive criticism.
Otherwise please continue like this. Kudos to you.
Please add a option on the main page before you select your files on weather to keep or remove the image metadata. Metadata such as title, tags, geolocation, camera manufacture and so on.
I would prefer if the metadata was kept by default to prevent any mistakes, if a user compressed his images and made the mistake and forgot to enable the remove metadata switch, then they can do it again but if it was the other way around and they do not have the -min enabled then they would lose all the metadata.
This feature will make it handy for compressing my family photos which heavily rely on metadata without removing the metadata itself.
Hello,
I propose this to allow to know if we are compressing an image because it's showing nowhere (because when an image is long to compress we are not sure if it does or not or if it didn't crash)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.