- i_test_format_probe() now attempts to detect MS Windows Icon/cursor files
authorTony Cook <tony@develop=help.com>
Thu, 23 Mar 2006 13:41:56 +0000 (13:41 +0000)
committerTony Cook <tony@develop=help.com>
Thu, 23 Mar 2006 13:41:56 +0000 (13:41 +0000)
- made the TGA probe a bit more specific since it was giving false
  positives on icon files.

image.c
imager.h
t/t1000files.t
tga.c

diff --git a/image.c b/image.c
index 2d1b2ae..1b5cec3 100644 (file)
--- a/image.c
+++ b/image.c
@@ -2122,13 +2122,15 @@ Check the beginning of the supplied file for a 'magic number'
 #define FORMAT_ENTRY(magic, type) \
   { (unsigned char *)(magic ""), sizeof(magic)-1, type }
 
-char *
-i_test_format_probe(io_glue *data, int length) {
-  static struct {
+struct magic_entry {
     unsigned char *magic;
     size_t magic_size;
     char *name;
-  } formats[] = {
+};
+
+const char *
+i_test_format_probe(io_glue *data, int length) {
+  static struct magic_entry formats[] = {
     FORMAT_ENTRY("\xFF\xD8", "jpeg"),
     FORMAT_ENTRY("GIF87a", "gif"),
     FORMAT_ENTRY("GIF89a", "gif"),
@@ -2143,10 +2145,13 @@ i_test_format_probe(io_glue *data, int length) {
     FORMAT_ENTRY("P5", "pnm"),
     FORMAT_ENTRY("P6", "pnm"),
   };
+  static struct magic_entry more_formats[] = {
+    FORMAT_ENTRY("\x00\x00\x01\x00", "ico"),
+    FORMAT_ENTRY("\x00\x00\x02\x00", "ico"), /* cursor */
+  };
 
   unsigned int i;
   unsigned char head[18];
-  char *match = NULL;
   ssize_t rc;
 
   io_glue_commit_types(data);
@@ -2160,29 +2165,25 @@ i_test_format_probe(io_glue *data, int length) {
       continue;
     c = !memcmp(formats[i].magic, head, formats[i].magic_size);
     if (c) {
-      match = formats[i].name;
-      break;
+      return formats[i].name;
     }
   }
 
-  /*
-    if (match && !strcmp(match, "jpeg")) {
-    unsigned int x0, x1;
-    rc = data->readcb(data, head, 18);
-    if (rc == -1) return NULL;
-    x0 = (unsigned char)head[0];
-    x1 = (unsigned char)head[1];
-    data->seekcb(data, -rc, SEEK_CUR);
-    printf("Jpeg reread: %x %x\n", x0, x1);
-    }
-  */
-
-  if (!match && 
-      (rc == 18) &&
+  if ((rc == 18) &&
       tga_header_verify(head))
     return "tga";
 
-  return match;
+  for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) { 
+    int c;
+    if (rc < more_formats[i].magic_size)
+      continue;
+    c = !memcmp(more_formats[i].magic, head, more_formats[i].magic_size);
+    if (c) {
+      return more_formats[i].name;
+    }
+  }
+
+  return NULL;
 }
 
 
index 5991268..e72d0c6 100644 (file)
--- a/imager.h
+++ b/imager.h
@@ -351,7 +351,7 @@ extern i_img *i_img_double_new(int x, int y, int ch);
 extern i_img *i_img_double_new_low(i_img *im, int x, int y, int ch);
 
 
-char * i_test_format_probe(io_glue *data, int length);
+const char * i_test_format_probe(io_glue *data, int length);
 
 
 #ifdef HAVE_LIBJPEG
index b306e2c..341288b 100644 (file)
@@ -5,7 +5,7 @@
 
 use strict;
 use lib 't';
-use Test::More tests => 18;
+use Test::More tests => 20;
 use Imager;
 
 Imager::init_log("testout/t1000files.log", 1);
@@ -73,11 +73,24 @@ probe_ok("49492A00", "tiff", "tiff intel");
 probe_ok("4D4D002A", "tiff", "tiff motorola");
 probe_ok("474946383961", "gif", "gif 89");
 probe_ok("474946383761", "gif", "gif 87");
+probe_ok(<<TGA, "tga", "TGA");
+00 00 0A 00 00 00 00 00 00 00 00 00 96 00 96 00
+18 20 FF 00 00 00 95 00 00 00 FF 00 00 00 95 00
+00 00 FF 00 00 00 95 00 00 00 FF 00 00 00 95 00
+00 00 FF 00 00 00 95 00 00 00 FF 00 00 00 95 00
+TGA
+
+probe_ok(<<ICO, "ico", "Windows Icon");
+00 00 01 00 02 00 20 20 10 00 00 00 00 00 E8 02
+00 00 26 00 00 00 20 20 00 00 00 00 00 00 A8 08
+00 00 0E 03 00 00 28 00 00 00 20 00 00 00 40 00
+ICO
 
 sub probe_ok {
   my ($packed, $exp_type, $name) = @_;
 
   my $builder = Test::Builder->new;
+  $packed =~ tr/ \r\n//d; # remove whitespace used for layout
   my $data = pack("H*", $packed);
 
   my $io = Imager::io_new_buffer($data);
diff --git a/tga.c b/tga.c
index 230be5b..0326119 100644 (file)
--- a/tga.c
+++ b/tga.c
@@ -329,13 +329,16 @@ tga_header_verify(unsigned char headbuf[18]) {
   default:
     /*printf("bad typecode!\n");*/
     return 0;
-  case 0:
   case 1:  /* Uncompressed, color-mapped images */ 
-  case 2:  /* Uncompressed, rgb images          */ 
   case 3:  /* Uncompressed, grayscale images    */ 
   case 9:  /* Compressed,   color-mapped images */ 
-  case 10: /* Compressed,   rgb images          */ 
   case 11: /* Compressed,   grayscale images    */ 
+    if (header.bitsperpixel != 8)
+      return 0;
+    break;
+  case 0:
+  case 2:  /* Uncompressed, rgb images          */ 
+  case 10: /* Compressed,   rgb images          */ 
          break;
        }
 
@@ -343,10 +346,23 @@ tga_header_verify(unsigned char headbuf[18]) {
   default:
     /*printf("bad colourmaptype!\n");*/
     return 0;
-  case 0:
   case 1:
+    if (header.datatypecode != 1 && header.datatypecode != 9)
+      return 0; /* only get a color map on a color mapped image */
+  case 0:
        break;
        }
+
+  switch (header.colourmapdepth) {
+  default:
+    return 0;
+  case 0: /* can be 0 if no colour map */
+  case 15:
+  case 16:
+  case 24:
+  case 32:
+    break;
+  }
   
   return 1;
 }