James,
When you strip out all of the duplications and optional parts that won't be used, your pattern reduces to:
<img.*?(?:src=(['"])https?://(\S+)\1)[^>]*/?>
(I've taken the liberty of actually checking for the matching single- or double-quote which you seem to be setting up but not using.)
The reason is that, once you use the '(\S+)' sub-pattern, then the regex engine will have matched every non-space character it can find and it will only backtrack to locate the '/?>' part at the end. The other optional sub-patterns that follow the '(\S+)' part will all be ignored as they are only looking for non-space characters that will have already been matched by the '(\S+)'.
The problem of determining if a URL is valid or not is non-trivial and, as the gurus of this forum (ddrudik, mash et al) have often said, it cannot really be done by a regex. What you consider 'valid' may not be what I do, and something that both of us agree is 'valid' may not represent something that actually exists in the (cyber)world.
Also, are you wanting to match an invalid URL so that you can replace it with a null string, match it so that the 'then' clause of an 'if... then' statement will be used to remove the whole tag, or are you wanting to fail a match if the URL is invalid (presumably because you want to sue the 'else' clause of an 'if...then...else' statement).
There are two methods that I tend to use to exclude something from a match:
1) if the unwanted string is known to exist at a certain point in the string, then use a negative lookahead at that point:
src=(?!")\S+
will not match the literal string 'src=' that is followed by a double-quote but is followed by any other non-space character.
2) if the character string is somewhere ahead of you but you don't know where, then something like:
src="(((?!abc).)+)"
will match whatever follows the 'src="' until the next double quote UNLESS the string "abc" is found. This technique moves forward 1 character at a time to perform the search and match process.
If you can decide exactly what you mean by a 'valid URL' then technique #1 is probably the one you want. IF you decide that an 'invalid URL' is one that contains some pattern somewhere inside it, then technique #2 is the one you might consider.
Susan