FLTK - FLTK1.4.1 - demo - animgifimage
文章目录
- FLTK - FLTK1.4.1 - demo - animgifimage
- 概述
- 笔记
- END
FLTK - FLTK1.4.1 - demo - animgifimage
概述
知识点:
注册图像文件类型判断回调
FLTK支持的图像格式 GIF, BMP, ICO, PNM, PNG, jpg, svg
事件回调的注册
GIF图像显示为图片或动画的标志设置
// 超时回调的设置和移除, 超时回调是一次性的,如果还需要同一个超时回调,需要再次设置超时回调
// 文件选择器UI的调用和返回
// 用户选择通过文件选择器选择的文件,有可能不是指定尾缀的文件类型
// fltk窗口的遍历
// fltk窗口 背景颜色设置 Fl_Color
// fltk窗口退出回调的设置
// 图像数据载入成功和图像数据有效的判断
// 图像关键数据(长,宽,帧数)的取得
// fltk窗口类的copy_x()是复制了一份数据,并不是指向原始数据
// fltk图像类禁用缓存
// fltk窗体禁止响应快捷键的窗体size缩放
// 等待当前窗体正常结束
// fltk类的构造函数是通过弹窗来报错的(e.g. 图像文件格式错), 这个报错信息不是API调用者能控制的。
笔记
// FLTK - FLTK1.4.1 - demo - animgifimage
/*
知识点:注册图像文件类型判断回调FLTK支持的图像格式 GIF, BMP, ICO, PNM, PNG, jpg, svg事件回调的注册GIF图像显示为图片或动画的标志设置// 超时回调的设置和移除, 超时回调是一次性的,如果还需要同一个超时回调,需要再次设置超时回调// 文件选择器UI的调用和返回// 用户选择通过文件选择器选择的文件,有可能不是指定尾缀的文件类型// fltk窗口的遍历// fltk窗口 背景颜色设置 Fl_Color// fltk窗口退出回调的设置// 图像数据载入成功和图像数据有效的判断// 图像关键数据(长,宽,帧数)的取得// fltk窗口类的copy_x()是复制了一份数据,并不是指向原始数据// fltk图像类禁用缓存// fltk窗体禁止响应快捷键的窗体size缩放// 等待当前窗体正常结束// fltk类的构造函数是通过弹窗来报错的(e.g. 图像文件格式错), 这个报错信息不是API调用者能控制的。
*/#include "fltk_test.h"// 如果要将fl demo的实现搬过来测试,就注释掉下面的宏
// #define DONT_USE_FL_DEMO#ifdef DONT_USE_FL_DEMO
int fl_demo_main(int argc, char** argv)
{return 0;
}#else#endif // TEST_FL_DEMO//
// Test program for displaying animated GIF files using the
// Fl_Anim_GIF_Image class.
//
#include <FL/Fl_Anim_GIF_Image.H>#include <FL/Fl_Double_Window.H>
#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_Shared_Image.H>
#include <FL/Fl_Tiled_Image.H>
#include <stdlib.h>static int g_good_count = 0, g_bad_count = 0, g_frame_count = 0;static const Fl_Color BackGroundColor = FL_GRAY; // use e.g. FL_RED to see// transparent parts better
static const double RedrawDelay = 30 /* 1. / 20*/ ; // interval [sec] for forced redrawstatic void quit_cb(Fl_Widget* w_, void*) {exit(0);
}static void set_title(Fl_Window* win, Fl_Anim_GIF_Image* animgif) {char buf[200];snprintf(buf, sizeof(buf), "%s (%d frames) %2.2fx", fl_filename_name(animgif->name()),animgif->frames(), animgif->speed());if (animgif->frame_uncache())strcat(buf, " U");// fltk窗口类的copy_x()是复制了一份数据,并不是指向原始数据win->copy_label(buf);win->copy_tooltip(buf);
}static void cb_forced_redraw(void* d) {// fltk窗口的遍历Fl_Window* win = Fl::first_window();while (win) {if (!win->menu_window())win->redraw();win = Fl::next_window(win);}if (Fl::first_window())Fl::repeat_timeout(RedrawDelay, cb_forced_redraw);
}Fl_Window* openFile(const char* name, char* flags, bool close = false) {// determine test options from 'flags'bool uncache = strchr(flags, 'u');char* d = flags - 1;int debug = 0;while ((d = strchr(++d, 'd'))) debug++;bool optimize_mem = strchr(flags, 'm');bool desaturate = strchr(flags, 'D');bool average = strchr(flags, 'A');bool test_tiles = strchr(flags, 'T');bool test_forced_redraw = strchr(flags, 'f');char* r = strchr(flags, 'r');bool resizable = r && !test_tiles;double scale = 1.0;if (r && resizable) scale = atof(r + 1);if (scale <= 0.1 || scale > 5)scale = resizable ? 0.7 : 1.0;// setup windowFl::remove_timeout(cb_forced_redraw);Fl_Double_Window* win = new Fl_Double_Window(300, 300);// fltk窗口 背景颜色设置 Fl_Colorwin->color(BackGroundColor);if (close){// fltk窗口退出回调的设置win->callback(quit_cb);}printf("Loading '%s'%s%s ... ", name,uncache ? " (uncached)" : "",optimize_mem ? " (optimized)" : "");// create a canvas for the animationFl_Box* canvas = test_tiles ? 0 : new Fl_Box(0, 0, 0, 0); // canvas will be resized by animationFl_Box* canvas2 = 0;unsigned short gif_flags = debug ? Fl_Anim_GIF_Image::LOG_FLAG : 0;if (debug > 1)gif_flags |= Fl_Anim_GIF_Image::DEBUG_FLAG;if (optimize_mem)gif_flags |= Fl_Anim_GIF_Image::OPTIMIZE_MEMORY;// create animation, specifying this canvas as display widget// fltk类的构造函数是通过弹窗来报错的(e.g. 图像文件格式错), 这个报错信息不是API调用者能控制的。Fl_Anim_GIF_Image* animgif = new Fl_Anim_GIF_Image(name, canvas, gif_flags);// 图像数据载入成功和图像数据有效的判断bool good(animgif->ld() == 0 && animgif->valid());// 图像关键数据(长,宽,帧数)的取得printf("%s: %d x %d (%d frames) %s\n",animgif->name(), animgif->w(), animgif->h(), animgif->frames(), good ? "OK" : "ERROR");// for the statistics (when run on testsuite):g_good_count += good;g_bad_count += !good;g_frame_count += animgif->frames();// 设置窗体的用户数据win->user_data(animgif); // store address of image (see note in main())// exercise the optional tests on the animation// fltk图像类禁用缓存animgif->frame_uncache(uncache);if (scale != 1.0) {animgif->resize(scale);printf("TEST: resized %s by %.2f to %d x %d\n", animgif->name(), scale, animgif->w(), animgif->h());}if (average) {printf("TEST: color_average %s\n", animgif->name());animgif->color_average(FL_GREEN, 0.5); // currently hardcoded}if (desaturate) {printf("TEST: desaturate %s\n", animgif->name());animgif->desaturate();}int W = animgif->w();int H = animgif->h();if (animgif->frames()) {if (test_tiles) {// demonstrate a way how to use the animation with Fl_Tiled_Imageprintf("TEST: use %s as tiles\n", animgif->name());W *= 2;H *= 2;Fl_Tiled_Image* tiled_image = new Fl_Tiled_Image(animgif);Fl_Group* group = new Fl_Group(0, 0, win->w(), win->h());group->image(tiled_image);group->align(FL_ALIGN_INSIDE);animgif->canvas(group, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS | Fl_Anim_GIF_Image::DONT_SET_AS_IMAGE);win->resizable(group);}else {// demonstrate a way how to use same animation in another canvas simultaneously:// as the current implementation allows only automatic redraw of one canvas..if (test_forced_redraw) {if (W < 400) {printf("TEST: open %s in another animation with application redraw\n", animgif->name());canvas2 = new Fl_Box(W, 0, animgif->w(), animgif->h()); // another canvas for animationcanvas2->image(animgif); // is set to same animation!W *= 2;Fl::add_timeout(RedrawDelay, cb_forced_redraw); // force periodic redraw}}}// make window resizable (must be done before show())if (resizable && canvas && !test_tiles) {win->resizable(win);}win->size(W, H); // change to actual size of canvas// start the animationwin->end();win->show();win->wait_for_expose();set_title(win, animgif);if (resizable && !test_tiles) {// need to reposition the widgets (have been moved by setting resizable())if (canvas && canvas2) {canvas->resize(0, 0, W / 2, canvas->h());canvas2->resize(W / 2, 0, W / 2, canvas2->h());}else if (canvas) {canvas->resize(0, 0, animgif->canvas_w(), animgif->canvas_h());}}// fltk窗体禁止响应快捷键的窗体size缩放win->init_sizes(); // IMPORTANT: otherwise weird things happen at Ctrl+/- scaling}else {delete win;return 0;}if (debug >= 3) {// open each frame in a separate windowfor (int i = 0; i < animgif->frames(); i++) {char buf[200];snprintf(buf, sizeof(buf), "Frame #%d", i + 1);Fl_Double_Window* win = new Fl_Double_Window(animgif->w(), animgif->h());win->copy_tooltip(buf);win->copy_label(buf);win->color(BackGroundColor);int w = animgif->image(i)->w();int h = animgif->image(i)->h();// in 'optimize_mem' mode frames must be offsetted to canvasint x = (w == animgif->w() && h == animgif->h()) ? 0 : animgif->frame_x(i);int y = (w == animgif->w() && h == animgif->h()) ? 0 : animgif->frame_y(i);Fl_Box* b = new Fl_Box(x, y, w, h);// get the frame imageb->image(animgif->image(i));win->end();win->show();}}return win;
}#include <FL/filename.H>
bool openDirectory(const char* dir, char* flags) {dirent** list;int nbr_of_files = fl_filename_list(dir, &list, fl_alphasort);if (nbr_of_files <= 0)return false;int cnt = 0;for (int i = 0; i < nbr_of_files; i++) {char buf[512];const char* name = list[i]->d_name;if (!strcmp(name, ".") || !strcmp(name, "..")) continue;const char* p = strstr(name, ".gif");if (!p) p = strstr(name, ".GIF");if (!p) continue;if (*(p + 4)) continue; // is no extension!snprintf(buf, sizeof(buf), "%s/%s", dir, name);if (strstr(name, "debug")) // hack: when name contains 'debug' open single framesstrcat(flags, "d");if (openFile(buf, flags, cnt == 0))cnt++;}return cnt != 0;
}static void change_speed(double delta) {Fl_Widget* below = Fl::belowmouse();if (below && below->image()) {Fl_Anim_GIF_Image* animgif = 0;// Q: is there a way to determine Fl_Tiled_Image without using dynamic cast?Fl_Tiled_Image* tiled = dynamic_cast<Fl_Tiled_Image*>(below->image());animgif = tiled ?dynamic_cast<Fl_Anim_GIF_Image*>(tiled->image()) :dynamic_cast<Fl_Anim_GIF_Image*>(below->image());if (animgif && animgif->playing()) {double speed = animgif->speed();if (!delta) speed = 1.;else speed += delta;if (speed < 0.1) speed = 0.1;if (speed > 10) speed = 10;animgif->speed(speed);set_title(below->window(), animgif);}}
}static int events(int event) {if (event == FL_SHORTCUT) {if (Fl::event_key() == '+')change_speed(0.1);else if (Fl::event_key() == '-')change_speed(-0.1);else if (Fl::event_key() == '0')change_speed(0);elsereturn 0;return 1;}return 0;
}static const char testsuite[] = "testsuite";int fl_demo_main(int argc, char* argv[]) {// 注册图像文件类型判断回调fl_register_images();// 事件回调的注册Fl::add_handler(events);char* openFlags = (char*)calloc(1024, 1);if (argc > 1) {// started with argumemtsif (strstr(argv[1], "-h")) {printf("Usage:\n"" -t [directory] [-{flags}] open all files in directory (default name: %s) [with options]\n"" filename [-{flags}] open single file [with options] \n"" No arguments open a fileselector\n"" {flags} can be: d=debug mode, u=uncached, D=desaturated, A=color averaged, T=tiled\n"" m=minimal update, r[scale factor]=resize by 'scale factor'\n"" Use keys '+'/'-/0' to change speed of the active image (belowmouse).\n", testsuite);exit(1);}for (int i = 1; i < argc; i++) {if (argv[i][0] == '-')strcat(openFlags, &argv[i][1]);}if (strchr(openFlags, 't')) { // open all GIF-files in a given directoryconst char* dir = testsuite;for (int i = 2; i < argc; i++)if (argv[i][0] != '-')dir = argv[i];openDirectory(dir, openFlags);printf("Summary: good=%d, bad=%d, frames=%d\n", g_good_count, g_bad_count, g_frame_count);}else { // open given file(s)for (int i = 1; i < argc; i++)if (argv[i][0] != '-')openFile(argv[i], openFlags, strchr(openFlags, 'd'));}}else {// started without arguments: choose file// GIF图像显示为图片或动画的标志设置Fl_GIF_Image::animate = true; // create animated shared .GIF images (e.g. file chooser)while (1) {Fl::add_timeout(RedrawDelay, cb_forced_redraw); // animate images in chooser// 文件选择器UI的调用和返回// 用户选择通过文件选择器选择的文件,有可能不是指定尾缀的文件类型const char* filename = fl_file_chooser("Select a GIF image file", "*.{gif,GIF}", NULL);// 超时回调的移除Fl::remove_timeout(cb_forced_redraw);if (!filename)break;Fl_Window* win = openFile(filename, openFlags);// 等待当前窗体正常结束Fl::run();// delete last window (which is now just hidden) to test destructors// NOTE: it is essential that *before* doing this also the// animated image is destroyed, otherwise it will crash// because it's canvas will be gone.// In order to keep this demo simple, the adress of the// Fl_Anim_GIF_Image has been stored in the window's user_data.// In a real-life application you will probably store// it somewhere in the window's or canvas' object and destroy// the image in the window's or canvas' destructor.if (win && win->user_data())delete ((Fl_Anim_GIF_Image*)win->user_data());delete win;}}return Fl::run();
}
END
相关文章:
FLTK - FLTK1.4.1 - demo - animgifimage
文章目录 FLTK - FLTK1.4.1 - demo - animgifimage概述笔记END FLTK - FLTK1.4.1 - demo - animgifimage 概述 知识点: 注册图像文件类型判断回调 FLTK支持的图像格式 GIF, BMP, ICO, PNM, PNG, jpg, svg 事件回调的注册 GIF图像显示为图片或动画的标志设置 // 超时回调的设置…...
目前市场主流的AI PC对于大模型本地部署的支持情况分析-Deepseek
以下是目前市场主流AI PC对**大模型本地部署支持情况**的综合分析,结合硬件能力、软件生态及厂商动态进行总结: --- ### **一、硬件配置与算力支持** 1. **核心处理器架构** - **异构计算方案(CPUGPUNPU)**:主流…...

1.2 基于深度学习的底层视觉技术
文章目录 高层视觉任务与底层视觉任务深度神经网络相对于传统方法的优势 高层视觉任务与底层视觉任务 计算机视觉中的任务包含高层视觉任务,底层视觉任务。高层视觉任务是处理语义级别相关的任务,例如图像分类、目标检测、图像分割等。底层视觉任务处理与…...
HTML 标题
HTML 标题 引言 HTML(超文本标记语言)是构建网页的基础,而标题则是网页中不可或缺的元素。标题不仅能够帮助用户快速了解网页内容,还能够对搜索引擎优化(SEO)产生重要影响。本文将详细介绍HTML标题的用法…...

SOME/IP--协议英文原文讲解3
前言 SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块: 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 Note: Thi…...

Microsoft Visual Studio 2022 主题修改(补充)
Microsoft Visual Studio 2022 透明背景修改这方面已经有很多佬介绍过了,今天闲来无事就补充几点细节。 具体的修改可以参考:Microsoft Visual Studio 2022 透明背景修改(快捷方法)_material studio怎么把背景弄成透明-CSDN博客文…...

UE(UltraEdit) 配置简易C/C++编译运行环境
该类型其他帖子 EmEditor 配置简易C/C 编译运行环境_emeditor 代码运行-CSDN博客 RJ TextEd 配置简易C/C 编译运行环境-CSDN博客 这种配置适合ACM竞赛,即要求不使用现代IDE,又想用一个比较好用、至少支持代码高亮的编辑器。 前提条件 1.Mingw GCC 已…...

使用 MSYS2 qemu 尝鲜Arm64架构国产Linux系统
近期,我的师弟咨询我关于Arm64架构的国产CPU国产OS开发工具链问题。他们公司因为接手了一个国企的单子,需要在这类环境下开发程序。说实在的我也没有用过这个平台,但是基于常识,推测只要基于C和Qt,应该问题不大。 1. …...
python Flask-Redis 连接远程redis
当使用Flask-Redis连接远程Redis时,首先需要安装Flask-Redis库。可以通过以下命令进行安装: pip install Flask-Redis然后,你可以使用以下示例代码连接远程Redis: from flask import Flask from flask_redis import FlaskRedisa…...

在Windows系统中本地部署属于自己的大语言模型(Ollama + open-webui + deepseek-r1)
文章目录 1 在Windows系统中安装Ollama,并成功启动;2 非docker方式安装open-webui3下载并部署模型deepseek-r1 Ollama Ollama 是一个命令行工具,用于管理和运行机器学习模型。它简化了模型的下载与部署,支持跨平台使用,…...

Haproxy入门学习二
一、Haproxy的算法 1.haproxy通过固定参数balance指明对后端服务器的调度算法,其中balance参数可以配置在listen或backend选项中 2.haproxy的调度算法分为静态和动态调度算法,其中有些算法可以根据参数在静态和动态算法中相互转换 3.静态算法:…...

Git图形化工具【lazygit】
简要介绍一下偶然发现的Git图形化工具——「lazygit」 概述 Lazygit 是一个用 Go 语言编写的 Git 命令行界面(TUI)工具,它让 Git 操作变得更加直观和高效。 Github地址:https://github.com/jesseduffield/lazygit 主要特点 主要…...

node 爬虫开发内存处理 zp_stoken 作为案例分析
声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 前言 主要说3种我们补环境过后如果用…...

基于Langchain-Chatchat + ChatGLM 本地部署知识库
一、相关环境 参考链接: Github:https://github.com/chatchat-space/Langchain-Chatchat Langchain-chatchat版本:v0.3.1 安装环境:Ubuntu:22.04,CUDA:12.1 二、搭建过程 2.1 环境配置 2.1.1 创建chatchat虚拟环…...

【C语言】main函数解析
一、前言 在学习编程的过程中,我们很早就接触到了main函数。在Linux系统中,当你运行一个可执行文件(例如 ./a.out)时,如果需要传入参数,就需要了解main函数的用法。本文将详细解析main函数的参数ÿ…...
【QT】- QUdpSocket
QUdpSocket 是 Qt 自带的一个类,属于 Qt 网络模块,用于进行 UDP(用户数据报协议) 通信。它提供了简便的接口来发送和接收 UDP 数据报(datagrams)。 UDP 是一种无连接的协议,适用于那些不需要确…...
性能测试丨分布式性能监控系统 SkyWalking
软件测试领域,分布式系统的复杂性不断增加,如何保证应用程序的高可用性与高性能,这是每一个软件测试工程师所面临的重大挑战。幸运的是,现在有了一些强大的工具来帮助我们应对这些挑战,其中之一便是Apache SkyWalking。…...
SQL GROUP BY 详解
SQL GROUP BY 详解 引言 在数据库查询中,GROUP BY 子句是一个非常有用的工具,它允许我们对查询结果进行分组,并基于这些分组进行聚合计算。本文将详细介绍 GROUP BY 的用法、注意事项以及在实际应用中的场景。 什么是 GROUP BY? GROUP BY 子句用于对查询结果进行分组。…...
C语言中string.h头文件功能介绍
在C语言的世界里,string.h头文件提供了许多用于处理字符串和内存操作的函数。今天,我们就来深入探讨string.h头文件的功能、使用注意事项以及一些拓展应用。 一、功能介绍 string.h头文件定义了一系列用于操作字符串和内存的函数。这些函数可以分为几个…...
从规则到神经网络:机器翻译技术的演进与未来展望
从规则到神经网络:机器翻译技术的演进与未来展望 引言 还记得早些年用翻译软件翻译一句简单的英文句子,却发现翻译结果让人啼笑皆非的日子吗?从“我喜欢吃苹果”被翻译成“我喜欢吃苹果电脑”,到今天的神经网络机器翻译(Neural Machine Translation, NMT)能够生成语义流…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...