最初コミット

このコミットが含まれているのは:
守矢諏訪子 2023-10-24 12:16:55 +09:00
コミット d040da7c87
5個のファイルの変更216行の追加0行の削除

1
.gitignore vendored ノーマルファイル
ファイルの表示

@ -0,0 +1 @@
mivfx

24
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

78
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;
}

10
format/png.h ノーマルファイル
ファイルの表示

@ -0,0 +1,10 @@
#ifndef _PNG_H
#define _PNG_H
#include <stdlib.h>
#include <X11/Xlib.h>
#include <png.h>
XImage* read_png(Display *d, const char *filename);
#endif

103
main.c ノーマルファイル
ファイルの表示

@ -0,0 +1,103 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#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;
}