遗漏的部分

This commit is contained in:
qing committed 2026-08-02 21:21:03 +08:00
1 parent 84fb370da8
commit 0493383ee8
63 files changed
+28237 -4

No files matched your search

+21
View File
@@ -0,0 +1,21 @@
/*
* Area是某个形状上的一个区域,它没有自己的帧缓冲区
*
*
*/
#pragma once
#include "Drawable.h"
namespace qing {
class Area: public Drawable {
public:
/* Phase Plotting Method 相图法 */
Area(Drawable *d, int w, int h, int x, int y, int rotate, int fontsize);
Color _get(int x, int y) override; /* 实现接口 */
void _p(int x, int y, Color &clr) override;
virtual void flush(Drawable *n, bool border = false) override;
virtual void move(int x, int y);
protected:
Drawable *d; /* 持有的绘制主体 */
};
}
+72
View File
@@ -0,0 +1,72 @@
#pragma once
#include <iostream>
#include <map>
namespace qing {
/*
* C++ 的命令行
*/
class Arguments {
public:
Arguments(int argc, char **argv) {
for (int i=1; i<argc; ++i) {
std::string item = argv[i];
if (item.length() > 1 && item[0] == '-' && item[1] != '-') {
for (unsigned long j=1; j<item.length(); ++j) {
if (item.length() == 2 && i < argc-1 && argv[i+1][0] != '-') {
std::string args = "";
while (i < argc-1 && argv[i+1][0] != '-') {
args += (args == "") ? "" : " ";
args += std::string(argv[++i]);
}
mc.insert(std::pair(item[j], args));
std::cout << item[j] << "=" << args << std::endl;
} else {
mc.insert(std::pair(item[j], ""));
std::cout << item[j] << std::endl;
}
}
} else if (item.length() > 2 && item[0] == '-' && item[1] == '-' && item[2] != '-') {
std::string arg = get_long_param_key(item);
size_t pos =arg.find('=');
if (pos == (long unsigned int)-1) {
std::cout << arg << std::endl;
m.insert(std::pair<std::string, std::string>(arg, ""));
} else {
std::string k = arg.substr(0, pos);
std::string v = arg.substr(pos+1, arg.length()-pos-1);
std::cout << k << "=" << v << std::endl;
m.insert(std::pair<std::string, std::string>(k, v));
}
} else {
throw WrongArgument(item);
}
}
}
std::map<std::string, std::string> &get_m() {
return m;
}
std::map<char, std::string> &get_mc() {
return mc;
}
class WrongArgument: std::runtime_error { /* 错的参数 */
public:
WrongArgument(std::string key): std::runtime_error(key) {}
};
private:
std::map<std::string, std::string> m;
std::map<char, std::string> mc;
std::string get_long_param_key(std::string &s) {
return s.substr(2, s.length() -2);
}
};
}
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include "lci/Shape.h"
#include "lci/字体绘制器.h"
namespace qing {
class CharShape: public Shape {
public:
CharShape(int w, int h, int x, int y, wchar_t wc)
: Shape(w, h, x, y), wc(wc), 绘制(w, h) {}
virtual void Draw(Drawable &d, Color clr) override{
int w = getw();
int h = geth();
int x = getx();
int y = gety();
绘制.drawvfont(&d, x, y, wc, clr);
}
private:
wchar_t wc;
字体绘制器 绘制;
};
}
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include "Area.h"
#include "InputBox.h"
#include <memory>
#include <mutex>
namespace qing {
/*
* CmdArea(命令区域)是一种特殊的Area区域
*
* 基层绘制方法我们已经在Area中实现了
*/
class CmdArea: public Area {
public:
CmdArea(Drawable *d, int w, int h, int x, int y, int rotate =0, int fontsize=18, bool hasBox = false);
void Input(char c);
void ClearInput();
virtual void print(char *utf8, int d=0); /* FIXME: d不知道是什么*/
void update_input();
void delete_input();
void clearBox();
std::string get_input_and_clear();
private:
int x_f=0, y_f=0;
std::unique_ptr<InputBox> area;
std::mutex lock;
std::string input = "";
void handle_ansi_code(char *buffer);
bool hasBox;
};
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
namespace qing {
/* 32位色彩和16位色彩 */
class Color{
public:
unsigned char r=0,g=0,b=0;
Color(unsigned char r=0, unsigned char g=0, unsigned char b=0) {
this->r=r;
this->g=g;
this->b=b;
}
};
extern const Color black;
extern const Color white;
extern const Color green;
extern const Color blue;
extern const Color red;
/* FIXME: 完成这个类定义 */
class Color16 {
public:
};
}
+63
View File
@@ -0,0 +1,63 @@
#pragma once
#include <iostream>
#include <stdexcept>
#include <thread>
#include "fsm.h"
#include "ThreadInterface.h"
/*
@qing:包含一个简易的多线程控制机制。
需要共享内存的变量和函数声明为全局变量(通常需要带锁),
线程中单独使用的变量和函数声明到属于它的命名空间中。
每个线程的主函数包括了对其的流程控制代码。
stop,setup,loop,clean函数中填入每个状态下的执行代码。
其中需要用到的函数,又实现在后边。
*/
namespace qing {
namespace lci{
//线程的主函数
//-----------------------------------------------------------
/*通常情况下,线程的主函数。*/
//前向声明脚本类型
class CommonThread: public lci::Fsm, ThreadInterface {
//一个持有资源线程的状态机类型
public:
//构造函数.
//没有必要输入打印机、脚本、线程的名字,放到全局变量
CommonThread(std::string name);
//暂时删除复制构造函数
CommonThread(CommonThread&) = delete;
//如果把析构函数放在这里,将会导致纯虚函数错误
virtual ~CommonThread();
//对线程名字的设置
void SetLabel(std::string name);
//对线程名字的获取
std::string& GetLabel();
//-----------------------------------------------------------
//等待线程启动完毕
//线程启动失败返回失败。线程启动成功或者现程结束返回成功。
//
//这个函数在某些情况下有可能会一直等待,直到循环结束
bool WaitStart(unsigned long n);
void WaitClose();
virtual void StopEvent() override;
virtual void WakeEvent() override;
virtual void LoopEvent() override;
virtual void ClearEvent() override;
void thread_main();
private:
//线程的名字
std::string label;
//用来存放该子线程的标识符。
std::thread *thread = NULL;
};
}
}
+89
View File
@@ -0,0 +1,89 @@
/*
* 这个是个抽象类,子类实现抽象的内部接口后
*
* 可以调用它已经写好的绘制方法。
*/
#pragma once
#include "Rectangle.h"
#include "Color.h"
#include <iostream>
/* 用于文字的绘制
* FIXME: 使用类封装 */
extern unsigned char ttu[];
extern int ttunumber;
extern unsigned char zzhi[];
extern int zzhinumber;
namespace qing {
class Drawable {
public:
/* 表示旋转方向 */
enum class Rotate: char {
R_0 = 0,
R_90 = 1,
R_180 = 2,
R_270 = 3
};
/* 非法的旋转模式 */
class InvalidRotateMode: std::runtime_error {
public:
InvalidRotateMode(): std::runtime_error("Invalid rotate mode.") {}
};
/*====== attr 属性区(访问器) ======*/
Drawable(int w, int h, int x, int y, int rotate, int fontsize);
virtual Rectangle get_size();
virtual Rectangle get_pos();
virtual void set_pos(Rectangle rect);
virtual Color get_color(int x, int y);
virtual void set_color(Color &color);
void FontSize(int fontsize);
int FontSize_get();
virtual Color& getFontsColor();
/*------ basic 基本 ------
* 这些类需要由子类分别进行实现,但是子类不直接调用,
* 而是由抽象基类中实现的方法调用 */
virtual Color _get(int x, int y) = 0; /* 获取像素点像素 */
virtual void _p(int x, int y, Color &clr) = 0; /* 绘制像素点像素 */
//virtual void _up(int x, int y, int w, int h, int level) = 0; /* FIXME: 不使用屏幕移动函数 */
//virtual void _down(int x, int y, int w, int h, int level) = 0;
//virtual void _left(int x, int y, int w, int h, int level) = 0;
//virtual void _right(int x, int y, int w, int h, int level) = 0;
//virtual void _clear(int x, int y, int w, int h) = 0; /* FIXME: 实现该方法 */
/*====== drawer 绘制 ======
* 提供给子类和外部的绘制方法 */
virtual void point(int x, int y, Color &clr);
virtual void line(int x1, int y1, int x2, int y2, Color &clr);
virtual void rectangle(int x, int y, int w, int h, Color &clr);
virtual void rectangle_fill(int x, int y, int w, int h, Color &clr);
virtual void flush(Drawable *n, bool border) = 0;
//virtual void clear(); /* 对于区域来说,清理可能较为复杂 */
/*------ printer 打印 ------
* 打印文字
*
* 只实现了打印文字的基本方法 */
void drawvfont(int x, int y, unsigned short z, Color &clr);
/*------ test 测试 ------
* 绘制测试图案 */
virtual void test(); /* 颜色测试 */
protected:
/*------ window ------
* 窗口属性 */
int w, h, x, y, rotate=0;
/*------ fonts lib ------
* 文字库 */
int font_w, font_h;
unsigned short *chss = (unsigned short *)zzhi;
unsigned char *vec = ttu;
int zn;
int vennum;
/* 绘制文字 */
unsigned char *drawvect(int x, int y, unsigned char *vect, int width, int high, Color &clr);
/*------ printer ------*/
Color clr = green;
//Color clr = white;
};
}
+40
View File
@@ -0,0 +1,40 @@
#pragma once
#include "Rectangle.h"
#include "Color.h"
#include "Drawable.h"
#include <iostream>
#include <linux/fb.h>
namespace qing{
/* FIXME: 这个类的绘制点方法可能过于复杂 */
class FrameBuf: public Drawable { /* 帧缓冲区类 */
public:
FrameBuf(const char *path, int rotate, int fontsize);
FrameBuf(const FrameBuf&) = delete; /* 持有fd */
~FrameBuf();
int get_bpp(); /* bits_per_pixel 像素比特 */
virtual Color _get(int x, int y) override;
virtual void _p(int x, int y, Color &color) override;
virtual void flush(Drawable *d, bool border = false) override;
void clear(); /* FIXME: 也许把这个方法加到抽象父类中? */
class UnknowBPP: std::runtime_error { /* 未知标准的像素比特 */
public:
UnknowBPP(): std::runtime_error("Unknow the number of Bits Per Pixel.") {}
};
static const int _HEAD_LEN = 8;
private:
int d = -1;
struct fb_var_screeninfo var_info; /* 可变参数 */
struct fb_fix_screeninfo fix_info; /* 固定参数 */
int x_over = 0; /* 横轴过量 */
int line_jump = 0; /* 行跳 */
char *buf = nullptr; /* 缓冲区指针 */
/* 根据像素比特的不同分情况讨论 */
Color get16(__u32 x, __u32 y);
Color get32(__u32 x, __u32 y);
void p32(__u32 x, __u32 y, Color &color);
void p16(__u32 x, __u32 y, Color &color);
};
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "Area.h"
namespace qing {
class InputBox: public Area { /* 输入框 */
public:
InputBox(Drawable *d, int w, int h, int x, int y, int rotate, int fontsize);
virtual void print(char *utf8, int line);
};
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include <iostream>
#include <string>
#include <map>
#include <linux/input.h>
//#define MAX 64 /* FIXME: 这个是不是没用了 */
namespace qing {
class KeyboardEvent{
public:
KeyboardEvent();
~KeyboardEvent();
struct input_event get(); /* 获取键盘事件 */
class NoEvent: std::runtime_error{ /* 键盘无事件异常 */
public:
NoEvent(std::string s): std::runtime_error(s){}
};
private:
std::map<std::string, int> pool;
static bool is_event_with_number(const char *filename);
static void set_noblocking(int d);
int maxd();
static void print(struct input_event ev);
};
}
+53
View File
@@ -0,0 +1,53 @@
/*
* 控件池区域
*
* 能够容纳别的控件,不需要重写flush()方法
*/
#include <memory>
#include <unordered_map>
#include "lci/Area.h"
#include "lci/Drawable.h"
namespace qing {
class PoolArea: public Area{
public:
PoolArea(Drawable *d, int w, int h, int x, int y, int rotate, int fontsize)
:Area(d, w, h, x, y, rotate, fontsize) {};
void add(const std::string& name, const std::shared_ptr<Area>& item) {
umap.insert({name, item});
}
/* 访问控件 */
std::shared_ptr<Area>& operator[](const std::string& key) {
return umap.at(key);
}
/* 访问控件 - const */
const std::shared_ptr<Area>& operator[](const std::string& key) const {
return umap.at(key);
}
/* 安全访问 - 不抛异常 */
//std::shard_ptr<Area> get(const std::string& key) const {}
/* 检查是否存在 */
bool contains(const std::string& key) const {
return umap.find(key) != umap.end();
}
/* 获取控件数量 */
size_t size() const { return umap.size(); }
/* 迭代器支持 - 范围for循环 */
std::unordered_map<std::string, std::shared_ptr<Area>>::iterator begin() { return umap.begin(); }
std::unordered_map<std::string, std::shared_ptr<Area>>::iterator end() { return umap.end(); }
/* 迭代器支持 - const版本 */
std::unordered_map<std::string, std::shared_ptr<Area>>::const_iterator begin() const { return umap.begin(); }
std::unordered_map<std::string, std::shared_ptr<Area>>::const_iterator end() const { return umap.end(); }
/* FIXME: cbegin/cend 支持 */
private:
std::unordered_map<std::string, std::shared_ptr<Area>> umap;
};
}
+14
View File
@@ -0,0 +1,14 @@
#pragma once
namespace qing{
class Rectangle{ /* 矩形类 */
public:
int w=0; /* width */
int h=0; /* height */
int b=0; /* ? */
Rectangle(int w=0, int h=0, int b=0) {
this->w=w;
this->h=h;
this->b=b;
}
};
}
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include "lci/Drawable.h"
#include "lci/Color.h"
namespace qing {
/* 【形状】
* 抽象基类 */
class Shape {
public:
Shape(int w, int h, int x, int y)
: w(w), h(h), x(x), y(y) {}
virtual void Draw(Drawable &d, Color clr) = 0;
int getw() {
return w;
}
void setw(int w) {
this->w = w;
}
int geth() {
return h;
}
void seth(int h) {
this->h = h;
}
int getx() {
return x;
}
void setx(int x) {
this->x = x;
}
int gety() {
return y;
}
void sety(int y) {
this->y = y;
}
private:
int w, h;
int x, y;
};
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
/*
* 形状区域
*/
#include "lci/Area.h"
#include "lci/Shape.h"
#include "vector"
#include "memory"
namespace qing {
class ShapeArea: public Area {
public:
ShapeArea(Drawable *d, int w, int h, int x, int y, int rotate, int fontsize)
: Area(d, w, h, x, y, rotate, fontsize){}
size_t size() const { return list.size(); }
void add(const std::shared_ptr<Shape>& item) {
list.push_back(item);
}
Shape& operator[](const size_t idx) {
return *(list[idx]);
}
const Shape& operator[](const size_t idx) const {
return *(list[idx]);
}
std::vector<std::shared_ptr<Shape>>::iterator begin() { return list.begin(); }
std::vector<std::shared_ptr<Shape>>::iterator end() { return list.end(); }
std::vector<std::shared_ptr<Shape>>::const_iterator begin() const { return list.begin(); }
std::vector<std::shared_ptr<Shape>>::const_iterator end() const { return list.end(); }
private:
std::vector<std::shared_ptr<Shape>> list;
};
}
+46
View File
@@ -0,0 +1,46 @@
#pragma once
#include <iostream>
#include <cstring>
#include <fcntl.h>
#include <unistd.h>
namespace qing {
class Term {
public:
/* 需要输入当前的控制台号(源头tty) */
Term(int target_tty, int origin_tty) {
this->origin_tty = origin_tty;
chvt(target_tty);
HideCursor(target_tty);
}
~Term(){ /* 切回源tty */
chvt(origin_tty);
}
private:
int origin_tty;
static int open_tty(int num) {
char path[16] = {'\0'};
snprintf(path, sizeof(path), "/dev/tty%d", num);
int d = open(path, O_WRONLY);
if (d == -1)
throw std::runtime_error(path);
else
return d;
}
static void HideCursor(int id) {
int d = open_tty(id);
const char *hide = "\033[?25l";
if (write(d, hide, strlen(hide)) == -1){
close(d);
throw std::runtime_error("term writting");
}
close(d);
}
static void chvt(int id) {
char cmd[16] = {'\0'};
snprintf(cmd, sizeof(cmd), "chvt %d", id);
int err = system(cmd);
if (err)
throw std::runtime_error("chvt");
}
};
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
namespace qing {
class ThreadInterface {
public:
//---------------------------------------------
//程序睡眠阶段的操作函数。
virtual void StopEvent() = 0;
//程序设置阶段的操作函数。
virtual void WakeEvent() = 0;
//程序运行阶段的操作函数。
virtual void LoopEvent() = 0;
//程序清理阶段的操作函数。
virtual void ClearEvent() = 0;
//可以将操作函数作为一种事件,可以从外界传入写好的事件函数,
//那么就需要将操作函数设定为静态函数
};
}
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <iostream>
#include <cstddef>
namespace qing {
/* ANSI是WINDOWS操作系统默认的编码格式。 */
class ansi{
public:
static int size_gb18030(unsigned char *c, size_t maxLen);
static int size_gb2312(unsigned char first_byte);
class WrongLength: public std::runtime_error { /* 非法的长度 */
public:
WrongLength(): std::runtime_error("") {}
};
};
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include<mutex>
#include<condition_variable>
namespace qing{
namespace lci{
//用来存储状态的枚举类型
enum Stat{
SSHUT = -1,
SSTOP = 0,
SSTART = 1,
SRUNNING = 2
};//Status
class Fsm {//FiniteStateMachine有限状态机
public:
//构造函数
Fsm();
//检查状态
enum Stat chk();
//改变状态
void wake();
void stop();
void shut();
void run();
//protected:
//等待事件唤醒
void suspend();
private:
//锁类型,确保状态机线程安全
std::mutex lock;
//条件变量,用来执行等待或者唤醒
std::condition_variable cv;
//存放状态机的状态
enum Stat stat;
};//StateMachine
}//lci
}//qing
+160
View File
@@ -0,0 +1,160 @@
#pragma once
#include "Area.h"
#include "CmdArea.h"
#include "CommonThread.h"
namespace qing {
namespace lci{
/* PrintThread 打印线程 */
class p_th: public CommonThread {
public:
/**
* 构造函数 传入要读取的控制台设备文件描述符,背景画布,以及命令行区域
*/
p_th(std::string name, int masterfd, Drawable *back, CmdArea *font)
: CommonThread(name) {
this->masterfd = masterfd;
this->back = back;
this->font = font;
}
/**
* 析构函数 关闭线程
*
* 我在可控制线程中主要遇到的问题便是线程的自主终止,
*
* 在 Python 中似乎是只能实现可控制线程的手动退出的,
*
* 我在想是不是在cpp中也做成那样。
*
*
* FIXME(20260108): 啥意思不懂
*/
~p_th(){
/* 使线程自主关闭 */
if (this->chk() != lci::SSHUT){
this->shut();
}
/* 等待线程退出 */
this->WaitClose();
}
/**
* 暂时删除复制构造函数,因为复制出一个与原来线程无关的空白线程似乎没有什么作用
*
* 如果让两个变量引用同一个线程,会使得它们在结束的时候出现错误。
*/
p_th(p_th&) = delete;
/**
* 线程睡眠阶段的操作函数,线程等待。
*
* suspend() 方法似乎不太稳定,我还得再测试测试。
*/
void StopEvent() override {
this->suspend();
}
/**
* 线程苏醒之后执行的操作,线程启动。
*
* 我不知道为什么要等待1秒。
*/
void WakeEvent() {
/* 将文件描述符集合清零 */
FD_ZERO(&read_fds);
/* 清空缓存字符串 */
output = "";
/* 设置完毕,线程进入运行态 */
this->run();
}
/**
* 线程运行阶段的循环体,线程运行。
*
* 使用 SELECT 进行缓冲区的探测。
*/
void LoopEvent() {
/* 对可读集合进行清零 */
//FD_ZERO(&read_fds);
/* 设置可读集合 */
//FD_SET(masterfd, &read_fds);
/**
* 仅在集合中不存在控制台描述符时,才往其中添加该描述符
*
* 在这个集合中,应该只会存在这一个文件描述符吧
*/
if (!FD_ISSET(masterfd, &read_fds))
FD_SET(masterfd, &read_fds);
/* 设置超时时间 */
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
int ret = select(masterfd + 1, &read_fds, NULL, NULL, &timeout);
if (ret == -1) {
//throw std::runtime_error("select");
//this->stop();
return; /* qing(20260108): 为什么不停止 */
} else if (ret == 0) { /* No data to read 无值可读 */
if (output == "") return; /* 在空闲时进行打印*/
font->print((char*)output.c_str(), 0); /* 按次为单位进行刷新应该可以提高效率 20260108(qing): ?*/
back->flush(font, false);
output = "";
} else {
if (FD_ISSET(masterfd, &read_fds)) { /* 有值可读 */
nread = read(masterfd, buffer, sizeof(buffer));
if (nread > 0) {
buffer[nread] = '\0';
output += buffer;
}
}
}
}
/**
* 线程执行过后的清理函数,清理资源。
*
* 什么也不做。我们在唤醒时并未申请资源。
*/
void ClearEvent() {
;
}
private:
int masterfd; /* 对象中存储的要读取的控制台设备文件描述符。 */
Drawable *back; /* 对象中存储的背景画布指针 */
CmdArea *font; /* 对象中存储的命令行区域指针 */
std::string output; /* 从终端设备中读取的进程输出 */
//--------------------------------------------
/* 下面的变量是为了提高速度,避免重复申请 */
fd_set read_fds; /* 文件描述符集合,用于存储 SELECT 返回的可读区域 */
struct timeval timeout; /* 时间结构体 用于传入 SELECT 函数的超时时间 */
ssize_t nread; /* 这一次从控制台中所读取大小 */
char buffer[1024]; /* 存储从控制台中读取字符的缓冲区,一次最多读这么多 */
};
}
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
namespace qing {
class utf8{ /* */
public:
static int size(const unsigned char c);
static char *to_ansi(char *s);
};
}
+114
View File
@@ -0,0 +1,114 @@
/* 图层区域是能够绘制图片的区域类型 */
#define cimg_display 0
#define cimg_use_jpeg
#define cimg_use_png
#include <CImg.h>
#include "cn/中文化.hpp"
#include "lci/Area.h"
使用 命名空间 cimg_library;
命名空间 qing {
类 图层区域: 公开的 Area { /* 图层区域 */
公开的:
图层区域(Drawable *d, int w, int h, int x, int y, int rotate, int fontsize, CImg<unsigned char>& img)
: Area(d, w, h, x, y, rotate, fontsize) {
/* 储存图片,需要调用图片的构造函数 */
this->img = img;
}
空类型 涂写图像() {
单精度小数 区域长宽比 = (float)w / h;
单精度小数 图片长宽比 = (float)img.width() / img.height();
/* 长宽比越大,代表图片越横向细长
* 长宽比越小,代表图片越竖向细长
* 长宽比为1时,图片为正方形
*
* 图片长宽比较大时,取区域长
* 图片长宽比较小时,取区域高 */
逻辑型 长为标准 = 图片长宽比 > 区域长宽比;
如果(长为标准) {
auto fixed = scaleByWidth(this->img, this->w);
CImg<unsigned char> gray = 转灰度图(fixed);
auto start = (int)(this->h - gray.height()) / 2;
for (int y = 0; y < gray.height(); ++y) {
for (int x = 0; x < gray.width(); ++x){
auto xx = x;
auto yy = y + start;
auto clr1 = 颜色转换(gray(x, y), this->clr);
this->point(xx, yy, clr1);
}
}
}
否则{ /* 以宽为标准 */
auto fixed = scaleByHeight(this->img, this->h);
auto gray = 转灰度图(fixed);
auto start = (int)(this->w - gray.width()) / 2;
for (int y = 0; y < gray.height(); ++y) {
for (int x = 0; x < gray.width(); ++x){
auto xx = x + start;
auto yy = y;
auto clr1 = 颜色转换(gray(x, y), this->clr);
this->point(xx, yy, clr1);
}
}
}
}
私有的:
CImg<unsigned char> img;
/* 以长为标准缩放 */
static CImg<unsigned char> scaleByWidth(const CImg<unsigned char>& src, int newWidth) {
/* 计算缩放比例 */
float ratio = (float)newWidth / src.width();
int newHeight = (int)(src.height() * ratio);
/* 使用_resize方法进行缩放 */
return src.get_resize(newWidth, newHeight, -100, -100, 5);
}
/* 以高为标准缩放 */
static CImg<unsigned char> scaleByHeight(const CImg<unsigned char>& src, int newHeight) {
/* 计算缩放比例 */
float ratio = (float)newHeight / src.height();
int newWidth = (int)(src.width() * ratio);
/* 计算_resize方法进行缩放 */
return src.get_resize(newWidth, newHeight, -100, -100, 5);
}
/* 将灰度颜色转换为我们目前画笔的颜色 */
静态的 Color 颜色转换(无符号 字符 灰度, Color clr) {
单精度小数 红 = (单精度小数)clr.r / 255;
单精度小数 绿 = (单精度小数)clr.g / 255;
单精度小数 蓝 = (单精度小数)clr.b / 255;
自动的 结果 = Color(红* 灰度*255, 绿*灰度*255, 蓝*灰度*255);
返回 结果;
}
/* 将CImg对象转为灰度图 */
静态的 CImg<unsigned char> 转灰度图(CImg<unsigned char>& img) {
if (img.spectrum() == 3) {
return img.get_normalize(0, 255).get_RGBtoXYZ().get_channel(1);
}
else if (img.spectrum() ==4) {
auto rgb_img = t_4_to_3(img);
return rgb_img.get_RGBtoXYZ().get_channel(1);
}
else {
抛出异常 std::runtime_error("没有对应通道数的算法");
}
}
/* 将4通道图片转为3通道 */
静态的 CImg<unsigned char> t_4_to_3(CImg<unsigned char>& img) {
// 创建RGB图像(3通道)
CImg<unsigned char> rgb_img(img.width(), img.height(), 1, 3);
cimg_forXY(rgb_img, x, y) {
rgb_img(x, y, 0, 0) = img(x, y, 0, 0); // R
rgb_img(x, y, 0, 1) = img(x, y, 0, 1); // G
rgb_img(x, y, 0, 2) = img(x, y, 0, 2); // B
// 忽略alpha通道 img(x, y, 0, 3)
}
return rgb_img;
}
};
}
+121
View File
@@ -0,0 +1,121 @@
/*
* 用于在可绘制对象上绘制中文文字
*
* 绘制时将对象作为参数传入
*/
#include "cn/中文化.hpp"
#include "lci/Drawable.h"
/* 用于文字的绘制,只要不动就线程安全 */
extern unsigned char ttu[];
extern int ttunumber;
extern unsigned char zzhi[];
extern int zzhinumber;
命名空间 qing {
类 字体绘制器 {
私有的:
/*------ fonts lib ------
* 文字库 */
int font_w, font_h;
unsigned short *chss = (unsigned short *)zzhi;
unsigned char *vec = ttu;
int zn = zzhinumber;
int vennum = ttunumber;
unsigned char *drawvect(Drawable* d, int x, int y, unsigned char *vect, int width, int high, Color &clr)
// x, y是左上角坐标,vect指向矢量图数据,width和high分别代表要绘制的图的宽和高(好像宽需要=高)
{
if (!vect) return nullptr;
int i = 0, j = 1; // 指向第一对数字
unsigned char ix, iy; // 从数组取出的第一对坐标放在这
double x1, y1;//, x2, y2; // 绘制直线的实数的坐标
if (high == 0) high = width; // 调节高宽
int ii1, jj1, ii2, jj2; // 最后算出的绘制直线的坐标
int isend = 0; //是否到达曲线尾
int isallend = 0; // 是否结束整个图像
do {
ix = vect[i];
iy = vect[j];
isend = ix & 1; // 奇数代表曲线尾
isallend = iy & 1; // 奇数代表整个图像结束
if (isallend) {
i += 2;
break; // 整个图像结束返回
}
if (isend) { // 如果这里曲线结束什么也不画进到下一条曲线
i += 2;
j += 2;
continue;
}
ix /= 2;
iy /= 2;
x1 = ix;
y1 = iy;
x1 = width * x1 / 128.0;
y1 = high * y1 / 128.0;
ii1 = (int)(x1 + x);
jj1 = (int)(y1 + y);
int k;
for (k = 0; k < 100000; k++) {
//x2 = x1;
//y2 = y1;
ii2 = ii1;
jj2 = jj1;
i += 2;
j += 2;
ix = vect[i];
iy = vect[j];
isend = ix & 1; //奇数代表曲线尾
isallend = iy & 1; //奇数代表整个图像结束
ix /= 2;
iy /= 2;
x1 = ix;
y1 = iy;
x1 = width * x1 / 128.0;
y1 = high * y1 / 128.0;
ii1 = (int)(x1 + x);
jj1 = (int)(y1 + y);
d->line(ii1, jj1, ii2, jj2, clr);
if (isend || isallend)
break;
}
i += 2; //指向下一条曲线
j += 2;
} while (!isallend);
return vect + i;
}
公开的:
字体绘制器(const int font_w, const int font_h)
: font_w(font_w), font_h(font_h) {}
/* 绘制文字 */
void drawvfont(Drawable* d, int x, int y, unsigned short z, Color &clr) {
int i, j, k, ii;
j = -1;
for (i = 0; i < zn; i++) {
if (chss[i] == z) {
j = i;
break;
}
}
if (j < 0) return;
k = 0;
for (i = 0; i < vennum; i++) {
if (k == j)
break;
for (ii =i; ii <vennum; ii++) {
if (vec[2*ii + 1] & 1) {
k++;
i = ii;
break;
}
}
}
if (k < j) return;
drawvect(d, x, y, vec + 2 * i, font_w, font_h, clr);
}
};
}