Apples Automator to make JPEG, asking for compression level and dimensions - automator

This is a followup to Apple's Automator: compression settings for jpg?
It works. However I am failing at modifying it to make it more flexible.
I am incorporating Sips into Automator to try to create a droplet that changes an image file to a jpeg, of a particular quality and dimensions. The automator app asks for the compression level and pixel width, then spits out the requested file. Except... mine doesn't. The scripting (my lack of programming knowledge) is my weak link.
This is what I've done that's not working... Please see:

There are two mistakes in the code that the poster who wrote the code made.
When calling a variable in shell. You must prepend it with "$"
so where the have missed this out is what is stopping the code to work as it should.
The lines without the $ are: compressionLevel=file
and
sips -s format jpeg -s formatOptions compressionLevel $file --out ${filename%.*}.jpg
The corrected code:
should be:
compressionLevel=$file
and
sips -s format jpeg -s formatOptions $compressionLevel $file --out ${filename%.*}.jpg
UPDATED ANSWER* I noticed you have pixel width.
So I have change the code to accommodate it.
I have also added a "_" to the end of the out put file which you can remove if you want.
The reason I put it there is so I do not overwrite originals and create in effect copies.
compressionLevel=$1
pixalWidth=$2
i=1 # index of item
for item # A for loop by default loop through $1, $2, ...
do
if [ $i -gt 2 ]; then # start at index 3 #-- array indexes start at 0. 0 is just a "-" in this case so we totally ignor it. we are using items 1 & 2 for the sip options, the rest for file paths. the index "i" is used to keep track of the array item indexes.
echo "Processing $item"
sips -s format jpeg -s formatOptions $compressionLevel --resampleWidth $pixalWidth $item --out ${item%.*}_.jpg
fi
((i++))
done
osascript -e 'tell app "Automator" to display dialog "Done." buttons {"OK"}'
I would suggest you do some reading on shell scripting to get some basics down.
there are plant of references on the web. And Apple have this.
I am sure if you ask the question others can give you some good starting points first search this site for similar question as I am sure it base been asked a thousand times.

Related

Batch converting .eps to .jpg in imagemagick and making .mkv

I am trying to convert multiple .eps files into .jpg ones. By looking at answers here in SO, I was able to do it for single separate files.
The problem is that, when I'm trying to do it for all the files, they don't show any .jpg file.
I am currently using Imagemagick with the command
convert -density 300 outputs-000.eps -flatten outputs-000.jpg
I believe the problem is because my files are written as
outputs-000.eps
outputs-001.eps
outputs-002.eps
outputs-003.eps
...
outputs-145.eps
...
and so on. I tried putting %d (as in outputs-%d.eps and outputs-%d.jpg), but with no success.
Apart from that, I intent to get all those files and "convert" them into an .mkv or .gif or similar type (they are images of the time configuration of a particle collision system, so each image is a frame, so the goal is to make it into a 10sec movie). If there is a way to do that directly from the .eps, even better. Any help is welcome, since I've been trying to do this for several hours now. Thank you.
You should be able to make an animated GIF in one go like this:
convert -density 300 outputs-*eps -delay 200 animated.gif
Failing that, you should be able to convert all your eps files to, say PNG with:
mogrify -density 300 -format png outputs-*eps
Be careful with mogrify - it overwrites your input files unless you specify -path for an output directory, or you change format - like I just did to PNG.
For anyone who lands here trying to figure out how to work around ImageMagic's convert: not authorized without reverting the change that was made to the system-wide security policy to close a vulnerability, here's how you'd use Ghostscript to do a batch EPS-to-JPEG conversion directly without bringing ImageMagick into the mix:
gs -dSAFER -dEPSCrop -r300 -sDEVICE=jpeg -o outputs-%03d.jpg outputs-*.eps
-dSAFER puts Ghostscript in a sandboxed mode where Postscript code can only interact with the files you specified on the command line. (Yes, the parts of EPS, PS, and PDF files that define the page contents are in a turing-complete programming language.)
-dEPSCrop asks for the rendered output to be cropped to the bounding box of the drawing rather than padded out to whatever size page Ghostscript expects you to be printing to. (See the manual for details.)
The -r300 requests 300 DPI (-r600 for 600 DPI, etc.)
The -sDEVICE specifies the output format (See the Devices section of the manual for other choices.)
-o is a shorthand for -dBATCH -dNOPAUSE -sOutputFile=
This section of the Ghostscript manual gives some example formats for for multi-file filename output but, for the actual syntax definition, it points you at the documentation for the C printf(3) function.
Once you've got your JPEGs, you can follow the instructions in this answer over on the Video Production Stack Exchange to combine them into an MKV file.
The TL;DR is this command here:
ffmpeg -framerate 30 -i outputs-%03d.jpg -codec copy output.mkv
Check out the other answers if you want something that performs inter-frame compression rather than aiming to avoid transcoding the JPEGs again.
(If you want the best compromise, have Ghostscript output PNGs and then let ffmpeg handle switching to lossy compression.)

