Read width and height from jpeg, png and gif files directly instead of executing w3mimgdisplay -size.
This commit is contained in:
committed by
Tatsuya Kinoshita
parent
0d99209d9f
commit
0c0d4b5f38
91
image.c
91
image.c
@@ -625,6 +625,91 @@ getImage(Image * image, ParsedURL *current, int flag)
|
||||
return cache;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
jpg_error:
|
||||
fclose(fp);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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 (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gif_error:
|
||||
fclose(fp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
getImageSize(ImageCache * cache)
|
||||
{
|
||||
@@ -637,6 +722,10 @@ getImageSize(ImageCache * cache)
|
||||
if (!cache || !(cache->loaded & IMG_FLAG_LOADED) ||
|
||||
(cache->width > 0 && cache->height > 0))
|
||||
return FALSE;
|
||||
|
||||
if (parseImageHeader(cache->file, &w, &h))
|
||||
goto got_image_size;
|
||||
|
||||
tmp = Strnew();
|
||||
if (!strchr(Imgdisplay, '/'))
|
||||
Strcat_m_charp(tmp, w3m_auxbin_dir(), "/", NULL);
|
||||
@@ -652,6 +741,8 @@ getImageSize(ImageCache * cache)
|
||||
|
||||
if (!(w > 0 && h > 0))
|
||||
return FALSE;
|
||||
|
||||
got_image_size:
|
||||
w = (int)(w * image_scale / 100 + 0.5);
|
||||
if (w == 0)
|
||||
w = 1;
|
||||
|
Reference in New Issue
Block a user