在前面一篇,已经能够基于gtk读取图像并显示。更前面的一篇:基于GDI的imshow:使用stb_image读取图像并修正绘制,通过stb_image读取图像并通过GDI显示图像,实现了一个imshow。本篇则在这两基础上,利用stb_image读取图像,并利用gtk显示,初步实现一个基于gtk的imshow。

首先是找到一份代码,从指定的buffer创建gtk的image并显示(参考1)。然后用stb image读取,先前我进行了封装,得到fc image是和opencv兼容的bgr格式。然而发现gtk需要的是rgb的顺序,因此又做了一道转化步骤:BGR to RGB,然后把对应的buffer传给gtk去生成它的image。

代码实现

完整的代码需要 基于GDI的imshow:使用stb_image读取图像并修正绘制 这一篇blog中的代码,以及本文新增的代码gtk_show_image_v3.c:

#include <gtk/gtk.h>
#include <stdlib.h>
#include <assert.h> #include "fc_image.h" void fc_bgr_to_rgb(FcImage* im) {
if (im==NULL) return;
if (im->c<=0 || im->h<=0 || im->w==0) return;
assert(im->c==3); int num_pixel = im->c * im->h * im->w;
unsigned char t;
for(int i=0; i<num_pixel; i+=3) {
t = im->data[i];
im->data[i] = im->data[i+2];
im->data[i+2] = t;
}
} int main (int argc, char *argv[])
{
const char* im_pth = "/home/zz/work/libfc/imgs/fruits.jpg";
FcImage im = fc_load_image(im_pth);
fc_bgr_to_rgb(&im); GtkWidget *window;
GtkWidget* image; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data (im.data, GDK_COLORSPACE_RGB,
FALSE, 8, im.w, im.h, im.w*3, NULL, NULL); gtk_window_set_title (GTK_WINDOW (window), "Image Viewer"); g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); image = gtk_image_new_from_pixbuf (pixbuf);
gtk_container_add(GTK_CONTAINER (window), image); gtk_widget_show_all (window); gtk_main (); return 0;
}

简单封装

考虑到把原有的bgr顺序的图像buffer修改为rgb,就地修改肯定是有问题的,影响到后续算法的使用。因此应当拷贝产生一个新的图像数据。并且还需要把im和title作为参数,封装为API,以后调用方便。修改后的代码如下:

#include <gtk/gtk.h>
#include <stdlib.h>
#include <assert.h> #include "fc_image.h" void fc_copy_bgr_to_rgb(const FcImage* src, FcImage* dst) {
if (src==NULL) return;
if (dst==NULL) return;
assert(src!=dst);
assert(src->data!=NULL);
assert(dst->data!=NULL);
assert(src->data!=dst->data);
assert(src->c>=0 && src->h>=0 && src->c==3);
assert(src->c>=0 && src->h>=0 && src->c==3);
assert(src->c==dst->c && src->h==dst->h && src->w==dst->w); int num_pixel = src->c * src->h * src->w;
for(int i=0; i<num_pixel; i+=3) {
dst->data[i] = src->data[i+2];
dst->data[i+1] = src->data[i+1];
dst->data[i+2] = src->data[i];
}
} FcImage fc_make_image(int w, int h, int c)
{
FcImage out;
out.w = w;
out.h = h;
out.c = c;
out.data = (unsigned char*)calloc(h*w*c, sizeof(float));
return out;
} void gtk_show_image_v3(const FcImage* im, const char* title)
{
FcImage im_rgb = fc_make_image(im->w, im->h, im->c); //?? check this dimensions
fc_copy_bgr_to_rgb(im, &im_rgb); GtkWidget *window;
GtkWidget* image; gtk_init (NULL, NULL); window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data (im_rgb.data, GDK_COLORSPACE_RGB,
FALSE, 8, im_rgb.w, im_rgb.h, im_rgb.w*3, NULL, NULL); gtk_window_set_title (GTK_WINDOW (window), title); g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); image = gtk_image_new_from_pixbuf (pixbuf);
gtk_container_add(GTK_CONTAINER (window), image); gtk_widget_show_all (window); gtk_main ();
} int main (int argc, char *argv[])
{
const char* im_pth = "/home/zz/work/libfc/imgs/fruits.jpg";
FcImage im = fc_load_image(im_pth);
const char* title = "fruits";
gtk_show_image_v3(&im, title); return 0;
}

其他注意

使用stb image.h的时候提示需要链接math库,也就是CMakeLists.txt中target_link_libraries时加上m

参考

Display a sequence of images using gtk in Linux

