Converting jpegs without using Photoshop

I have an interest in an applescript that will convert a folder of jpeg images from their original size to 72 dpi versions at 2" wide without the use of Photoshop. My question is whether anyone has utilized any of the available tools (ie. Kazu’s Extra Suites, Image Events, GraphicConverter, or others?) and have a tool to recommend based on performance & flexibility?

Scott:

I have not had the need to do anything that specific, but supposedly, iMagine Photo is your best bet.

Thank you… I have read some interesting information re: imaginePhoto… I did write a script using Image Events earlier and was going to give imagine a speed test later on. If I determine a significant speed difference, I will report my findings. (But, if anyone else has had any experience, feel free to chime in!)

I was trying to batch scale down some images with Image Events, only to find that a) it’s slow and worse, b) there’s no way to reduce quality. So I took a shot at iMagine Photo. It looks amazing, and I thank ktam for it. Unfortunately its power makes it way more complicated that I really need. I could spend a couple hours studying the manual, or maybe somebody with more experience could tell me how to convert this to iMagine Photo syntax, with the addition of a quality reduciton:


on rescale_and_save(this_item)
	tell application "Image Events"
		launch
		-- open the image file
		set this_image to open this_item
		set typ to this_image's file type
		if themethod is "Pixels" then
			set target_width to theValue
			copy dimensions of this_image to {current_width, current_height}
			if current_width is greater than current_height then
				scale this_image to size target_width
			else
				set the new_height to (current_height * target_width) / current_width
				scale this_image to size new_height
			end if
		else if themethod is "Percentage" then
			scale this_image by factor theValue
		end if
		save this_image as typ
	end tell
end rescale_and_save

here theMethod is set with a dialog; theValue is set in pixels if theMethod is “Pixels” and as a factor (ie, 0.5) if theMethod is Percentage (ie, 50). the_item is an HFS path as a string.

Ideally I would also like to:

  1. revert to Image Events if iMagine Photo is not installed (is there a way to check if an application is installed and can be “told” without checking the processes first??)
  2. run iMagine Photo as a background application.

PS: I notice that in the example droplets, there is a property:
property myLib : load script (alias “/Applications/iMagine Photo/AppleScriptLib/Subroutines”)

This depends on the iMagine Photo folder being kept in /Applications. Shouldn’t this be relative to the application’s actual location instead?

This might be better:


property idtype : "kASD"
tell application "Finder" to set IPpath to container of (application file id idtype as alias) as string
set myLib to load script (IPpath & "AppleScriptLib:Subroutines") as string

Thanks.

i really like the netpbm package availible via fink.

as simple as and really powerfull you can do anything almost.

jpegtopnm DSC00088.JPG | pnmscale --height 200 --width 200 | pnmtojpeg > one.jpg

thanks for the suggestion. but i want something that your average end user can install – so if it involves fink it’s probably no good.

Using iMagine Photo I think the following script will do what you want.

Kevin


using terms from application "iMagine Photo"
	property exportQuality : low
end using terms from
property themethod : "Pixels"
property target_width : 144
property theValue : 0.4 -- not percentage.

on run
	set thisFile to choose file
	my rescale_and_save(thisFile)
end run

on rescale_and_save(this_item)
	tell application "iMagine Photo"
		launch
		set thisImporter to import graphic this_item
		if the component error of thisImporter is equal to 0 then
			my CreateReplacingExporterLikeImporter(thisImporter)
			if themethod is "Pixels" then
				set {x, y, current_width, current_height} to the natural bounds of thisImporter
				set theScale to target_width / current_width
			else
				set theScale to theValue
			end if
			set the scale of thisImporter to {theScale, theScale}
			set the export compression quality of thisImporter to exportQuality
			export thisImporter
		end if
		close thisImporter
	end tell
end rescale_and_save

