SVNからのミラー
This commit is contained in:
34
CHANGELOG.md
Normal file
34
CHANGELOG.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# 0.6.0 (2024/06/07)
|
||||||
|
* MakefileとREADME.mdファイルの更新
|
||||||
|
* NetBSDは「/usr/pkg」→「/usr/local」
|
||||||
|
* スペルミスの修正
|
||||||
|
* manpageでコントロールの説明の追加
|
||||||
|
* 再レンダーリングの問題の修正
|
||||||
|
* 画像回転機能性の追加
|
||||||
|
* 画像反転機能性の追加
|
||||||
|
* 画像をダウンロード機能性
|
||||||
|
|
||||||
|
# 0.5.0 (2024/03/03)
|
||||||
|
* .desktopファイルの追加
|
||||||
|
* CDNを回避する様に
|
||||||
|
* 画像は大き過ぎるの場合、画面に合うまで小さくにする様に
|
||||||
|
* 「Q」キーを押すと、終了する様に
|
||||||
|
* サイズ変更の修正
|
||||||
|
* Pixivからダウンロード出来る様に
|
||||||
|
* ズーム機能性の追加
|
||||||
|
* マウスで使って画像を移動出来る様に
|
||||||
|
* OpenBSDで靜的リンクを可能に
|
||||||
|
|
||||||
|
# 0.4.0 (2024/04/07)
|
||||||
|
* URLから画像ファイルを開ける様に
|
||||||
|
* GPLv2→BSD2clouseライセンスに変更
|
||||||
|
* 画面アスペクト比ロック
|
||||||
|
|
||||||
|
# 0.3.0 (2024/03/0?)
|
||||||
|
* 負荷をすくなくするために画面の更新を減らした (たかしさん)
|
||||||
|
|
||||||
|
# 0.2.0 (2024/02/0?)
|
||||||
|
* XlibからSDL2に変えた方が良いと思います
|
||||||
|
|
||||||
|
# 0.1.0 (2024/01/0?)
|
||||||
|
* 開始
|
||||||
13
LICENSE.txt
Normal file
13
LICENSE.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
Copyright © 2018-2024 by 076.moe
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||||
|
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||||
|
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||||
|
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
SOFTWARE.
|
||||||
78
Makefile
Normal file
78
Makefile
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
UNAME_S!=uname -s
|
||||||
|
UNAME_M!=uname -m
|
||||||
|
|
||||||
|
NAME!=cat main.c | grep "const char \*sofname" | awk '{print $$5}' | \
|
||||||
|
sed "s/\"//g" | sed "s/;//"
|
||||||
|
VERSION!=cat main.c | grep "const char \*version" | awk '{print $$5}' | \
|
||||||
|
sed "s/\"//g" | sed "s/;//"
|
||||||
|
PREFIX=/usr/local
|
||||||
|
|
||||||
|
.if ${UNAME_S} == "Linux"
|
||||||
|
PREFIX=/usr
|
||||||
|
.endif
|
||||||
|
|
||||||
|
CC=cc
|
||||||
|
FILES=main.c
|
||||||
|
CFLAGS=-Wall -Wextra -g -I/usr/include -I/usr/local/include
|
||||||
|
LIBS=-lSDL2 -lSDL2_image -lcurl
|
||||||
|
LDFLAGS=-L/usr/lib -L/usr/local/lib
|
||||||
|
MANPREFIX=${PREFIX}/share/man
|
||||||
|
|
||||||
|
.if ${UNAME_S} == "OpenBSD"
|
||||||
|
MANPREFIX=${PREFIX}/man
|
||||||
|
LDFLAGS+=-L/usr/X11R6/lib
|
||||||
|
CFLAGS+=-I/usr/X11R6/include
|
||||||
|
.elif ${UNAME_S} == "NetBSD"
|
||||||
|
LDFLAGS+=-L/usr/X11R7/lib -L/usr/pkg/lib
|
||||||
|
CFLAGS+=-I/usr/X11R7/include -I/usr/pkg/include
|
||||||
|
.endif
|
||||||
|
|
||||||
|
all:
|
||||||
|
${CC} ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS} ${LIBS}
|
||||||
|
strip ${NAME}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ${NAME}
|
||||||
|
|
||||||
|
dist:
|
||||||
|
mkdir -p ${NAME}-${VERSION} release/src
|
||||||
|
cp -R LICENSE.txt Makefile *.md ${NAME}.desktop ${NAME}.1 *.c ${NAME}-${VERSION}
|
||||||
|
tar zcfv release/src/${NAME}-${VERSION}.tar.gz ${NAME}-${VERSION}
|
||||||
|
rm -rf ${NAME}-${VERSION}
|
||||||
|
|
||||||
|
release-openbsd:
|
||||||
|
mkdir -p release/bin
|
||||||
|
${CC} ${CFLAGS} -o release/bin/${NAME}-${VERSION}-openbsd-${UNAME_M} ${FILES}\
|
||||||
|
${LDFLAGS} -static ${LIBS} -lc -lm -liconv -lsndio -lsamplerate -lX11\
|
||||||
|
-lxcb -lXext -lXcursor -lXrender -lXfixes -lXi -lXrandr -lXss -lusbhid -lpthread\
|
||||||
|
-ljxl -ljxl_cms -llcms2 -lhwy -lc++ -lc++abi -lbrotlidec\
|
||||||
|
-lbrotlicommon -lbrotlienc -lyuv -ltiff -lz -ljpeg -llzma -lzstd -lavif\
|
||||||
|
-ldav1d -laom -lsharpyuv -lwebpdemux -lwebp -lnghttp3 -lngtcp2_crypto_quictls\
|
||||||
|
-lngtcp2 -lssl -lcrypto -lnghttp2 -lXau -lXdmcp
|
||||||
|
strip release/bin/${NAME}-${VERSION}-openbsd-${UNAME_M}
|
||||||
|
|
||||||
|
release-netbsd:
|
||||||
|
mkdir -p release/bin
|
||||||
|
${CC} ${CFLAGS} -o release/bin/${NAME}-${VERSION}-netbsd-${UNAME_M} ${FILES}\
|
||||||
|
${LDFLAGS} -static ${LIBS} -lc -lm -lossaudio -lX11 -lxcb -lXau -lXdmcp -lgcc\
|
||||||
|
-lXext -lXcursor -lXrender -lXi -lXfixes -lXrandr -lXss -ldrm -lpci -lgbm -lglapi\
|
||||||
|
-lstdc++ -lexpat -lusbhid -lusb-1.0 -lpthread -lnghttp2 -lidn2 -lunistring\
|
||||||
|
-lintl -lgssapi -lkrb5 -lhx509 -lssl -lcrypto -lcrypt -lasn1 -lcom_err -lroken\
|
||||||
|
-lutil -lwind -lheimbase -lheimntlm -lz
|
||||||
|
strip release/bin/${NAME}-${VERSION}-netbsd-${UNAME_M}
|
||||||
|
|
||||||
|
install:
|
||||||
|
mkdir -p ${DESTDIR}${PREFIX}/bin\
|
||||||
|
${DESTDIR}${MANPREFIX}/man1\
|
||||||
|
${DESTDIR}${PREFIX}/share/applications
|
||||||
|
cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
|
||||||
|
sed "s/VERSION/${VERSION}/g" < ${NAME}.1 > ${DESTDIR}${MANPREFIX}/man1/${NAME}.1
|
||||||
|
cp -f ${NAME}.desktop ${DESTDIR}${PREFIX}/share/applications
|
||||||
|
chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -f ${DESTDIR}${PREFIX}/share/applications/${NAME}.desktop
|
||||||
|
rm -f ${DESTDIR}${PREFIX}/man1/${NAME}.1
|
||||||
|
rm -f ${DESTDIR}${PREFIX}/bin/${NAME}
|
||||||
|
|
||||||
|
.PHONY: all clean install uninstall
|
||||||
55
README.md
Normal file
55
README.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# mivfx - minimalist image view for x
|
||||||
|
ミニマリストな画像ビューアー
|
||||||
|
|
||||||
|
# インストールする方法
|
||||||
|
|
||||||
|
## OpenBSD
|
||||||
|
```sh
|
||||||
|
doas pkg_add sdl2 sdl2_image curl
|
||||||
|
make
|
||||||
|
doas make install
|
||||||
|
```
|
||||||
|
|
||||||
|
## FreeBSD
|
||||||
|
```sh
|
||||||
|
doas pkg install sdl2 sdl2_image curl
|
||||||
|
make
|
||||||
|
doas make install
|
||||||
|
```
|
||||||
|
|
||||||
|
## NetBSD
|
||||||
|
```sh
|
||||||
|
doas pkgin install SDL2-2.28.5 SDL2_image curl
|
||||||
|
make
|
||||||
|
doas make install
|
||||||
|
```
|
||||||
|
|
||||||
|
## CRUX
|
||||||
|
```sh
|
||||||
|
doas prt-get depinst libsdl2 sdl2_image curl bmake
|
||||||
|
bmake
|
||||||
|
doas bmake install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Void Linux
|
||||||
|
```sh
|
||||||
|
doas xbps-install -S SDL2 SDL2_image curl bmake
|
||||||
|
bmake
|
||||||
|
doas bmake install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Artix Linux
|
||||||
|
```sh
|
||||||
|
doas pacman -S sdl2 sdl2_image curl bmake
|
||||||
|
bmake
|
||||||
|
doas bmake install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Devuan GNU/Linux
|
||||||
|
```sh
|
||||||
|
doas apt install libsdl2-dev libsdl2-image-dev libcurl4 bmake
|
||||||
|
bmake
|
||||||
|
doas bmake install
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
456
main.c
Normal file
456
main.c
Normal file
@@ -0,0 +1,456 @@
|
|||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define DELAY_MS 50
|
||||||
|
|
||||||
|
SDL_Window *window = NULL;
|
||||||
|
SDL_Renderer *renderer = NULL;
|
||||||
|
SDL_Texture *texture = NULL;
|
||||||
|
bool quit = false;
|
||||||
|
bool hasdownloaded = false; // DDoSを避ける為
|
||||||
|
float aspectRatio;
|
||||||
|
int imgX = 10;
|
||||||
|
int imgY = 10;
|
||||||
|
int imgWidth;
|
||||||
|
int imgHeight;
|
||||||
|
int screenWidth;
|
||||||
|
int screenHeight;
|
||||||
|
int init = 0;
|
||||||
|
char *imgfilename;
|
||||||
|
char *imgurl;
|
||||||
|
SDL_Rect renderQuad;
|
||||||
|
float newWidth;
|
||||||
|
float newHeight;
|
||||||
|
|
||||||
|
// マウス
|
||||||
|
int mouseX = 10;
|
||||||
|
int mouseY = 10;
|
||||||
|
int drag = 0;
|
||||||
|
|
||||||
|
// ズーム
|
||||||
|
float zoom = 1.0f;
|
||||||
|
|
||||||
|
// 回転
|
||||||
|
float angle = 0.0f;
|
||||||
|
|
||||||
|
// 反転
|
||||||
|
bool flippedH = false;
|
||||||
|
bool flippedV = false;
|
||||||
|
|
||||||
|
const char *sofname = "mivfx";
|
||||||
|
const char *version = "0.6.0";
|
||||||
|
|
||||||
|
bool dlfile(const char *url, const char *filename) {
|
||||||
|
CURL *curl = curl_easy_init();
|
||||||
|
if (!curl) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *file = fopen(filename, "wb");
|
||||||
|
if (!file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
|
// Clownflareは面倒くさいわね・・・
|
||||||
|
curl_easy_setopt(
|
||||||
|
curl,
|
||||||
|
CURLOPT_USERAGENT,
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; rv:102.0) Gecko/20100101 Firefox/102.0"
|
||||||
|
);
|
||||||
|
// Pixivも結構面倒くさい
|
||||||
|
if (
|
||||||
|
strstr("s.pximg.net", url) == 0 ||
|
||||||
|
strstr("i.pximg.net", url) == 0
|
||||||
|
) {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_REFERER, "https://www.pixiv.net/");
|
||||||
|
}
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
|
||||||
|
CURLcode res = curl_easy_perform(curl);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
if (res != CURLE_OK) {
|
||||||
|
remove(filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *fromurl(char *imgfile, char *dir) {
|
||||||
|
char s[512], *p, *tokens[128];
|
||||||
|
char *last;
|
||||||
|
int i = 0;
|
||||||
|
imgurl = imgfile;
|
||||||
|
|
||||||
|
snprintf(s, sizeof(s), "%s", imgfile);
|
||||||
|
|
||||||
|
for (
|
||||||
|
(p = strtok_r(s, "/", &last));
|
||||||
|
p;
|
||||||
|
(p = strtok_r(NULL, "/", &last))
|
||||||
|
) {
|
||||||
|
if (i < 127) tokens[i++] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens[i] = NULL;
|
||||||
|
imgfilename = tokens[i - 1];
|
||||||
|
|
||||||
|
char *res;
|
||||||
|
|
||||||
|
res = (char *)malloc(1024);
|
||||||
|
if (res == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(res, 1024, "%s/%s", dir, imgfilename);
|
||||||
|
if (!dlfile(imgfile, res)) {
|
||||||
|
printf("画像をダウンロードに失敗。URL: %s\n", imgfile);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderCopy(SDL_Rect renderQuad) {
|
||||||
|
SDL_RenderCopyEx(
|
||||||
|
renderer,
|
||||||
|
texture,
|
||||||
|
NULL,
|
||||||
|
&renderQuad,
|
||||||
|
angle,
|
||||||
|
NULL,
|
||||||
|
flippedV ? SDL_FLIP_VERTICAL : (flippedH ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rotateWindow(int w, int h) {
|
||||||
|
if (angle >= 360.0f) angle = 0.0f;
|
||||||
|
else if (angle <= -360.0f) angle = 0.0f;
|
||||||
|
else if (angle == 270.0f) angle = -90.0f;
|
||||||
|
else if (angle == -180.0f) angle = 180.0f;
|
||||||
|
|
||||||
|
imgWidth = h;
|
||||||
|
imgHeight = w;
|
||||||
|
aspectRatio = (float)imgWidth / imgHeight;
|
||||||
|
SDL_Rect renderQuad = { imgX, imgY, imgWidth, imgHeight };
|
||||||
|
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
SDL_SetWindowSize(window, imgWidth + (imgX * 2), imgHeight + (imgY * 2));
|
||||||
|
RenderCopy(renderQuad);
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void windowevent(SDL_Event e) {
|
||||||
|
int windowWidth, windowHeight;
|
||||||
|
SDL_GetWindowSize(window, &windowWidth, &windowHeight);
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||||
|
|
||||||
|
if (e.type == SDL_QUIT) {
|
||||||
|
quit = true;
|
||||||
|
} else if (e.type == SDL_KEYDOWN) {
|
||||||
|
if (e.key.keysym.sym == SDLK_q) {
|
||||||
|
quit = true;
|
||||||
|
} else if (e.key.keysym.sym == SDLK_e) {
|
||||||
|
// GIFアニメーションの停止・続き、0.7.0から追加する予定
|
||||||
|
} else if (e.key.keysym.sym == SDLK_r) {
|
||||||
|
angle -= 90.0f;
|
||||||
|
rotateWindow(imgWidth, imgHeight);
|
||||||
|
} else if (e.key.keysym.sym == SDLK_t) {
|
||||||
|
angle += 90.0f;
|
||||||
|
rotateWindow(imgWidth, imgHeight);
|
||||||
|
} else if (e.key.keysym.sym == SDLK_y) {
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
SDL_Rect renderQuad = { imgX, imgY, imgWidth, imgHeight };
|
||||||
|
|
||||||
|
SDL_SetWindowSize(window, imgWidth + (imgX * 2), imgHeight + (imgY * 2));
|
||||||
|
RenderCopy(renderQuad);
|
||||||
|
flippedV = !flippedV;
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
} else if (e.key.keysym.sym == SDLK_u) {
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
SDL_Rect renderQuad = { imgX, imgY, imgWidth, imgHeight };
|
||||||
|
|
||||||
|
SDL_SetWindowSize(window, imgWidth + (imgX * 2), imgHeight + (imgY * 2));
|
||||||
|
RenderCopy(renderQuad);
|
||||||
|
flippedH = !flippedH;
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
} else if (e.key.keysym.sym == SDLK_o) {
|
||||||
|
bool isurl = strncmp(imgurl, "http://", 7) == 0 ||
|
||||||
|
strncmp(imgurl, "https://", 8) == 0;
|
||||||
|
if (isurl && !hasdownloaded) {
|
||||||
|
char path[1024];
|
||||||
|
getcwd(path, 1024);
|
||||||
|
if (fromurl(imgurl, path) != NULL) puts("ダウンロード済み");
|
||||||
|
hasdownloaded = true;
|
||||||
|
}
|
||||||
|
} else if (e.key.keysym.sym == SDLK_p) {
|
||||||
|
// 画像をrsync|sftp|http postで使って共有する、0.7.0から追加する予定
|
||||||
|
}
|
||||||
|
} else if (e.type == SDL_MOUSEBUTTONDOWN) {
|
||||||
|
if (e.button.button == SDL_BUTTON_LEFT) {
|
||||||
|
drag = 1;
|
||||||
|
SDL_GetMouseState(&mouseX, &mouseY);
|
||||||
|
}
|
||||||
|
} else if (e.type == SDL_MOUSEBUTTONUP) {
|
||||||
|
if (e.button.button == SDL_BUTTON_LEFT) {
|
||||||
|
drag = 0;
|
||||||
|
}
|
||||||
|
} else if (e.type == SDL_MOUSEMOTION) {
|
||||||
|
if (drag) {
|
||||||
|
int newMouseX, newMouseY;
|
||||||
|
SDL_GetMouseState(&newMouseX, &newMouseY);
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
|
if (newWidth != 0.0f) imgWidth = (newWidth);
|
||||||
|
if (newHeight != 0.0f) imgHeight = (newHeight);
|
||||||
|
imgX = newMouseX - (imgWidth / 2);
|
||||||
|
imgY = newMouseY - (imgHeight / 2);
|
||||||
|
SDL_Rect renderQuad = { imgX, imgY, imgWidth, imgHeight };
|
||||||
|
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
RenderCopy(renderQuad);
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
}
|
||||||
|
} else if (e.type == SDL_MOUSEWHEEL) {
|
||||||
|
int curWidth = imgWidth;
|
||||||
|
int curHeight = imgHeight;
|
||||||
|
|
||||||
|
float zoomSpeed = 0.1f;
|
||||||
|
if (e.wheel.y > 0) {
|
||||||
|
zoom += zoomSpeed;
|
||||||
|
} else if (e.wheel.y < 0) {
|
||||||
|
zoom -= zoomSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zoom < 0.1f) {
|
||||||
|
zoom = 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 画像のサイズが変わった場合
|
||||||
|
newWidth = (float)imgWidth * zoom;
|
||||||
|
newHeight = (float)imgHeight * zoom;
|
||||||
|
float minLimit = 50.0f;
|
||||||
|
|
||||||
|
// 画像は50x50以下じゃ駄目
|
||||||
|
if (newWidth < minLimit) {
|
||||||
|
newWidth = minLimit;
|
||||||
|
newHeight = curHeight;
|
||||||
|
} else if (newHeight < minLimit) {
|
||||||
|
printf("%d\n", curWidth);
|
||||||
|
newWidth = curWidth;
|
||||||
|
newHeight = minLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// テキスチャーのレンダーリングサイズの設定
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
|
imgWidth = (int)newWidth;
|
||||||
|
imgHeight = (int)newHeight;
|
||||||
|
imgX = (windowWidth - imgWidth) / 2;
|
||||||
|
imgY = (windowHeight - imgHeight) / 2;
|
||||||
|
SDL_Rect renderQuad = { imgX, imgY, imgWidth, imgHeight };
|
||||||
|
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
RenderCopy(renderQuad);
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
} else if (e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
|
// ウィンドウのサイズが変わった場合
|
||||||
|
int newWidth = e.window.data1;
|
||||||
|
int newHeight = e.window.data2;
|
||||||
|
|
||||||
|
// 縦横比を変わらずに新しい大きさの算数
|
||||||
|
float newAspectRatio = (float)newWidth / newHeight;
|
||||||
|
int scaledWidth, scaledHeight;
|
||||||
|
|
||||||
|
if (newAspectRatio != aspectRatio) {
|
||||||
|
// 画像よりウィンドウの方が広い場合
|
||||||
|
scaledHeight = angle == 90 || angle == -90 ? newWidth : newHeight;
|
||||||
|
scaledHeight = newHeight;
|
||||||
|
scaledWidth = (int)(scaledHeight * aspectRatio);
|
||||||
|
} else {
|
||||||
|
// 画像よりウィンドウの方が高い場合
|
||||||
|
scaledWidth = angle == 90 || angle == -90 ? newHeight : newWidth;
|
||||||
|
scaledHeight = angle == 90 || angle == -90 ? newWidth : newHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 画像は50x50以下じゃ駄目
|
||||||
|
int minWidth = 50;
|
||||||
|
int minHeight = 50;
|
||||||
|
if (scaledWidth < minWidth) scaledWidth = minWidth;
|
||||||
|
if (scaledHeight < minHeight) scaledHeight = minHeight;
|
||||||
|
|
||||||
|
// 大きすぎの場合もふざけんな
|
||||||
|
if (scaledWidth >= (screenWidth-20)) scaledWidth = screenWidth-20;
|
||||||
|
if (scaledHeight >= (screenHeight-20)) scaledHeight = screenHeight-20;
|
||||||
|
|
||||||
|
imgWidth = scaledWidth;
|
||||||
|
imgHeight = scaledHeight;
|
||||||
|
|
||||||
|
// テキスチャーのレンダーリングサイズの設定
|
||||||
|
SDL_Rect renderQuad = { imgX, imgY, imgWidth, imgHeight };
|
||||||
|
|
||||||
|
SDL_SetWindowSize(window, imgWidth + (imgX * 2), imgHeight + (imgY * 2));
|
||||||
|
RenderCopy(renderQuad);
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
} else if (e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_MOVED) {
|
||||||
|
SDL_Rect renderQuad = { imgX, imgY, imgWidth, imgHeight };
|
||||||
|
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
RenderCopy(renderQuad);
|
||||||
|
SDL_SetWindowSize(window, imgWidth + (imgX * 2), imgHeight + (imgY * 2));
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
} else if (e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_EXPOSED) {
|
||||||
|
if (init == 1) return;
|
||||||
|
init = 1;
|
||||||
|
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
|
if (
|
||||||
|
(imgWidth >= (screenWidth - 100)) &&
|
||||||
|
imgHeight >= (screenHeight - 100)
|
||||||
|
) {
|
||||||
|
imgWidth = (screenWidth - 100);
|
||||||
|
imgHeight = (screenHeight - 100);
|
||||||
|
} else if (
|
||||||
|
(imgWidth >= (screenWidth - 100)) &&
|
||||||
|
imgHeight <= (screenHeight - 100)
|
||||||
|
) {
|
||||||
|
imgWidth = (screenWidth - 100);
|
||||||
|
imgHeight = (imgWidth * aspectRatio);
|
||||||
|
} else if (
|
||||||
|
(imgWidth <= (screenWidth - 100)) &&
|
||||||
|
imgHeight >= (screenHeight - 100)
|
||||||
|
) {
|
||||||
|
imgHeight = (screenHeight - 100);
|
||||||
|
imgWidth = (imgHeight * aspectRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Rect renderQuad = { imgX, imgY, imgWidth, imgHeight };
|
||||||
|
|
||||||
|
RenderCopy(renderQuad);
|
||||||
|
SDL_SetWindowSize(window, imgWidth + (imgX * 2), imgHeight + (imgY * 2));
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage() {
|
||||||
|
printf("%s-%s\nusage: %s [file or url]\n", sofname, version, sofname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc < 2) {
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SDL2とSDL2_imageの初期設定
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||||
|
printf("SDLを初期設定出来なかった:%s\n", SDL_GetError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)) {
|
||||||
|
printf("SDL_imageを初期設定出来なかった:%s\n", SDL_GetError());
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *imgfile = argv[1];
|
||||||
|
|
||||||
|
// URLの場合、仮にダウンロードして
|
||||||
|
bool isurl = strncmp(imgfile, "http://", 7) == 0 ||
|
||||||
|
strncmp(imgfile, "https://", 8) == 0;
|
||||||
|
imgfile = isurl ? fromurl(argv[1], "/tmp") : argv[1];
|
||||||
|
if (imgfile == NULL) {
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 画像の読込
|
||||||
|
SDL_Surface *imgsurface = IMG_Load(imgfile);
|
||||||
|
if (imgsurface == NULL) {
|
||||||
|
printf("画像の読込に失敗:%s\n", IMG_GetError());
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 画像の大きさの受取
|
||||||
|
imgWidth = imgsurface->w;
|
||||||
|
imgHeight = imgsurface->h;
|
||||||
|
aspectRatio = (float)imgWidth / imgHeight;
|
||||||
|
|
||||||
|
// 画面の大きさの受取
|
||||||
|
SDL_DisplayMode DM;
|
||||||
|
SDL_GetCurrentDisplayMode(0, &DM);
|
||||||
|
screenWidth = DM.w;
|
||||||
|
screenHeight = DM.h;
|
||||||
|
|
||||||
|
// ウィンドウの大きさの設定
|
||||||
|
int windowWidth = (imgWidth >= (screenWidth-20)) ? screenWidth-20 : imgWidth;
|
||||||
|
int windowHeight = (imgHeight >= (screenHeight-20)) ? screenHeight-20 : imgHeight;
|
||||||
|
|
||||||
|
// ウィンドウの作成
|
||||||
|
SDL_SetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT, "1");
|
||||||
|
window = SDL_CreateWindow(
|
||||||
|
"mivfx",
|
||||||
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
|
windowWidth,
|
||||||
|
windowHeight,
|
||||||
|
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
|
||||||
|
);
|
||||||
|
if (window == NULL) {
|
||||||
|
printf("ウィンドウの作成に失敗:%s\n", SDL_GetError());
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// レンダーの作成
|
||||||
|
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||||
|
if (renderer == NULL) {
|
||||||
|
printf("レンダーの作成に失敗:%s\n", SDL_GetError());
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture = SDL_CreateTextureFromSurface(renderer, imgsurface);
|
||||||
|
SDL_FreeSurface(imgsurface);
|
||||||
|
if (texture == NULL) {
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// メインループ
|
||||||
|
SDL_Event e;
|
||||||
|
while (!quit) {
|
||||||
|
// イベント
|
||||||
|
while (SDL_PollEvent(&e) != 0) {
|
||||||
|
windowevent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 休ませる
|
||||||
|
SDL_Delay(DELAY_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 掃除
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
IMG_Quit();
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
48
mivfx.1
Normal file
48
mivfx.1
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
.TH MIVFX 1 VERSION
|
||||||
|
.SH NAME
|
||||||
|
mivfx - minimalist image view for x
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B mivfx
|
||||||
|
[\fI\,file\fR|\fI\,url\fR]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.PP
|
||||||
|
ミニマリストな画像ビューアーです。
|
||||||
|
.SH KEYBINDING
|
||||||
|
.TP
|
||||||
|
\fB\,Q\fR
|
||||||
|
終了
|
||||||
|
.TP
|
||||||
|
\fB\,R\fR
|
||||||
|
画像を-90°で回転する
|
||||||
|
.TP
|
||||||
|
\fB\,T\fR
|
||||||
|
画像を+90°で回転する
|
||||||
|
.TP
|
||||||
|
\fB\,Y\fR
|
||||||
|
縦側に反転する
|
||||||
|
.TP
|
||||||
|
\fB\,U\fR
|
||||||
|
横側に反転する
|
||||||
|
.TP
|
||||||
|
\fB\,マウスでスクロール\fR
|
||||||
|
ズームインやズームアウト
|
||||||
|
.TP
|
||||||
|
\fB\,マウスで移動\fR
|
||||||
|
画像の移動
|
||||||
|
.SH EXAMPLES
|
||||||
|
\&...
|
||||||
|
|
||||||
|
$ mivfx ~/画像/image.png
|
||||||
|
.ED
|
||||||
|
.br
|
||||||
|
ローカルな画像を開く
|
||||||
|
|
||||||
|
\&...
|
||||||
|
|
||||||
|
$ mivfx https://076.moe/image.png
|
||||||
|
.ED
|
||||||
|
.br
|
||||||
|
リモートサーバから画像を開く
|
||||||
|
.SH AUTHORS
|
||||||
|
.PP
|
||||||
|
テクニカル諏訪子
|
||||||
9
mivfx.desktop
Normal file
9
mivfx.desktop
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Name=mivfx
|
||||||
|
GenericName=Image Viewer
|
||||||
|
GenericName[ja]=画像ビューアー
|
||||||
|
Exec=mivfx %F
|
||||||
|
MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;image/x-bmp;image/x-portable-anymap;image/x-portable-bitmap;image/x-portable-graymap;image/x-tga;image/x-xpixmap;image/webp;image/heic;image/svg+xml;application/postscript;image/jp2;image/jxl;image/avif;image/heif;
|
||||||
|
NoDisplay=true
|
||||||
|
Icon=mivfx
|
||||||
Reference in New Issue
Block a user