aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAraki Ken <arakiken@users.sf.net>2014-03-01 07:16:48 +0000
committerTatsuya Kinoshita <tats@debian.org>2014-12-06 11:47:04 +0000
commite6856f2329a68e93704db4eab35a934d2a54e40f (patch)
tree42e578b8d190c30a6404665c26ce2bdb4ce03b8d
parentRead width and height from jpeg, png and gif files directly instead of execut... (diff)
downloadw3m-e6856f2329a68e93704db4eab35a934d2a54e40f.tar.gz
w3m-e6856f2329a68e93704db4eab35a934d2a54e40f.zip
Determine the format of an image file by its header data not by its file name suffix.
-rw-r--r--image.c116
1 files changed, 51 insertions, 65 deletions
diff --git a/image.c b/image.c
index 3c2a9ab..fdc9b27 100644
--- a/image.c
+++ b/image.c
@@ -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