diff options
author | Araki Ken <arakiken@users.sf.net> | 2014-03-01 07:16:48 +0000 |
---|---|---|
committer | Tatsuya Kinoshita <tats@debian.org> | 2014-12-06 11:47:04 +0000 |
commit | e6856f2329a68e93704db4eab35a934d2a54e40f (patch) | |
tree | 42e578b8d190c30a6404665c26ce2bdb4ce03b8d /image.c | |
parent | Read width and height from jpeg, png and gif files directly instead of execut... (diff) | |
download | w3m-e6856f2329a68e93704db4eab35a934d2a54e40f.tar.gz w3m-e6856f2329a68e93704db4eab35a934d2a54e40f.zip |
Determine the format of an image file by its header data not by its file name suffix.
Diffstat (limited to 'image.c')
-rw-r--r-- | image.c | 116 |
1 files changed, 51 insertions, 65 deletions
@@ -628,86 +628,72 @@ getImage(Image * image, ParsedURL *current, int flag) static int parseImageHeader(char *path, u_int *width, u_int *height) { - char *suffix; - - suffix = path + strlen(path); - if (strcasecmp(suffix - 5, ".jpeg") == 0 || strcasecmp(suffix - 4 , ".jpg") == 0) { - FILE *fp = fopen(path, "r"); - if (fp) { - u_char buf[2]; - if (fread(buf, 1, 2, fp) != 2 || memcmp(buf, "\xff\xd8", 2) != 0 || - fseek(fp, 2, SEEK_CUR) < 0) /* 0xffe0 */ - goto jpg_error; - - while (fread(buf, 1, 2, fp) == 2) { - size_t len = ((buf[0] << 8) | buf[1]) - 2; - if (fseek(fp, len, SEEK_CUR) < 0) goto jpg_error; - if (fread(buf, 1, 2, fp) == 2 && memcmp(buf, "\xff\xc0", 2) == 0) { - fseek(fp, 3, SEEK_CUR); + FILE *fp; + u_char buf[8]; + + if (!(fp = fopen(path, "r"))) return FALSE; + + if (fread(buf, 1, 2, fp) != 2) goto error; + + if (memcmp(buf, "\xff\xd8", 2) == 0) { + /* JPEG */ + if (fseek(fp, 2, SEEK_CUR) < 0) goto error; /* 0xffe0 */ + while (fread(buf, 1, 2, fp) == 2) { + size_t len = ((buf[0] << 8) | buf[1]) - 2; + if (fseek(fp, len, SEEK_CUR) < 0) goto error; + if (fread(buf, 1, 2, fp) == 2 && + /* SOF0 or SOF2 */ + (memcmp(buf, "\xff\xc0", 2) == 0 || memcmp(buf, "\xff\xc2", 2) == 0)) { + fseek(fp, 3, SEEK_CUR); + if (fread(buf, 1, 2, fp) == 2) { + *height = (buf[0] << 8) | buf[1]; if (fread(buf, 1, 2, fp) == 2) { - *height = (buf[0] << 8) | buf[1]; - if (fread(buf, 1, 2, fp) == 2) { - *width = (buf[0] << 8) | buf[1]; - fclose(fp); - return TRUE; - } + *width = (buf[0] << 8) | buf[1]; + goto success; } - break; } + break; } - - jpg_error: - fclose(fp); - return FALSE; } + goto error; } - else if (strcasecmp(suffix - 4, ".png") == 0) { - FILE *fp = fopen(path, "r"); - if (fp) { - u_char buf[8]; - if (fread(buf, 1, 8, fp) != 8 || - memcmp(buf, "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) != 0 || - fseek(fp, 8, SEEK_CUR) < 0) - goto png_error; - if (fread(buf, 1, 4, fp) == 4) { - *width = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; - if (fread(buf, 1, 4, fp) == 4) { - *height = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; - fclose(fp); - return TRUE; - } - } + if (fread(buf + 2, 1, 1, fp) != 1) goto error; - png_error: - fclose(fp); - return FALSE; - } - } - else if (strcasecmp(suffix - 4, ".gif") == 0) { - FILE *fp = fopen(path, "r"); - if (fp) { - u_char buf[3]; - if (fread(buf, 1, 3, fp) != 3 || memcmp(buf, "GIF", 3) != 0 || - fseek(fp, 3, SEEK_CUR) < 0) { - goto png_error; - } + if (memcmp(buf, "GIF", 3) == 0) { + /* GIF */ + if (fseek(fp, 3, SEEK_CUR) < 0) goto error; + if (fread(buf, 1, 2, fp) == 2) { + *width = (buf[1] << 8) | buf[0]; if (fread(buf, 1, 2, fp) == 2) { - *width = (buf[1] << 8) | buf[0]; - if (fread(buf, 1, 2, fp) == 2) { - *height = (buf[1] << 8) | buf[0]; - fclose(fp); - return TRUE; - } + *height = (buf[1] << 8) | buf[0]; + goto success; } } + } - gif_error: - fclose(fp); - return FALSE; + if (fread(buf + 3, 1, 5, fp) != 5) goto error; + + if (memcmp(buf, "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0) { + /* PNG */ + if (fseek(fp, 8, SEEK_CUR) < 0) goto error; + if (fread(buf, 1, 4, fp) == 4) { + *width = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + if (fread(buf, 1, 4, fp) == 4) { + *height = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + goto success; + } + } } +error: + fprintf(stderr,"%s\n",path); + fclose(fp); return FALSE; + +success: + fclose(fp); + return TRUE; } int |