Help with converting PNG to JPG (every 0.5 seconds)
Linux - SoftwareThis forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Help with converting PNG to JPG (every 0.5 seconds)
Hello everyone!
I'm trying to figure out how to solve the following problem:
I'm generating a PNG every 0.5 seconds (this PNG always overwrites itself)
Because a PNG file is too large, I need to convert it to JPG.
I made a script:
Code:
#!/bin/sh
while [ true ]; do
/usr/bin/convert /home/file.png /var/www/html/website/file.jpg
uleep 500
done
This script doesn't work well, because many times the conversion happens before the png file was completely written (as I said, this PNG is generated every 500 ms), so the jpg file will often result in a damaged picture, half a picture, etc.
Is there any way I can tell the "convert" command to do the conversion ONLY when the PNG was completely written on the HDD, and not before?
You could make use of the inotify-tools package, which allows you to script inotify events:
Code:
#!/bin/sh
while [ true ] ; do
inotifywait -e close_write file.png
/usr/bin/convert file.png file.jpg
echo "converted"
done
You cannot just check whether the file has been closed (eg using 'lsof file'), because you will still have a race condition.
The above script also has a race condition, but hopefully 500ms is long enough to do the conversion before the next write to the png. An improvement would be to do the conversion to a temporary file, and test the return value from the convert command; if it gives an error, then don't copy the temporary file to the public one.
Incidentally, is the 'usleep' command you were using a 500 millisecond sleep or a 500 microsecond sleep?
This probably means that the generating program is not just rewriting the file, but recreating it (which means the inotify returns with an error, because it loses the node). So this following script instead waits on a notify on the directory; however, it also has to test which file was written to (on the assumption that there might be other files in the same directory).
Code:
#!/bin/sh
while [ true ] ; do
inotifywait -e close_write /home | grep 'file.png'
if [ $? -eq 0 ] ; then
/usr/bin/convert file.png file.jpg
fi
done
If the inotify is working correctly, you do not need the half second delay.
/home/ CLOSE_WRITE,CLOSE file.png.swp
Setting up watches.
Watches established.
/home/ CLOSE_WRITE,CLOSE file.png.swp
Setting up watches.
Watches established.
/home/ CLOSE_WRITE,CLOSE file.png.swp
Setting up watches.
Watches established.
/home/ CLOSE_WRITE,CLOSE file.png.swp
Setting up watches.
Watches established.
/home/ CLOSE_WRITE,CLOSE file.png.swp
So, it looks like there is actually a renaming going on... but it still doesn't work.
Using your latest script, brings us back to the beginning... corrupted JPGs every 1-2 seconds.
I don't understand why file.png gets ignored, even though it's constantly replaced...
We may need to know more about the image generation sequence. As you say, the originating program may be creating the temporary (.png.swp) and then renaming it, in which case you would have to wait for a 'move-to' event rather than a 'close-write' event, eg:
Code:
#!/bin/sh
while [ true ] ; do
inotifywait -e move_to /home | grep 'file.png$'
if [ $? -eq 0 ] ; then
/usr/bin/convert file.png file.jpg
fi
done
(jadrevenge has added the '$' to prevent it matching on 'file.png.swp', which is triggering the convert too soon.)
Last edited by neonsignal; 05-11-2011 at 06:15 PM.
Using "moved_to" for the inotifywait event seems to do the trick, it matches the file correctly:
Code:
/ramcache/ MOVED_TO file.png
Setting up watches.
Watches established.
/ramcache/ MOVED_TO file.png
Setting up watches.
Watches established.
/ramcache/ MOVED_TO file.png
Setting up watches.
Watches established.
I'm now using this script, which seems to work best, but still not 100% OK:
Code:
#!/bin/sh
while [ true ] ; do
inotifywait -e moved_to /ramcache | grep 'file.png$'
if [ $? -eq 0 ] ; then
/usr/bin/convert /ramcache/file.png /ramcache/$$.jpg 2>/dev/null
usleep 1000
cp /ramcache/$$.jpg /var/www/html/website/file.jpg
fi
done
With this script the conversion process works much better, but every 30 seconds or so, I still get corrupted JPGs.
I even created a ramdisk to speed up caching, but it doesn't seem to help a lot.
Solved it !!
The problem was : cp /ramcache/$$.jpg /var/www/html/website/file.jpg
I changed it to: mv /ramcache/$$.jpg /var/www/html/website/file.jpg
Now the corrupted JPGs have disappeared.
Now, another problem:
Is there some way to send the whole " inotifywait -e moved_to /ramcache | grep 'file.png$' " to /dev/null?
I tried various ways but it doesn't seem to work.
Later edit: Never mind, " inotifywait -e moved_to /ramcache 2>/dev/null | grep 'file.png$' >/dev/null " seems to do the trick. Thank you, neonsignal and jadrevenge for all the help !
Did you look at whether it's possible to make whatever it is that's producing the PNG file send it's output to stdout instead of a file? Because if you can do that you could pipe it's output to convert to produce a JPEG and save yourself all this hassle with ionotify.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.