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)能够生成语义流…...

园区管理智能化创新引领企业效能提升与风险控制新趋势
内容概要 在现代园区管理中,智能化创新正成为越来越多企业优化效能和控制风险的重要途径。通过引入先进的技术手段,企业能够更高效地管理资源,并实现全面的风险控制。 首先,园区管理系统的基本概念和发展现状让我们看到科技与管…...

Python爬虫之——Cookie存储器
目录 专栏导读1、背景介绍2、库的安装3、核心代码4、完整代码总结 专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注 &…...

第21节课:前端构建工具—自动化与模块化的利器
目录 前端构建工具的重要性任务运行器:Gulp与GruntGulpGulp的工作原理安装与使用Gulp GruntGrunt的工作原理安装与使用Grunt 模块打包器:WebpackWebpack简介Webpack的工作原理安装与使用Webpack 实践:使用Gulp和Webpack构建前端项目示例&…...

企业SaaS(软件即服务)行业中AARRR
获取(Acquisition) 通过各种渠道吸引用户。 社交媒体广告:Facebook、Instagram等平台的广告。 内容营销:通过博客、视频等吸引用户。 SEO优化:提高网站在搜索引擎中的排名。 合作营销:与其他企业合作进行交…...

为什么要学习rust
内存管理:对于我来说,我就喜欢它的内存管理。我做了一个webapi,取100万行数据,导出到xlsx,再把这个xlsx文件发送给前端。分别用了java、c#、go和rust进行了相同的操作。只有rust做到了,启动时8MB内存&#…...

观察者模式和订阅发布模式的关系
有人把观察者模式等同于发布订阅模式,也有人认为这两种模式存在差异,本质上就是调度的方法不同。 发布订阅模式: 观察者模式: 相比较,发布订阅将发布者和观察者之间解耦。(发布订阅有调度中心处理)...

基于STM32的智能温控花盆设计
目录 引言系统设计 硬件设计软件设计 系统功能模块 空气质量传感器模块数据处理与分析模块实时显示与用户交互模块报警与提示模块远程监控与数据上传模块 控制算法 空气质量数据处理与分析算法异常检测与报警算法数据上传与历史数据回溯算法 代码实现 空气质量检测与数据处理代…...

OpenAI-Edge-TTS:本地化 OpenAI 兼容的文本转语音 API,免费高效!
文本转语音(TTS)技术已经成为人工智能领域的重要一环,无论是语音助手、教育内容生成,还是音频文章创作,TTS 工具都能显著提高效率。今天要为大家介绍的是 OpenAI-Edge-TTS,一款基于 Microsoft Edge 在线文本…...

P4681 [THUSC 2015] 平方运算 Solution
Description 给定序列 a ( a 1 , a 2 , ⋯ , a n ) a(a_1,a_2,\cdots,a_n) a(a1,a2,⋯,an) 和常数 p p p ,有 m m m 个操作,分以下两种: modify ( l , r ) \operatorname{modify}(l,r) modify(l,r):对每个 i ∈ [ …...

【apt源】RK3588 平台ubuntu20.04更换apt源
RK3588芯片使用的是aarch64架构,因此在Ubuntu 20.04上更换apt源时需要使用针对aarch64架构的源地址。以下是针对RK3588芯片在Ubuntu 20.04上更换apt源到清华源的正确步骤: 步骤一:打开终端 在Ubuntu 20.04中,按下Ctrl Alt T打…...