on CreateReplacingExporterLikeImporter(theInitialImporter)
	tell application "iMagine Photo"
		try
			tell theInitialImporter
				set theImporterType to the graphic type
				set exportType to my GetExportTypeFromImportType(theImporterType)
				make exporter with properties {export file type:exportType}
				if the export component error is not equal to 0 then
					set the export file type to "TIFF"
				end if
				set export file location to file location as alias
			end tell
		end try
	end tell
end CreateReplacingExporterLikeImporter

on GetExportTypeFromImportType(theimportType)
	if theimportType is equal to "Photo - JPEG" then
		return "JPEG"
	else if theimportType contains "TIFF" then
		return "TIFF"
	else if theimportType is equal to "QuickDraw" then
		return "PICT"
	else if theimportType is equal to "Planar RGB" then
		return "Photoshop"
	else if theimportType is equal to "JPEG 2000" then
		return "JP2"
	else
		return theimportType
	end if
end GetExportTypeFromImportType


If you have any problems let me know.

Kevin

Thanks a lot! I had already dove in and got something workable, but without fully understanding how. But your solution is much more elegant than mine was, which used a lot of unnecessary parts of your subroutines that I didn’t understand, and separate handlers for scaling and setting image size.

You left out two things though which are important here : 1) ability to revert to using image events if iMagine isn’t installed and 2) setting image quality if it is.

With regards to 2 above, I wonder why iMagine doesn’t just use a quality value instead of named properties. But at any rate it can be handled.

One other comment/feedback on the subroutines: Please see what I said above about needing to have iMagine folder in the /Applications folder to work. A better solution would be to use something like I did above. Even better would be to put the essential subroutines inside the iMagine package, so it can be accessed with path to scripts folder of …

Anyway here’s my modified solution, hope it is usefull generally:


property default_method : "Percentage"
-- options would be "No Scale", "Percentage", "Pixels"
property default_target_width : "320"
property default_scale : "40"
property default_qual : "Medium"
property export_options : {"Minimum", "Low", "Medium", "High", "Maximum", "Lossless"}
property iptype : "kASD"
property ipName : "iMagine Photo"
property hasip : false

global themethod, theValue, exportQuality

on run
	-- normally setting defaults handled in run handler, with better error checking
	set default_method to button returned of (display dialog "How do you want to scale images?" buttons {"No Scale", "Pixels", "Percentage"} default button default_method)
	if default_method is "Pixels" then
		set default_target_width to text returned of (display dialog "Scale images to a target width of how many pixels?" default answer default_target_width)
	else if default_method is "Percentage" then
		set default_scale to text returned of (display dialog "Scale images to what percentage?" default answer default_scale)
	end if
	set hasip to my appExists(ipName, iptype)
	if hasip then
		set thereply to choose from list export_options with prompt "Choose an export quality:" with title "JPG Quality" default items default_qual without multiple selections allowed and empty selection allowed
		if thereply is not false then set default_qual to item 1 of thereply
	end if
	
	-- normally this would be part of an open handler
	set themethod to default_method
	if themethod is "Pixels" then
		set theValue to default_target_width as number
	else if themethod is "Percentage" then
		set theValue to (default_scale as number) / 100
	else
		set theValue to 0
	end if
	set hasip to my appExists(ipName, iptype)
	if hasip then
		using terms from application "iMagine Photo"
			tell application ipName
				if default_qual is "Minimum" then
					set exportQuality to minimum
				else if default_qual is "Low" then
					set exportQuality to low
				else if default_qual is "Medium" then
					set exportQuality to medium
				else if default_qual is "High" then
					set exportQuality to high
				else if default_qual is "Maximum" then
					set exportQuality to maximum
				else
					set exportQuality to lossless
				end if
			end tell
		end using terms from
	end if
	set thisFile to (choose file) as string
	-- thisFile stored as a string as needed by image events, converted to alias below for iMagine
	my rescale_and_save(thisFile)
end run

