shmulvad Posted August 11, 2020 Share Posted August 11, 2020 (edited) An Alfred 4 workflow for quickly compressing and resizing images using TinyPNG. Simply select a collection of images or a folder in Finder and activate the workflow. Installation and Getting Started Install alfred-tinypng workflow. All further updates are handled automatically. You will need to configure the workflow with an API key from TinyPNG. Type tinypng_api to get a link to the pagewhere you can get your API key and to actually set the key when you have gotten it. Usage Select either a folder, image file or a number of image files in Finder. Afterward, open Alfred and type tinypng. You are presented with the following choices: Choose an item based on what you want. When selected, the workflow will start compressing/resizing the image(s). After it is done, they will be saved to the same directory and with the same filename as the original image. The original image will be preserved with .bak prepended before the file extension. I.e. if compressing img.jpg, this will now become img.bak.jpg and the compressed image will be saved as img.jpg. Refer to the TinyPNG documentation for a full explanation of the different resizing options. Why? Another TinyPNG workflow already exists It doesn't support choosing the files based on what is selected in Finder (which I personally prefer). Only simple compression is supported whereas all TinyPNG compressions and resizing options are supported in this workflow. It seems to be abandoned by the creator (has not been updated since 2015). Credits The workflow makes use of the following: OneUpdater by vitorgalvao for handling automatic updates. TinyPNG Python API Code and more can be viewed on the associated GitHub-repo. If you find this workflow useful, stars are appreciated. Edited August 15, 2020 by shmulvad Add GitHub link Vero, JJJJ, alfredpanda and 1 other 4 Link to comment
mixterdee Posted August 12, 2020 Share Posted August 12, 2020 (edited) I've used the old workflow for years and as you mentioned it hasn't been updated so thought I'd give yours a try. Unfortunately I can't enter my API key. Once I click on Enter/Change API Key it switches to the default search. Can you suggest what could be causing the issue? Edited August 12, 2020 by mixterdee Adding an image Link to comment
shmulvad Posted August 12, 2020 Author Share Posted August 12, 2020 1 minute ago, mixterdee said: I've used the old workflow for years and as you mentioned it hasn't been updated so thought I'd give yours a try. Unfortunately I can't enter my API key. Once I click on Enter/Change API Key it switches to the default search. Can you suggest what could be causing the issue? Sorry about that. This workflow uses Python 3. Does it work if you do "which python3" in your Terminal and set that as the path for the variable "pythonPath" in the workflow? Link to comment
DaniTz Posted January 7, 2021 Share Posted January 7, 2021 doesn't work for me. I've tried for at least an hour, ending up installing different versions of python 3 on a new M1 mac mini. I really wish for it to work but it doesn't. First notification is a starting the compression/resizing then another one with Status which is blank and nothing happens. I would appreciate some help Thanks, Dan Link to comment
shmulvad Posted January 11, 2021 Author Share Posted January 11, 2021 On 1/8/2021 at 12:20 AM, DaniTz said: doesn't work for me. I've tried for at least an hour, ending up installing different versions of python 3 on a new M1 mac mini. I really wish for it to work but it doesn't. First notification is a starting the compression/resizing then another one with Status which is blank and nothing happens. I would appreciate some help Thanks, Dan Hi Dan. Sorry, but I do not have a M1 machine to test on. I am not sure what causes the issue based on your information, but since at least some of the workflow works based on your information, I think it is not a problem with your Python version and something else is causing it. Can you check the log using the Workflow Debugger and report back on what you see? Link to comment
deanishe Posted January 11, 2021 Share Posted January 11, 2021 (edited) 19 minutes ago, shmulvad said: I think it is not a problem with your Python version and something else is causing it Out of interest, why have you written the workflow to use a custom Anaconda installation instead of /usr/bin/python3 that's part of macOS? Edited January 11, 2021 by deanishe Link to comment
shmulvad Posted January 11, 2021 Author Share Posted January 11, 2021 Just now, deanishe said: Out of interest, why have you written the workflow to use a custom Anaconda installation instead of one of the system Pythons that everybody has? It is just the installation I use per default on my personal system if I do not set up a new separate environment for a Python project. I wrote the workflow because I personally had a use case for it and afterward thought I might as well release it publicly now that the workflow existed anyway. When I tried using just "python" from within Alfred to call it, it didn't work on my system (even though "python --version" gives me 3.8.5 in a regular terminal session, even when no conda env is activated). It could be fixed by using the absolute path, so I just did that. I can see it also works (on my system at least) when using "python3" which I agree would have been a better choice as the default. Link to comment
deanishe Posted January 11, 2021 Share Posted January 11, 2021 1 hour ago, shmulvad said: When I tried using just "python" from within Alfred to call it […] even though "python --version" gives me 3.8.5 in a regular terminal session On macOS python is Python 2 (/usr/bin/python), which is what you get in Alfred. You’ve done something to your shell’s PATH to make python point to a Python 3 executable, but Mac apps don’t use your shell environment. In workflows, I think it’s generally best to hardcode /usr/bin/python or /usr/bin/python3, so you always get a known version regardless of what you or users have done to their environment. Having the python command run Python 3 is a bit dubious, imo, because it contradicts what the OS does. shmulvad 1 Link to comment
Geoffrey Posted April 10, 2021 Share Posted April 10, 2021 Hey mate. Thanks for creating this workflow. It sounds exactly like something that would be very handy in my work processes, as I deal with image compression a lot. Unfortunately, I'm running into an error when running an error shown below: [14:49:56.955] TinyPNG[Script Filter] Queuing argument '' [14:49:57.122] TinyPNG[Script Filter] Script with argv '(null)' finished [14:49:57.126] TinyPNG[Script Filter] {"items": [{"title": "COMPRESS: Compress image(s)", "subtitle": "Compresses image(s)", "arg": "COMPRESS", "uid": "COMPRESS"}, {"title": "SCALE: Scale prop. down by *either* height or width", "subtitle": "Usage: I.e. \"w800\" or \"h500\"", "valid": false, "arg": "SCALE", "uid": "SCALE", "icon": {"path": "scale.png"}}, {"title": "FIT: Scale prop. down within width and height", "subtitle": "Usage: \"width height\", i.e. \"800 500\"", "valid": false, "arg": "FIT", "uid": "FIT", "icon": {"path": "fit.png"}}, {"title": "COVER: Scale and crop down to exactly width and height", "subtitle": "Usage: \"width height\", i.e. \"800 500\"", "valid": false, "arg": "COVER", "uid": "COVER", "icon": {"path": "cover.png"}}, {"title": "THUMB: Advanced scale and crop to exactly width and height", "subtitle": "Usage: \"width height\", i.e. \"800 500\"", "valid": false, "arg": "THUMB", "uid": "THUMB", "icon": {"path": "thumb.png"}}], "variables": {"axis": 0, "len": 0, "width": 0, "height": 0}} [14:49:59.029] TinyPNG[Script Filter] Processing complete [14:49:59.038] TinyPNG[Script Filter] Passing output 'COMPRESS' to Conditional [14:49:59.041] TinyPNG[Conditional] Processing complete [14:49:59.043] TinyPNG[Conditional] Passing output 'COMPRESS' to Run Script [14:49:59.045] TinyPNG[Script Filter] Passing output 'COMPRESS' to Run Script [14:50:00.075] TinyPNG[Run Script] Processing complete [14:50:00.087] TinyPNG[Run Script] Passing output '"/Users/geoffrey/Desktop/achtergrond-tenniszaal.png:" COMPRESS ********************** 0 0 0 0 ' to Post Notification [14:50:00.090] TinyPNG[Run Script] Passing output '"/Users/geoffrey/Desktop/achtergrond-tenniszaal.png:" COMPRESS ********************** 0 0 0 0 ' to Run Script [14:50:00.194] ERROR: TinyPNG[Run Script] Traceback (most recent call last): File "tiny_upload.py", line 5, in <module> import tinify File "/Users/geoffrey/Dropbox/Alfred/Alfred.alfredpreferences/workflows/user.workflow.F8ABF891-4B1F-4AC7-8D88-44C494B28EA9/tinify/__init__.py", line 92, in <module> from .client import Client File "/Users/geoffrey/Dropbox/Alfred/Alfred.alfredpreferences/workflows/user.workflow.F8ABF891-4B1F-4AC7-8D88-44C494B28EA9/tinify/client.py", line 7, in <module> import requests ModuleNotFoundError: No module named 'requests' [14:50:00.211] TinyPNG[Run Script] Processing complete [14:50:00.213] TinyPNG[Run Script] Passing output '' to Post Notification Also, as a little suggestion for improvement: could you make the automatic backup image an optional setting? In my workflow, I only need to compress the image, not create a backup copy (as I can easily get that back myself if something goes wrong). I hope you could help me out with this. Thanks a bunch and have a great weekend. shmulvad 1 Link to comment
deanishe Posted April 10, 2021 Share Posted April 10, 2021 4 hours ago, Geoffrey said: I'm running into an error when running an error shown below The workflow needs the requests library, but @shmulvad has forgotten to include it. Link to comment
Geoffrey Posted April 10, 2021 Share Posted April 10, 2021 (edited) 18 hours ago, deanishe said: The workflow needs the requests library, but @shmulvad has forgotten to include it. Ah, thanks a lot! Installing that library fixed the issue. For anyone else running into the same issue, follow the install instructions listed on this page: https://docs.python-requests.org/en/master/user/install/ check deanishe's solution below. Edited April 11, 2021 by Geoffrey Link to comment
deanishe Posted April 10, 2021 Share Posted April 10, 2021 A better solution is to run /usr/bin/python -m pip install --user --upgrade requests That installs it in your user directory, so it won't be deleted by OS upgrades and you won't need elevated privileges to install it. The proper solution is for @shmulvad to bundle it with the workflow, however. You can do that with pip’s --target flag: /usr/bin/python -m pip install --target . requests shmulvad 1 Link to comment
shmulvad Posted April 10, 2021 Author Share Posted April 10, 2021 Thanks for making me aware of the unbundled library. Good to hear you got it solved for now, but as deanishe says the proper solution is for it to be bundled. I am busy with exams at the moment but will try to release a new version where this is fixed soon. I will probably look into your other suggestion as well, but no promises on when. Link to comment
deanishe Posted April 10, 2021 Share Posted April 10, 2021 Good luck with the exams! shmulvad 1 Link to comment
shmulvad Posted May 1, 2021 Author Share Posted May 1, 2021 @Geoffrey I've released version 1.0.2 where the issue regarding bundling of the requests library is fixed and now you can also set a workflow variable KEEP_BACKUPS to either True or False (True per default) that determines whether or not to keep the .bak files. Link to comment
Geoffrey Posted May 1, 2021 Share Posted May 1, 2021 @shmulvad Thank you very much! I'm already enjoying the workflow a lot and these fixes really are the icing on the cake. Great work! 🙂 shmulvad 1 Link to comment
PHlllPP Posted June 3, 2021 Share Posted June 3, 2021 Hey @shmulvad, thank you very much for this awesome workflow! super handy. I am new to Alfred and not sure how I can set the variable for the Backup to False.. can you help me out here? or is there a way to put a '_' in front of the filename to mark the backups instead? thanks a lot Link to comment
shmulvad Posted June 3, 2021 Author Share Posted June 3, 2021 @PHlllPP You need to edit the workflow variables. Click the button that looks like [x]. As for your other question, I don’t really see that the benefit in allowing multiple ways of handling renaming originals would outweight the additional mental burden. I would need some convincing arguments to do this. Link to comment
PHlllPP Posted June 4, 2021 Share Posted June 4, 2021 thanks so much @shmulvad for answering my rookie question. regarding the naming for the backup file: I was not requesting a change from your side, just wondering if I there is a way I can adjust it for my personal use. (I find it handy if I can separate modified files from backup files via sorting alphabetically in that folder, hence the idea with the underscore before the filename. But never mind it is super good as it is. thanks again. ) Link to comment
shmulvad Posted June 4, 2021 Author Share Posted June 4, 2021 @PHlllPP You can change the renaming logic in the file tiny_upload.py in the function get_new_and_bak_file() to suit your needs. But your changes will be overwritten when the workflow is updated next time so it is not recommended. Link to comment
PHlllPP Posted June 5, 2021 Share Posted June 5, 2021 ok thanks @shmulvad, I'll give it a try Link to comment
PHlllPP Posted July 26, 2021 Share Posted July 26, 2021 Hey @shmulvad, I was using your workflow a lot.. it is working like a charm and saved me hours so far. However I bumped in one issue: the workflow causes an error for file extensions in call caps. So .JPG files do not work. Unfortunately the iphone and some DSLR cameras save jpgs like that. Is there an easy way to fix this? thanks and greetings from Berlin Link to comment
deanishe Posted July 27, 2021 Share Posted July 27, 2021 15 hours ago, PHlllPP said: Is there an easy way to fix this? I've not actually tried it, but it looks like a tiny edit should do it. Change line 96 of tiny_upload.py to read if ext.lower() not in EXTS: Link to comment
alfredpanda Posted July 27, 2021 Share Posted July 27, 2021 Love this workflow! Thank you. Link to comment
PHlllPP Posted July 30, 2021 Share Posted July 30, 2021 thank you @deanishe adding lower() to the if statement did not work, but it works when added before: ext = file.split('.')[-1].lower() deanishe 1 Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now