The usual shell command is find. The options to find are really a small language. Learning how to put the available options together takes time. It may not always be obvious how to modify an existing list of options to add a new search criteria.
find can be faster than a search in Finder, but there are fundamental differences in how they work. find works at the POSIX level and takes no notice of file packages (directories of files that appear as a single item in Finder (e.g. most applications)). Images inside packages will be skipped by the Finder code you were using, but find will ignore the package status of a directory and search inside it. Not all the metadata available to Finder is directly available to find (type, creator, UI positioning info, icon, Get Info comments, displayed name, etc.). Great care must be taken in quoting the arguments to find to make sure nothing is interpreted incorrectly. Also, since find’s output is mostly plain text, care must be taken to make sure that filenames that include newlines or carriage returns are preserved (they are valid file name characters, though Finder usually does a good job dissuading the user from employing them).
The following code uses find to search for files that have extensions in a specified list.
on run
	set fileTypes to {"psd", "tif", "jpg", "png", "gif", "bmp", "eps", "ai", "pdf"}
	set theItem to alias ((path to desktop as Unicode text) & "stuff:") -- 3496 files in 290 directories; 3248 items (47 packages) in 160 folders
	--set theItem to alias ((path to startup disk as Unicode text) & "Applications:Utilities:") -- 12574 files in 5185 directories; 43 items (34 packages) in 6 folders
	set t0 to current date
	with timeout of 600 seconds
		tell application "Finder" to set ImageCount to (every file of entire contents of theItem whose name extension is in fileTypes)
	end timeout
	set t1 to current date
	set foundFiles to findFiles(POSIX path of theItem, fileTypes)
	set t2 to current date
	{t1 - t0, length of ImageCount, t2 - t1, length of foundFiles}
	--> /Applications/Utilities: {0, 0, 12, 1134}: Finder takes less than 1 second to find 0 matching items, find takes 12 seconds to find 1134 matching files
	--> ~/Desktop/stuff: {213, 689, 4, 714}: Finder takes 213 seconds to find 689 matching items, find takes 4 seconds to find 714 matching files
end run
to findFiles(startDirectory, extensionList)
	if class of extensionList is not list then
		set extensionList to {extensionList}
	else
		(* Duplicate the list, because it will be destructively modified by buildFind0Command.
		* We should not stomp on our caller's parameters unless it is clearly documented (like convertPOSIXPathsToFiles and convertItemsToAliases do).
		*)
		copy extensionList to extensionList
	end if
	set find0Cmd to buildFind0Command(startDirectory, extensionList)
	-- use "true" to ignore the exit code of find, this is needed if there might be any unreadable directories under startDirectory
	set cmd to find0Cmd & ";true"
	set findResults to do shell script cmd without altering line endings
	set posixPaths to extractFind0Results(findResults)
	set theFiles to convertPOSIXPathsToFiles(posixPaths)
	convertItemsToAliases(theFiles) -- if desired
end findFiles
to buildFind0Command(startDirectory, extensionList)
	"find " & quoted form of startDirectory & " -type f " & buildExtensionsClause(extensionList) & " -print0"
end buildFind0Command
to buildExtensionsClause(extensionList)
	if length of extensionList is 0 then return ""
	repeat with e in extensionList
		-- use -iname to match the normal case insensitivity exhibited in Finder
		set contents of e to "-iname \\*." & quoted form of quoteForFindNamePredicate(contents of e)
	end repeat
	if length of extensionList is greater than 1 then
		set {otid, text item delimiters} to {text item delimiters, {" -or "}}
		try
			set extensionClause to "\\( " & (extensionList as Unicode text) & " \\)"
			set text item delimiters to otid
		on error m number n from o partial result r to t
			set text item delimiters to otid
			error m number n from o partial result r to t
		end try
	else
		set extensionClause to first item of extensionList
	end if
	return extensionClause
end buildExtensionsClause
to quoteForFindNamePredicate(nameString)
	-- all of "[]*?" should be quoted with a backslash
	repeat with c in "[]*?"
		set c to contents of c
		set nameString to switchText from nameString to ("\\" & c) instead of c
	end repeat
	nameString
end quoteForFindNamePredicate
(* switchText From: http://bbs.applescript.net/viewtopic.php?pid=41257#p41257
Credit: kai, Nigel Garvey*)
to switchText from t to r instead of s
	local d
	set d to text item delimiters
	try
		set text item delimiters to s
		set t to t's text items
		-- The text items will be of the same class (string/unicode text) as the original string.
		set text item delimiters to r
		-- Using the first text item (beginning) as the first part of the concatentation means we preserve the class of the original string in the edited string.
		tell t to set t to beginning & ({""} & rest)
		set text item delimiters to d
	on error m number n from o partial result r to t
		set text item delimiters to d
		error m number n from o partial result r to t
	end try
	t
end switchText
to extractFind0Results(findResults)
	-- break up the null-delimited result of "find -print0"
	set {otid, text item delimiters} to {text item delimiters, {ASCII character 0}}
	try
		set foundPaths to text items of findResults
		set text item delimiters to otid
	on error m number n from o partial result r to t
		set text item delimiters to otid
		error m number n from o partial result r to t
	end try
	-- the output from "find -print0" always ends in a null, so drop the final, always empty entry
	if length of foundPaths is greater than 1 then
		set foundPaths to items 1 through -2 of foundPaths
	else
		set foundPaths to {}
	end if
	foundPaths
end extractFind0Results
to convertPOSIXPathsToFiles(posixPaths)
	-- changes the contents of the list passed as posixPaths!
	repeat with p in posixPaths
		set contents of p to POSIX file (contents of p)
	end repeat
	posixPaths
end convertPOSIXPathsToFiles
to convertItemsToAliases(theItems)
	-- changes the contents of the list passed as theItems!
	repeat with i in theItems
		set contents of i to contents of i as alias
	end repeat
	theItems
end convertItemsToAliases
Edit History: Added without altering line endings to do shell script otherwise, line feeds are changed to carriage returns. 2009-01-30: Corrected bug involving inadvertent modification of contents of list passed to findFiles as extensionList. Thanks to Jerome for reporting the problem.