#include <X11/Xlib.h>
#include <string>
#define STB_IMAGE_IMPLEMENTATION
#include "../dep/stb_image.h"
#include <stdexcept>
#include "image.hh"
namespace uw {
Image::Image(Screen &screen, const std::string imgPath) : uwScreen{ screen } {
if (imgPath.empty()) throw std::runtime_error("画像パスが空です。");
data = stbi_load(imgPath.c_str(), &width, &height, &chan, 4);
if (!data) throw std::runtime_error("画像の読み込みに失敗: " + imgPath);
imageExtent.width = width;
imageExtent.height = height;
imagePath = imgPath;
v = DefaultVisual(screen.getDisplay(), screen.getScreen());
createDepth();
createPixmap();
createImage();
createGC();
}
Image::~Image() {
if (gc) XFreeGC(uwScreen.getDisplay(), gc);
if (pm) XFreePixmap(uwScreen.getDisplay(), pm);
if (image) XFree(image);
if (data) stbi_image_free(data);
}
void Image::createDepth() {
depth = DefaultDepth(uwScreen.getDisplay(), uwScreen.getScreen());
if (depth != 24 && depth != 32) {
throw std::runtime_error(
"「" + std::to_string(depth) + "」の様な視覚の深さは未対応です。");
}
imageExtent.depth = depth;
}
void Image::createPixmap() {
pm = XCreatePixmap(uwScreen.getDisplay(), uwScreen.getWindow(), width, height,
depth);
}
void Image::createImage() {
if (depth == 24) {
std::vector<uchar> cd(data, data + (width * height * 4));
cdata = cd;
for (int i = 0; i < width * height; i++) {
cdata[i * 4 + 0] = data[i * 4 + 2];
cdata[i * 4 + 1] = data[i * 4 + 1];
cdata[i * 4 + 2] = data[i * 4 + 0];
cdata[i * 4 + 3] = data[i * 4 + 3];
}
image = XCreateImage(uwScreen.getDisplay(), v, depth, ZPixmap, 0,
(char *)cdata.data(), width, height, 32, 0);
} else {
image = XCreateImage(uwScreen.getDisplay(), v, depth, ZPixmap, 0,
(char *)data, width, height, 32, 0);
}
if (!image) throw std::runtime_error("XImageの作成に失敗。");
}
void Image::createGC() {
gc = XCreateGC(uwScreen.getDisplay(), pm, 0, nullptr);
if (!gc) throw std::runtime_error("GCの作成に失敗。");
}
}