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 best solutions below

3
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
On

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

0
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
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.
   } 
}