2
$\begingroup$

I have a directory of images that might not have downloaded, and need to delete the duds.

This is too slow: Import /* ImageQ /@ fileNames

In bash, I use the file command to inspect the metadata of an image file's header, but ImageQ only works on in-memory images not paths or File objects.

Is there some way to do this efficiently, without importing them? There's a function for this I forgot.

Update:

FileFormat has a problem - it checks all known filetypes! e.g. you can't just check if the file is one of a list {"JPEG","PNG","TIFF"}.

$\endgroup$
8
  • $\begingroup$ If you don't want to import them, then all you have is the file's extension, right? Or what other property would you like to check without looking inside the file? $\endgroup$
    – MarcoB
    Aug 12, 2020 at 20:30
  • 1
    $\begingroup$ Make an image called "myfile.jpg" but then remove the extension. FileFormat["myfile"] will still return JPEG. Presumably it inspects the file's magic number FFD8FF and determines it looks like a JPEG. Of course it could be a coincidence or a corrupt file. Only parsing the headers would determine it was a valid JPEG file which is tantamount to Import-ing it $\endgroup$
    – flinty
    Aug 12, 2020 at 21:30
  • $\begingroup$ @flinty Yup FileFormat was the symbol I was forgetting, thanks! $\endgroup$
    – M.R.
    Aug 12, 2020 at 23:07
  • 1
    $\begingroup$ What is the problem in the update? Couldn't you just check MemberQ[{"JPEG", "PNG", "TIFF"}, FileFormat[f]] or is it too slow? $\endgroup$
    – flinty
    Aug 17, 2020 at 20:56
  • $\begingroup$ FileFormat checks all these: is a pdf, is it HTML, is it bson... That's inefficient $\endgroup$
    – M.R.
    Aug 17, 2020 at 22:31

1 Answer 1

1
$\begingroup$

Maybe this helps you already:

Lets take the filenames as a provided list as you suggest.

fileNames = {} (*your list here*)

First, lets time the code you provided:

AbsoluteTiming[Import /* ImageQ /@ fileNames]

{0.204095, {True, True, True, True}}

Speed up by a factor of 2 gives this code:

AbsoluteTiming[MemberQ[Import[#, "Elements"], "Image"] & /@ fileNames]

{0.0822613, {True, True, True, True}}

Speed up by a factor of 20 seems to give this:

Extensions = {‰PNG, ‰JPG} (*or other extensions*)
AbsoluteTiming[MemberQ[Extensions, First@ReadList[#, Expression, 1]] & /@ fileNames]

{0.00788099, {True, True, True, True}}

Note that the last code also works if you delete the .png extension from the file name. So "image.png" and "image" give both True.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.