CImg: how to test that a file is image

1.8k views Asked by At

I am writing small C program using Cimg graphics library and need to test that a file is an image.

I attempted to load the file/image with

CImg<unsigned char> srcimg(filename)

and catch the exemption but the cimg flattly quits with:

convert.im6: improper image header `pok.txt' @ error/bmp.c/ReadBMPImage/603.
convert.im6: no images defined `pnm:-' @ error/convert.c/ConvertImageCommand/3044.
sh: 1: gm: not found
terminate called after throwing an instance of 'cimg_library::CImgIOException'
  what():  [instance(0,0,0,0,(nil),non-shared)] CImg<unsigned char>::load() : Failed to recognize format of file 'pok.txt'.
Aborted

Of course, the file is txt, but ignoring the suffix, is there a proper way how to test this? Without involving another dependencies/libraries.

Thanks

4

There are 4 answers

3
Jongware On

Do you need an exhaustive test, or do you only have to differ between a number of candidates?

To quickly find an appropriate file type, all you need to do is read the first bytes out of the file. Then,

  • if these are 'BM' it's a Windows BMP
  • if these are 0x89 'PNG' it's a PNG
  • both 'II' and 'MM' indicate a TIFF file
  • the sequence 0xFF 0xD8 0xFF 0xE0 is a typical start of a JPEG file (there are some others).

Once you find a possible file format, you can attempt load the image with the proper routine in your image library, and if that fails it wasn't a valid image to begin with.

An exhaustive test -- say, you find it's possibly a BMP file because it starts with BM -- is far more work. You then need to read the whole file and validate its entire contents, according to the specifications of each separate image type.

0
M Katz On

My version of CImg (148) has a function file_type(). Is that not reliable?

0
user2389519 On

Well, the answer is (for my purposes at least) simple: Cimg exception handling: http://cimg.sourceforge.net/reference/structcimg__library_1_1CImgException.html

This way I can go on with processing of next images

0
bvalabas On

As proposed above, the best thing to do is to catch the exception when there is one thrown by CImg, and skip that particular file when it happens. Something like :

CImg<> img;
const char *const filename[] = { "foo.txt", "foo.bmp", "foo.jpg" }
for (unsigned int i = 0; i<3; ++i) {
   try { img.load(filename[i]); } catch (CImgException) { img.assign(); }
   if (img) {
       .. Do what you want on your image now.
   } 
}