aboutsummaryrefslogtreecommitdiffstats
path: root/image.c
diff options
context:
space:
mode:
authorAraki Ken <arakiken@users.sf.net>2014-03-01 06:31:27 +0000
committerTatsuya Kinoshita <tats@debian.org>2014-12-06 11:47:04 +0000
commit0c0d4b5f387483dac627349e3415d5a7e7177fb2 (patch)
tree36af390b9874a199c2447735e4d0dbf2550c1ee7 /image.c
parent* display.c: Draw underline on anchor text which is not overlapped with any i... (diff)
downloadw3m-0c0d4b5f387483dac627349e3415d5a7e7177fb2.tar.gz
w3m-0c0d4b5f387483dac627349e3415d5a7e7177fb2.zip
Read width and height from jpeg, png and gif files directly instead of executing w3mimgdisplay -size.
Diffstat (limited to 'image.c')
-rw-r--r--image.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/image.c b/image.c
index 51e3903..3c2a9ab 100644
--- a/image.c
+++ b/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;