TODO: GIF対応

このコミットが含まれているのは:
守矢諏訪子 2024-04-07 14:30:42 +09:00
コミット 76f3ee0678
3個のファイルの変更114行の追加21行の削除

ファイルの表示

@ -5,7 +5,7 @@ PREFIX=/usr/local
CC=cc
FILES=main.c
CFLAGS=-Wall -Wextra -g
LIBS=-lSDL2 -lSDL2_image -lcurl
LIBS=-lSDL2 -lSDL2_image -lcurl -lgif
LDFLAGS=-L${PREFIX}/lib
CPPFLAGS=-I${PREFIX}/include

ファイルの表示

@ -5,49 +5,49 @@
## OpenBSD
```sh
doas pkg_add sdl2 sdl2_image curl
doas pkg_add sdl2 sdl2_image curl giflib
make
doas make install
```
## FreeBSD
```sh
doas pkg install sdl2 sdl2_image curl
doas pkg install sdl2 sdl2_image curl giflib
make
doas make install
```
## NetBSD
```sh
doas pkgin install SDL2-2.28.5 SDL2_image curl
doas pkgin install SDL2-2.28.5 SDL2_image curl giflib
make PREFIX=/usr/pkg
doas make install PREFIX=/usr/pkg
```
## CRUX
```sh
doas prt-get depinst libsdl2 sdl2_image curl
doas prt-get depinst libsdl2 sdl2_image curl giflib
make PREFIX=/usr
doas make install PREFIX=/usr
```
## Void Linux
```sh
doas xbps-install -S SDL2 SDL2_image curl
doas xbps-install -S SDL2 SDL2_image curl giflib-devel
make PREFIX=/usr
doas make install PREFIX=/usr
```
## Artix Linux
```sh
doas pacman -S sdl2 sdl2_image curl
doas pacman -S sdl2 sdl2_image curl giflib
make PREFIX=/usr
doas make install PREFIX=/usr
```
## Devuan GNU/Linux
```sh
doas apt install libsdl2-dev libsdl2-image-dev libcurl4
doas apt install libsdl2-dev libsdl2-image-dev libcurl4 giflib-tools
make PREFIX=/usr
doas make install PREFIX=/usr
```

119
main.c
ファイルの表示

@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <curl/curl.h>
#include <gif_lib.h>
#define DELAY_MS 50
@ -10,6 +11,7 @@ SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Texture* texture = NULL;
bool quit = false;
GifFileType* gif = NULL;
bool dlfile(const char* url, const char* filename) {
CURL* curl = curl_easy_init();
@ -35,6 +37,58 @@ bool dlfile(const char* url, const char* filename) {
return true;
}
const char* getmime(const char *filename) {
FILE* file = fopen(filename, "rb");
if (!file) {
fprintf(stderr, "ファイルを開くに失敗: %s\n", filename);
return NULL;
}
char header[4];
fread(header, sizeof(char), 4, file);
fclose(file);
if (header[0] == 'G' && header[1] == 'I' && header[2] == 'F' && header[3] == '8') {
return "image/gif";
}
return "image/png";
}
SDL_Surface* loadgif(const char* filename) {
int error;
gif = DGifOpenFileName(filename, &error);
if (!gif) {
fprintf(stderr, "GIFファイルを開くに失敗: %s\n", filename);
return NULL;
}
error = DGifSlurp(gif);
if (error != GIF_OK) {
fprintf(stderr, "GIFファイルの読込に失敗: %s\n", GifErrorString(error));
DGifCloseFile(gif, &error);
return NULL;
}
SavedImage* frame = &(gif->SavedImages[0]);
SDL_Surface* surface = SDL_CreateRGBSurface(
0,
frame->ImageDesc.Width,
frame->ImageDesc.Height,
24,
0, 0, 0, 0
);
/* SDL_Surface* surface = SDL_CreateRGBSurfaceFrom((void*)frame->RasterBits, */
/* frame->ImageDesc.Width, */
/* frame->ImageDesc.Height, */
/* 8 * sizeof(GifPixelType), */
/* frame->ImageDesc.Width * sizeof(GifPixelType), */
/* 0xFF, 0xFF00, 0xFF0000, 0); */
DGifCloseFile(gif, &error);
return surface;
}
void windowevent(SDL_Event e) {
if (e.type == SDL_QUIT) {
quit = true;
@ -58,7 +112,12 @@ void windowevent(SDL_Event e) {
/* } */
// テキスチャーのれんダーリングサイズの設定
SDL_Rect renderQuad = { (newWidth - scaledWidth) / 2, (newHeight - scaledHeight) / 2, scaledWidth, scaledHeight };
SDL_Rect renderQuad = {
(newWidth - scaledWidth) / 2,
(newHeight - scaledHeight) / 2,
scaledWidth,
scaledHeight
};
SDL_RenderCopy(renderer, texture, NULL, &renderQuad);
} else if (e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_EXPOSED) {
// 再描画が必要な場合
@ -86,8 +145,11 @@ int main(int argc, char* argv[]) {
return 1;
}
if (!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)) {
int imgflag = IMG_INIT_PNG;
if (!(IMG_Init(imgflag) & imgflag)) {
printf("SDL_imageを初期設定出来なかった%s\n", SDL_GetError());
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
@ -109,19 +171,41 @@ int main(int argc, char* argv[]) {
imgfile = tmpname;
}
const char* mimetype = getmime(imgfile);
SDL_Surface* imgsurface = NULL;
IMG_Animation* imganimate = NULL;
// 画像の読込
SDL_Surface* imgsurface = IMG_Load(imgfile);
if (imgsurface == NULL) {
printf("画像の読込に失敗:%s\n", IMG_GetError());
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
if (strcmp(mimetype, "image/gif") == 0) {
imganimate = IMG_LoadAnimation(imgfile);
if (imganimate == NULL) {
printf("画像の読込に失敗:%s\n", IMG_GetError());
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
} else {
imgsurface = IMG_Load(imgfile);
if (imgsurface == NULL) {
printf("画像の読込に失敗:%s\n", IMG_GetError());
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
}
// 画像の大きさの受取
int imgWidth = imgsurface->w;
int imgHeight = imgsurface->h;
int imgWidth = 0;
int imgHeight = 0;
if (strcmp(mimetype, "image/gif") == 0) {
imgWidth = imganimate->w;
imgHeight = imganimate->h;
} else {
imgWidth = imgsurface->w;
imgHeight = imgsurface->h;
}
/* float aspectRatio = (float)imgWidth / imgHeight; */
// 画面の大きさの受取
@ -165,14 +249,18 @@ int main(int argc, char* argv[]) {
return 1;
}
texture = SDL_CreateTextureFromSurface(renderer, imgsurface);
SDL_FreeSurface(imgsurface);
if (strcmp(mimetype, "image/gif") == 0) {
texture = IMG_LoadTexture(renderer, imgfile);
} else {
texture = SDL_CreateTextureFromSurface(renderer, imgsurface);
SDL_FreeSurface(imgsurface);
if (texture == NULL) {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
}
// メインループ
SDL_Event e;
@ -182,6 +270,10 @@ int main(int argc, char* argv[]) {
windowevent(e);
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
// 休ませる
SDL_Delay(DELAY_MS);
}
@ -190,6 +282,7 @@ int main(int argc, char* argv[]) {
if (isurl) {
remove(tmpname);
}
if (strcmp(mimetype, "image/gif") == 0) IMG_FreeAnimation(imganimate);
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);