ImageMagick to verify image integrity

I'm using ImageMagick (with Wand in Python) to convert images and to get thumbnails from them. However, I noticed that I need to verify whether a file is an image or not ahead of time. Should I do this with Identify?
So I would assume checking the integrity of a file needs the whole file to be read into memory. Is it better to try and convert the file and if there was an error, then we know the file wasn't good.
seems like you answered your own question
$ ls -l *.png
-rw-r--r-- 1 jsp jsp 526254 Jul 20 12:10 image.png
-rw-r--r-- 1 jsp jsp 10000 Jul 20 12:12 image_with_error.png
$ identify image.png &> /dev/null; echo $?
0
$ identify image_with_error.png &> /dev/null; echo $?
0
$ convert image.png /dev/null &> /dev/null ; echo $?
0
$ convert image_with_error.png /dev/null &> /dev/null ; echo $?
1
if you specify the regard-warnings flag with the imagemagick identify tool
magick identify -regard-warnings myimage.jpg
it will throw an error if there are any warnings about the file. This is good for checking images, and seems to be a lot faster than using verbose.
I the case you use Python you can consider also the Pillow module.
In my experiments, I have used both the Pyhton Pillow module (PIL) and the Imagemagick wrapper Wand (for psd, xcf formats) in order to detect broken images, the original answer with code snippets is here.
Update:
I also implemented this solution in my Python script here on GitHub.
I also verified that damaged files (jpg) frequently are not 'broken' images i.e, a damaged picture file sometimes remains a legit picture file, the original image is lost or altered but you are still able to load it.
End Update
I quote the full answer for completeness:
You can use Python Pillow(PIL) module, with most image formats, to check if a file is a valid and intact image file.
In the case you aim at detecting also broken images, #Nadia Alramli correctly suggests the im.verify() method, but this does not detect all the possible image defects, e.g., im.verify does not detect truncated images (that most viewers often load with a greyed area).
Pillow is able to detect these type of defects too, but you have to apply image manipulation or image decode/recode in or to trigger the check. Finally I suggest to use this code:
try:
im = Image.load(filename)
im.verify() #I perform also verify, don't know if he sees other types o defects
im.close() #reload is necessary in my case
im = Image.load(filename)
im.transpose(PIL.Image.FLIP_LEFT_RIGHT)
im.close()
except:
#manage excetions here
In case of image defects this code will raise an exception.
Please consider that im.verify is about 100 times faster than performing the image manipulation (and I think that flip is one of the cheaper transformations).
With this code you are going to verify a set of images at about 10 MBytes/sec (using single thread of a modern 2.5Ghz x86_64 CPU).
For the other formats psd,xcf,.. you can use Imagemagick wrapper Wand, the code is as follows:
im = wand.image.Image(filename=filename)
temp = im.flip;
im.close()
But, from my experiments Wand does not detect truncated images, I think it loads lacking parts as greyed area without prompting.
I red that Imagemagick has an external command identify that could make the job, but I have not found a way to invoke that function programmatically and I have not tested this route.
I suggest to always perform a preliminary check, check the filesize to not be zero (or very small), is a very cheap idea:
statfile = os.stat(filename)
filesize = statfile.st_size
if filesize == 0:
#manage here the 'faulty image' case
Here's another solution using identify, but without convert:
identify -verbose *.png 2>&1 | grep "corrupt image"
identify: corrupt image 'image_with_error.png' # error/png.c/ReadPNGImage/4051.
i use identify:
$ identify image.tif
00000005.tif TIFF 4741x6981 4741x6981+0+0 8-bit DirectClass 4.471MB 0.000u 0:00.010
$ echo $?