on rescale_and_save(this_item)
	if themethod is not "No Scale" then
		if hasip then
			using terms from application "iMagine Photo"
				tell application ipName
					launch
					set thisImporter to import graphic (this_item as alias)
					if the component error of thisImporter is equal to 0 then
						my CreateReplacingExporterLikeImporter(thisImporter)
						if themethod is "Pixels" then
							set {x, y, current_width, current_height} to the natural bounds of thisImporter
							set theScale to theValue / current_width
						else
							set theScale to theValue
						end if
						set the scale of thisImporter to {theScale, theScale}
						set the export compression quality of thisImporter to exportQuality
						export thisImporter
					end if
					close thisImporter
				end tell
			end using terms from
		else
			tell application "Image Events"
				launch
				-- open the image file
				set this_image to open this_item
				set typ to this_image's file type
				if themethod is "Pixels" then
					copy dimensions of this_image to {current_width, current_height}
					if current_width is greater than current_height then
						scale this_image to size theValue
					else
						-- figure out new height
						-- y2 = (y1 * x2) / x1
						set the new_height to (current_height * target_width) / current_width
						scale this_image to size new_height
					end if
				else if themethod is "Percentage" then
					scale this_image by factor theValue
				end if
				save this_image as typ
			end tell
		end if
	end if
end rescale_and_save

on CreateReplacingExporterLikeImporter(theInitialImporter)
	using terms from application "iMagine Photo"
		tell application ipName
			try
				tell theInitialImporter
					set theImporterType to the graphic type
					set exportType to my GetExportTypeFromImportType(theImporterType)
					make exporter with properties {export file type:exportType}
					if the export component error is not equal to 0 then
						set the export file type to "TIFF"
					end if
					set export file location to file location as alias
				end tell
			end try
		end tell
	end using terms from
end CreateReplacingExporterLikeImporter

on GetExportTypeFromImportType(theimportType)
	if theimportType is equal to "Photo - JPEG" then
		return "JPEG"
	else if theimportType contains "TIFF" then
		return "TIFF"
	else if theimportType is equal to "QuickDraw" then
		return "PICT"
	else if theimportType is equal to "Planar RGB" then
		return "Photoshop"
	else if theimportType is equal to "JPEG 2000" then
		return "JP2"
	else
		return theimportType
	end if
end GetExportTypeFromImportType

on appExists(appName, theid)
	try
		-- is it running?
		tell application "System Events"
			if (name of processes) contains appName then return true
		end tell
		-- is it in a standard location on the hard drive?
		tell application "Finder"
			--if exists file (appName & ".app") of (path to applications folder) then return true
			--this should work regardless of whether the app name end in .app :
			if exists file (appName) of (path to applications folder from system domain) then return true
			if exists file (appName) of (path to applications folder from user domain) then return true
			if exists file (appName) of (path to applications folder from local domain) then return true
		end tell
		-- can we get it by id type?
		tell application "Finder"
			if exists application file id theid then return true
		end tell
		return false
	on error
		return false
	end try
end appExists

Wooden Brain,

hey Mr Brain are you the brainy one. :slight_smile: sorry for the bad joke.

As to the script locations you have a point, but it is unlikely I’ll get around to doing it. My time for iMagine Photo is pretty limited these days.

One more thing though, you mentioned you wanted to have iMagine Photo run as a background application. You can control that.

you can find out if iMagine Photo is running in the background by using the following in an iMagine Photo block.

set isBackground to run in background

You can tell iMagine Photo to run as a background only app next time it runs by doing the following

 set run in background to true

You can also set a quit delay which means that iMagine Photo when running as a background only application will quit automatically if there is no requests of it and there are no objects still open after a set amount of time. For example the following will tell iMagine Photo to quit after 10 seconds if running as a background only application. iMagine Photo does not remember the quit delay setting between each time it runs.

 set quit delay to 10

You can add a small section to your script to set this the first time your script runs iMagine Photo.


tell application "iMagine Photo"
launch
if run in background is false then
set run in background to true
quit
do shell script "sleep 3"
launch
end if
end tell

Kevin