]> Nishi Git Mirror - mivfx.git/commitdiff
WEBP対応 3/head
author諏訪子 <suwako@076.moe>
Tue, 24 Oct 2023 11:39:40 +0000 (20:39 +0900)
committer諏訪子 <suwako@076.moe>
Tue, 24 Oct 2023 11:39:40 +0000 (20:39 +0900)
Makefile
format/webp.c [new file with mode: 0644]
format/webp.h [new file with mode: 0644]
main.c

index 530f3ec27d2851029eb78104dd5cccfbb6598adb..49b7d81f1763d9a9a287b419b56371e9e96016ac 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,9 +3,9 @@ VERSION=0.1.0
 # Linux、Haiku、かIllumos = /usr、FreeBSDかOpenBSD = /usr/local、NetBSD = /usr/pkg
 PREFIX=/usr
 CC=cc
-FILES=main.c format/png.c
+FILES=main.c format/png.c format/webp.c
 CFLAGS=-Wall -Wextra -g
-LDFLAGS=-lX11 -lpng
+LDFLAGS=-lX11 -lpng -lwebp
 
 all:
        ${CC} ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS}
diff --git a/format/webp.c b/format/webp.c
new file mode 100644 (file)
index 0000000..8f7c423
--- /dev/null
@@ -0,0 +1,50 @@
+#include "webp.h"
+
+XImage* read_webp(Display *d, const char *filename) {
+  FILE *fp = fopen(filename, "rb");
+  if (!fp) {
+    perror("ファイルを開けられません。");
+    return NULL;
+  }
+
+  fseek(fp, 0, SEEK_END);
+  size_t filesize = ftell(fp);
+  fseek(fp, 0, SEEK_SET);
+
+  uint8_t *data = malloc(filesize);
+  fread(data, filesize, 1, fp);
+  fclose(fp);
+
+  int width, height;
+  uint8_t *imgdata = WebPDecodeRGBA(data, filesize, &width, &height);
+  free(data);
+
+  if (imgdata == NULL) {
+    fprintf(stderr, "WEBP画像を逆符号化に失敗しました。\n");
+    return NULL;
+  }
+
+  // RGBAからARGBに交換(X11の為)
+  uint32_t *argbdata = malloc(4 * width * height);
+  uint32_t *dest = argbdata;
+  uint8_t *src = imgdata;
+  for (int y = 0; y < height; ++y) {
+    for (int x = 0; x < width; ++x) {
+      uint8_t r = *src++;
+      uint8_t g = *src++;
+      uint8_t b = *src++;
+      uint8_t a = *src++;
+      *dest++ = (a << 24) | (r << 16) | (g << 8) | b;
+    }
+  }
+  free(imgdata);
+
+  XImage* img = XCreateImage(d, CopyFromParent, 24, ZPixmap, 0, (char*)argbdata, width, height, 32, 0);
+  if (img == NULL) {
+    free(argbdata);
+    fprintf(stderr, "WEBPのXImageを創作に失敗しました。\n");
+    return NULL;
+  }
+
+  return img;
+}
diff --git a/format/webp.h b/format/webp.h
new file mode 100644 (file)
index 0000000..fa83d58
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _WEBP_H
+#define _WEBP_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <webp/decode.h>
+
+XImage* read_webp(Display *d, const char *filename);
+
+#endif
diff --git a/main.c b/main.c
index 7ce2d63342f98202000ca1275775a36a5e364c03..c9a528db93640572f19f7046fe721c1e0caaa55e 100644 (file)
--- a/main.c
+++ b/main.c
@@ -8,6 +8,7 @@
 #include <X11/keysym.h>
 
 #include "format/png.h"
+#include "format/webp.h"
 
 int XErrorHandlerd(Display *d, XErrorEvent *event) {
   char error_text[120];
@@ -30,6 +31,8 @@ XImage* openimg(Display *d, const char *filename) {
 
   if (memcmp(buf, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) == 0) { // PNG
     return read_png(d, filename);
+  } else if (memcmp(buf + 8, "WEBP", 4) == 0) { // WEBP
+    return read_webp(d, filename);
   }
 
   fprintf(stderr, "不明なファイル種類。\n");