Compressing multipage TIF files with varied page formats via command line

We have a large number of multipage TIF files (mainly document scans) contained in our document management system. Through various historical issues and end user misunderstandings a large number of these are considerably larger than they need to be (for example they will be scanned at a higher resolution than required, or stored without compression).
What I have been looking at doing is working through some of these documents and doing some optimisation in order to claim back some valuable storage space (I have already recovered 25GB just taking out the very low hanging fruit).
So far I have been using a combination of ImageMagick and Irfanview but I would really like to automate this process a lot more as it is pretty labour intensive at the moment. I have had a crack at creating a few scripts but unfortunately nature of the TIFs in question is proving problematic.
In particular, the majority of them contain mixed page formats; bilevel/1 bit pages for basic letter pages and full colour RGB pages for images / maps / plans. Most documents will have a mixture of these types and not always in any particular order (indeed they may go back and forth between these two formats).
Ideally I want to use group 4 fax compression on the bilevel pages and JPEG compression on the colour pages (so the -compress group4 / -compress jpeg flags in ImageMagick) but there does not appear to be any way (that I can tell - I have limited experience with IM) to set the compression on a per page format basis. Does anyone know if this is possible? Or can anyone recommend a scriptable tool that does have this capability?
Irfanview can do per page compression but it must be manually set page by page through the GUI, which is clearly not ideal.
Any tips would be greatly appreciated!
Since I don't have a sample TIFF file around showing the characteristics you describe (mixed formats, different compression schemes and color spaces for different pages...), here's a first shot.
To automate the processing of multipage TIFFs you need to know that you can access each picture individually by attaching its zero-based index number [n] to the file name.
Also, you should look up the list of ImageMagick escpape shortcuts, so you can construct an identify -format <%escapestrings> command that automatically extracts the interesting bits from the file, which you'll then use to base your further processing on.
So start your project with identifying the various characteristics between the different TIFF pages by running such an identify with a customized -format string, for example:
for i in $(seq 1 $(identify -format %n multipage.tiff)); do
identify -format \
"scene-number:%s \
image-width-in-pixels:%w \
image-height-in-pixels:%h \
x-resolution:%x \
y-resolution:%y \
image-depth:%z \
imageclass+colorspace:%r \
image-compression-type:%C \
image-compression-quality:%Q \
page-width:%W \
page-height:%H" \
multipage.tiff[$i];
done
(For educational reasons deliberately made more verbose than it need be...)
Based on that, you should be able to come up with a shell script that does what you need.

Apple's Automator: compression settings for jpg?

