It is time to be pedantic.
You should avoid downloading images, but that is OK because it is impossible to download an image anyway. All that can be transmitted across a network is files (to be even more pedantic, sequences of bytes.
No downloaded file is ever unsafe. It only becomes unsafe once you start to do something with it. For instance, if you pass those bytes to a so-called “image decoder” which has two functions: (a) if the bytes represent a valid image, do something rational such as converting the image to another format; (b) if the bytes do not represent a valid image, do something harmful to the system - then harm can result. The reason we distrust images and call them”unsafe” is that we are mostly using image decoders that contain, by design, some elements of function (b).
In your particular case, therefore:
Downloading a file is always safe. In fact, for your purposes you only need to download a small initial portion of it, so you do not even have to worry about “what if the file is 1GB in size?”
Treating the downloaded file as an image file is never safe - unless you can guarantee that the program, function or library doing the treating is guaranteed never to perform function (b), “damage the system”.
Accordingly, do not use an image decoder on the downloaded file.
Instead, do your own interpretation and validation. For instance, read about the image file formats and work out, yourself, how to extract parameters such as size and format. This is very simple and completely safe. The result will be “Yes, this is a not-obviously-invalid PNG of such and such a size”, “Yes, this is a not-obviously-invalid JPEG of such and such a size”, “No, this is none of the above”.
You say that your validation code only needs to extract size and format and resolution information. Doing it yourself without relying on library functions or deciders is absolutely safe.
Moreover, the validation you describe can be performed using only the first few bytes of the downloaded file.