From d040da7c87d33a77c7d8629e8d82e791e49e6d31 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E8=AB=8F=E8=A8=AA=E5=AD=90?= Date: Tue, 24 Oct 2023 12:16:55 +0900 Subject: [PATCH 1/1] =?utf8?q?=E6=9C=80=E5=88=9D=E3=82=B3=E3=83=9F?= =?utf8?q?=E3=83=83=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + Makefile | 24 ++++++++++++ format/png.c | 78 ++++++++++++++++++++++++++++++++++++++ format/png.h | 10 +++++ main.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 216 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 format/png.c create mode 100644 format/png.h create mode 100644 main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f965bf2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +mivfx diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..530f3ec --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +NAME=mivfx +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 +CFLAGS=-Wall -Wextra -g +LDFLAGS=-lX11 -lpng + +all: + ${CC} ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS} + +clean: + rm -f ${NAME} + +install: all + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f ${NAME} ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME} + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/${NAME} + +.PHONY: all clean install uninstall diff --git a/format/png.c b/format/png.c new file mode 100644 index 0000000..f56abd4 --- /dev/null +++ b/format/png.c @@ -0,0 +1,78 @@ +#include "png.h" + +XImage* read_png(Display *d, const char *filename) { + FILE *fp = fopen(filename, "rb"); + if (!fp) { + perror("ファイルを開けられません。"); + return NULL; + } + png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_infop info = png_create_info_struct(png); + + png_init_io(png, fp); + png_read_info(png, info); + + int width = png_get_image_width(png, info); + int height = png_get_image_height(png, info); + int bit_depth = png_get_bit_depth(png, info); + int color_type = png_get_color_type(png, info); + + if (bit_depth == 16) { + png_set_strip_16(png); + } + + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png); + } + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { + png_set_expand_gray_1_2_4_to_8(png); + } + if (png_get_valid(png, info, PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png); + } + if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_filler(png, 0xFF, PNG_FILLER_AFTER); + } + + png_read_update_info(png, info); + + png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); + for (int y = 0; y < height; y++) { + row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png, info)); + } + + png_read_image(png, row_pointers); + + char *imgdata = malloc(4 * width * height); + char *dst = imgdata; + + for (int y = 0; y < height; y++) { + png_bytep row = row_pointers[y]; + for (int x = 0; x < width; x++) { + png_bytep px = &(row[x * 4]); + *dst++ = px[2]; // 青 + *dst++ = px[1]; // 緑 + *dst++ = px[0]; // 赤 + *dst++ = px[3]; // 透明 + } + } + + // 掃除 + for (int y = 0; y < height; y++) { + free(row_pointers[y]); + } + free(row_pointers); + + png_destroy_read_struct(&png, &info, NULL); + fclose(fp); + + // XImageを創作 + XImage* img = XCreateImage(d, CopyFromParent, 24, ZPixmap, 0, imgdata, width, height, 32, 0); + if (img == NULL) { + free(imgdata); + fprintf(stderr, "PNGのXImageを創作に失敗しました。\n"); + return NULL; + } + + return img; +} diff --git a/format/png.h b/format/png.h new file mode 100644 index 0000000..0bdaffa --- /dev/null +++ b/format/png.h @@ -0,0 +1,10 @@ +#ifndef _PNG_H +#define _PNG_H + +#include +#include +#include + +XImage* read_png(Display *d, const char *filename); + +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..7ce2d63 --- /dev/null +++ b/main.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "format/png.h" + +int XErrorHandlerd(Display *d, XErrorEvent *event) { + char error_text[120]; + XGetErrorText(d, event->error_code, error_text, sizeof(error_text)); + fprintf(stderr, "Xエラー: %s\n", error_text); + return 0; +} + +XImage* openimg(Display *d, const char *filename) { + FILE *fp; + fp = fopen(filename, "rb"); + if (!fp) { + perror("ファイルを開けられません。"); + return NULL; + } + + unsigned char buf[16]; + fread(buf, 1, 16, fp); + fclose(fp); + + if (memcmp(buf, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) == 0) { // PNG + return read_png(d, filename); + } + + fprintf(stderr, "不明なファイル種類。\n"); + return NULL; +} + +int main(int argc, char **argv) { + XSetErrorHandler(XErrorHandlerd); + if (argc < 2) { + printf("使用方法: %s <画像ファイル>\n", argv[0]); + return 1; + } + + Display *d = XOpenDisplay(NULL); + if (d == NULL) { + fprintf(stderr, "画面を開けられません。\n"); + return 1; + } + + int scr = DefaultScreen(d); + Window w = XCreateSimpleWindow(d, RootWindow(d, scr), 0, 0, 500, 500, 1, BlackPixel(d, scr), WhitePixel(d, scr)); + XSelectInput(d, w, ExposureMask | KeyPressMask); + XMapWindow(d, w); + XFlush(d); + + GC gc = XCreateGC(d, w, 0, NULL); + if (gc == NULL) { + fprintf(stderr, "グラフィックス内容を創作に失敗しました。\n"); + return 1; + } + + XImage *ximg = openimg(d, argv[1]); + if (ximg == NULL) { + fprintf(stderr, "画像を開けられません: %s\n", argv[1]); + XFreeGC(d, gc); + XCloseDisplay(d); + return 1; + } + + double scale = 1.0; + + while (1) { + XEvent e; + XNextEvent(d, &e); + + if (e.type == Expose) { + int nw = (int)(ximg->width * scale); + int nh = (int)(ximg->height * scale); + XPutImage(d, w, gc, ximg, 0, 0, 0, 0, nw, nh); + } + + if (e.type == KeyPress) { + XWindowAttributes attrs; + XGetWindowAttributes(d, w, &attrs); + + KeySym keysym = XLookupKeysym(&e.xkey, 0); + + if (keysym == XK_q) { + break; + } + } + } + + // 掃除 + XFreeGC(d, gc); + XDestroyImage(ximg); + XDestroyWindow(d, w); + XCloseDisplay(d); + + return 0; +} -- 2.43.0