When I run Apple's Automator to simply cut a bunch of images in their size Automator will also reduce the quality of the files (jpg) and they get blurry.
How can I prevent this? Are there settings that I can take control of?
Edit:
Or are there any other tools that do the same job but without affecting the image quality?
If you want to have finer control over the amount of JPEG compression, as kopischke said you'll have to use the sips utility, which can be used in a shell script. Here's how you would do that in Automator:
First get the files and the compression setting:
The Ask for Text action should not accept any input (right-click on it, select "Ignore Input").
Make sure that the first Get Value of Variable action is not accepting any input (right-click on them, select "Ignore Input"), and that the second Get Value of Variable takes the input from the first. This creates an array that is then passed on to the shell script. The first item in the array is the compression level that was given to the Automator Script. The second is the list of files that the script will do the sips command on.
In the options on the top of the Run Shell Script action, select "/bin/bash" as the Shell and select "as arguments" for Pass Input. Then paste this code:
itemNumber=0
compressionLevel=0
for file in "$#"
do
if [ "$itemNumber" = "0" ]; then
compressionLevel=$file
else
echo "Processing $file"
filename="$file"
sips -s format jpeg -s formatOptions $compressionLevel "$file" --out "${filename%.*}.jpg"
fi
((itemNumber=itemNumber+1))
done
((itemNumber=itemNumber-1))
osascript -e "tell app \"Automator\" to display dialog \"${itemNumber} Files Converted\" buttons {\"OK\"}"
If you click on Results at the bottom, it'll tell you what file it's currently working on. Have fun compressing!
Automator’s “Crop Images” and “Scale Images” actions have no quality settings – as is often the case with Automator, simplicity trumps configurability. However, there is another way to access CoreImage’s image manipulation facilities whithout resorting to Cocoa programming: the Scriptable Image Processing System, which makes image processing functions available to
the shell via the sips utility. You can fiddle with the most minute settings using this, but as it is a bit arcane in handling, you might be better served with the second way,
AppleScript via Image Events, a scriptable faceless background application provided by OS X. There are crop and scale commands, and the option of specifying a compression level when saving as a JPEG with
save <image> as JPEG with compression level (low|medium|high)
Use a “Run AppleScript” action instead of your “Crop” / “Scale” one and wrap the Image Events commands in a tell application "Image Events" block, and you should be set. For instance, to scale the image to half its size and save as a JPEG in best quality, overwriting the original:
on run {input, parameters}
set output to {}
repeat with aPath in input
tell application "Image Events"
set aPicture to open aPath
try
scale aPicture by factor 0.5
set end of output to save aPicture as JPEG with compression level low
on error errorMessage
log errorMessage
end try
close aPicture
end tell
end repeat
return output -- next action processes edited files.
end run
– for other scales, adjust the factor accordingly (1 = 100 %, .5 = 50 %, .25 = 25 % etc.); for a crop, replace the scale aPicture by factor X by crop aPicture to {width, height}. Mac OS X Automation has good tutorials on the usage of both scale and crop.
Eric's code is just brilliant. Can get most of the jobs done.
but if the image's filename contains space, this workflow will not work.(due to space will break the shell script when processing sips.)
There is a simple solution for this: add "Rename Finder Item" in this workflow.
replace spaces with "_" or anything you like.
then, it's good to go.
Comment from '20
I changed the script into a quick action, without any prompts (for compression as well as confirmation). It duplicates the file and renames the original version to _original. I also included nyam's solution for the 'space' problem.
You can download the workflow file here: http://mobilejournalism.blog/files/Compress%2080%20percent.workflow.zip (file is zipped, because otherwise it will be recognized as a folder instead of workflow file)
Hopefully this is useful for anyone searching for a solution like this (like I did an hour ago).
Comment from '17
To avoid "space" problem, it's smarter to change IFS than renaming.
Back up current IFS and change it to \n only. And restore original IFS after the processing loop.
ORG_IFS=$IFS
IFS=$'\n'
for file in $#
do
...
done
IFS=$ORG_IFS

Using Delphi or FFMpeg to create a movie from image sequence

My Delphi app has created a squence called frame_001.png to frame_100.png.
I need that to be compiled into a movie clip. I think perhaps the easiest is to call ffmpeg from the command line, according to their documentation:
For creating a video from many images:
ffmpeg -f image2 -i foo-%03d.jpeg -r 12 -s WxH foo.avi
The syntax foo-%03d.jpeg specifies to use a decimal number composed of three digits padded with zeroes to express the sequence number. It is the same syntax supported by the C printf function, but only formats accepting a normal integer are suitable.
From: http://ffmpeg.org/ffmpeg-doc.html#SEC5
However my files are (lossless) png format, so I have to convert using imagemagick first.
My command line is now:
ffmpeg.exe -f image2 -i c:\temp\wentelreader\frame_%05d.jpg -r 12 foo.avi
But then I get the error:
[image2 # 0x133a7d0]Could not find codec parameters (Video: mjpeg)
c:\temp\wentelreader\Frame_C:\VID2EVA\Tools\Mencoder\wentel.bat5d.jpg: could not
find codec parameters
What am I doing wrong?
Alternatively can this be done easily with Delphi?
Not sure if you are interested but there are delphi headers for this # http://ultrastardx.svn.sourceforge.net/viewvc/ultrastardx/trunk/src/lib/ffmpeg/
So you can use the DLL vs command line.
-Brad
Look at the file name in the error message. That can't possibly be right. The percent sign needs to get all the way to the program you're running, but it's being expanded by the batch file instead, where %0 expands to the full name and path of the file. Double the percent sign in the batch file:
ffmpeg.exe -f image2 -i c:\temp\wentelreader\frame_%%05d.jpg -r 12 foo.avi
Also, why do you want five digits when you've already said your files are named like frame_001.png, which has only three digits?
ffmpeg can create a movie from png images, why do you think you have to convert them to jpeg?
Guys in DelphiFFMpeg have been produced a component wrapper for FFMpeg. It's very expensive but it's worth to test it. However what you want to do is very simple and command-line is more than enough for you.

Resources