基于gtk的imshow:用stb_image读取图像并用gtk显示的更多相关文章

  1. 【QT】对话框打开图像并用QPixmap显示

    绘图设备是指继承QPaintDevice的子类,可以使用QPainter直接在其上面绘制图形,Qt一共提供了四个这样继承QPaintDevice的绘图设备类. 分别是QPixmap.QBitmap.Q ...

  2. 基于gtk的imshow:用gtk读取并显示图像

    gtk实现imshow,最naive的做法是用gtk的组件去读取图像,然后show出来:后续再考虑用GTK显示用别的方式例如stb image读取的图像.先前基于GDI实现imshow时也是这一思路, ...

  3. 最简单的基于FFmpeg的AVDevice例子(读取摄像头)

    =====================================================最简单的基于FFmpeg的AVDevice例子文章列表: 最简单的基于FFmpeg的AVDev ...

  4. 基于FPGA的线阵CCD实时图像采集系统

    基于FPGA的线阵CCD实时图像采集系统 2015年微型机与应用第13期 作者:章金敏,张 菁,陈梦苇2016/2/8 20:52:00 关键词: 实时采集 电荷耦合器件 现场可编程逻辑器件 信号处理 ...

  5. [转载] 最简单的基于FFmpeg的AVDevice例子(读取摄像头)

    =====================================================最简单的基于FFmpeg的AVDevice例子文章列表: 最简单的基于FFmpeg的AVDev ...

  6. 最简单的基于FFmpeg的AVDevice例子(读取摄像头)【转】

    转自:http://blog.csdn.net/leixiaohua1020/article/details/39702113 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[- ...

  7. OpenCV2:第三章 读取图像

    一.简介 将图像文件读入内存,可以用cv::imread()函数 二.读取图像 Mat imread(const string& filename,int flags=1); Mat: 如果读 ...

  8. OpenCV读取图像问题:OpenCV(3.4.3) D:\Build\OpenCV\opencv-size.width0 && size.height0 in function 'cvimshow'

    版权声明:本文为博主原创文章,转载 请注明出处:https://blog.csdn.net/sc2079/article/details/83280067 - 问题与解决 最近正在学OpenCV,发现 ...

  9. opencv学习之读取图像-imread函数

    序 想要完整全面地学习opencv,仅凭阅读samples的示例源码是不够的.毕竟opencv是一个拥有非常多函数的程序库,所以在每学习一个函数时,芒果觉得有必要记录下来,分享给有需要的同学.于是,就 ...

随机推荐

  1. Ubuntu 上编译opencv_contrib模块for Android

    https://blog.csdn.net/ipfpm/article/details/81132144 [ubuntu]Ubuntu中Android SDK下载跟配置 android24的版本 (1 ...

  2. dmesg 命令的使用范例

    dmesg 命令的使用范例 ‘dmesg’命令设备故障的诊断是非常重要的.在‘dmesg’命令的帮助下进行硬件的连接或断开连接操作时,我们可以看到硬件的检测或者断开连接的信息.‘dmesg’命令在多数 ...

  3. Anaconda(三)

    五.TensorFlow安装 这一天由于版本问题走了太多弯路.之前用的conda版本是最新的,自带Python3.7.5,装了之后倒是各种包都能装,用命令: pip install xxx conda ...

  4. Django框架 + Djiango安装 + First Djiango + 常用命令

    一.Django框架 MVC框架和MTV框架 参考:https://www.cnblogs.com/taosiyu/p/11260016.html MVC,全名是Model View Controll ...

  5. siglongjmp和sigsetjmp 用法

    1. 引入原因 由于在信号处理期间自动屏蔽了正在被处理的信号,而使用setjmp/longjmp跳出信号处理程序时又不会自动将 信号屏蔽码修改会原来的屏蔽码,从而引起该信号被永久屏蔽. 可以使用sig ...

  6. Nginx - 根据IP分配不同的访问后端

    1. 需求分析 为了在线上环境提供测试分支,规定将某IP转发到测试程序地址.如果是 ngx 直接对外,采用 real_ip 就能够做限制,但是最前端确实一个7层是负载均衡就需要研究一番了. 2. 实践 ...

  7. laravel jwt实践

    laravel版本为5.5 1.使用 composer 安装 composer require tymon/jwt-auth 1.*@rc 2.发布配置文件 # 这条命令会在 config 下增加一个 ...

  8. 《ucore lab1 exercise5》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 题目:实现函数调用堆栈跟踪函数 我们需要在lab1中完成kdebug.c中函数print_stackframe的实现,可以通过函数print_s ...

  9. linux 压缩文件 查找

    zgrep '20190521155553776237' stdout-20190521.log.gz

  10. 2019-7-17 正则表达式和re模块

    一.re模块与正则表达式之间的关系 正则表达式不是python独有的,它是一门独立的技术 所有的编程语言都可以使用正则 但是如果你想在python中使用,你就必须依赖于re模块 正则的官方定义:正则表 ...