在前面一篇,已经能够基于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:

  1. #include <gtk/gtk.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #include "fc_image.h"
  5. void fc_bgr_to_rgb(FcImage* im) {
  6. if (im==NULL) return;
  7. if (im->c<=0 || im->h<=0 || im->w==0) return;
  8. assert(im->c==3);
  9. int num_pixel = im->c * im->h * im->w;
  10. unsigned char t;
  11. for(int i=0; i<num_pixel; i+=3) {
  12. t = im->data[i];
  13. im->data[i] = im->data[i+2];
  14. im->data[i+2] = t;
  15. }
  16. }
  17. int main (int argc, char *argv[])
  18. {
  19. const char* im_pth = "/home/zz/work/libfc/imgs/fruits.jpg";
  20. FcImage im = fc_load_image(im_pth);
  21. fc_bgr_to_rgb(&im);
  22. GtkWidget *window;
  23. GtkWidget* image;
  24. gtk_init (&argc, &argv);
  25. window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  26. GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data (im.data, GDK_COLORSPACE_RGB,
  27. FALSE, 8, im.w, im.h, im.w*3, NULL, NULL);
  28. gtk_window_set_title (GTK_WINDOW (window), "Image Viewer");
  29. g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
  30. image = gtk_image_new_from_pixbuf (pixbuf);
  31. gtk_container_add(GTK_CONTAINER (window), image);
  32. gtk_widget_show_all (window);
  33. gtk_main ();
  34. return 0;
  35. }

简单封装

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

  1. #include <gtk/gtk.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #include "fc_image.h"
  5. void fc_copy_bgr_to_rgb(const FcImage* src, FcImage* dst) {
  6. if (src==NULL) return;
  7. if (dst==NULL) return;
  8. assert(src!=dst);
  9. assert(src->data!=NULL);
  10. assert(dst->data!=NULL);
  11. assert(src->data!=dst->data);
  12. assert(src->c>=0 && src->h>=0 && src->c==3);
  13. assert(src->c>=0 && src->h>=0 && src->c==3);
  14. assert(src->c==dst->c && src->h==dst->h && src->w==dst->w);
  15. int num_pixel = src->c * src->h * src->w;
  16. for(int i=0; i<num_pixel; i+=3) {
  17. dst->data[i] = src->data[i+2];
  18. dst->data[i+1] = src->data[i+1];
  19. dst->data[i+2] = src->data[i];
  20. }
  21. }
  22. FcImage fc_make_image(int w, int h, int c)
  23. {
  24. FcImage out;
  25. out.w = w;
  26. out.h = h;
  27. out.c = c;
  28. out.data = (unsigned char*)calloc(h*w*c, sizeof(float));
  29. return out;
  30. }
  31. void gtk_show_image_v3(const FcImage* im, const char* title)
  32. {
  33. FcImage im_rgb = fc_make_image(im->w, im->h, im->c); //?? check this dimensions
  34. fc_copy_bgr_to_rgb(im, &im_rgb);
  35. GtkWidget *window;
  36. GtkWidget* image;
  37. gtk_init (NULL, NULL);
  38. window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  39. GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data (im_rgb.data, GDK_COLORSPACE_RGB,
  40. FALSE, 8, im_rgb.w, im_rgb.h, im_rgb.w*3, NULL, NULL);
  41. gtk_window_set_title (GTK_WINDOW (window), title);
  42. g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
  43. image = gtk_image_new_from_pixbuf (pixbuf);
  44. gtk_container_add(GTK_CONTAINER (window), image);
  45. gtk_widget_show_all (window);
  46. gtk_main ();
  47. }
  48. int main (int argc, char *argv[])
  49. {
  50. const char* im_pth = "/home/zz/work/libfc/imgs/fruits.jpg";
  51. FcImage im = fc_load_image(im_pth);
  52. const char* title = "fruits";
  53. gtk_show_image_v3(&im, title);
  54. return 0;
  55. }

其他注意

使用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. Java读取CSV数据并写入txt文件

    读取CSV数据并写入txt文件 package com.vfsd; import java.io.BufferedWriter; import java.io.File; import java.io ...

  2. promise简单实现

    function isFunction(fn){ return Object.prototype.toString.call(fn) === '[object Function]'; } let ST ...

  3. 工控随笔_25_西门子TIA 博图V14.SP1安装报错,授权错误

    前面有一篇文章说过西门子的软件安装的时候太麻烦,很容易出现错误. 但是有些错误在安装的时候却没有关系,例如下面的错误. 如上图所示,安装已经到最后一步,总结前面的修改系统组态已经打勾(✔) ,而且提示 ...

  4. svg轻松实现文字水印

    1. 水印图片生成采用svg,这样可以运行时生成名字或其他信息的图片 svg模板 <svg xmlns="http://www.w3.org/2000/svg" xmlns: ...

  5. visual studio ------- 更改字体和背景颜色

    1.打开vs   点击工具  选择选项 2.想要更换主题的也可以更换主题, 3.更改字体 4.更改为护眼小背景   参数为    85   123  205 ee

  6. 025 SSM综合练习01--数据后台管理系统--功能介绍及数据库表

    1.功能介绍 (1)环境搭建 主要讲解maven工程搭建,以及基于oracle数据库的商品表信息,并完成SSM整合.(2)商品查询 基于SSM整合基础上完成商品查询,要掌握主面页面main.jsp及商 ...

  7. fineui grid自定义选项框 带全选

    为什么要写这功能? 1 当你用可编辑列的时候,是不能用选择框的,这是ext设定的. 2 如果有不允许选择行,默认的选择框是没有这个功能的.   参考: 遍历asp.net控件 http://fineu ...

  8. Oracle RAC 创建实例出错(非+DATA目录)的简单处理

    今天进行oracle的rac测试 发现开发同事没有写好 oracle rac的设置.  创建完之后就会报错了 因为自己对oracle 的RAC 不太熟悉 不太会用.. 所以用 一个比较简单的办法. a ...

  9. 设计模式 AOP,OOP

    AOP.OOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想. 简单说,AOP面向动词领域,OOP面向名词领域 AOP: (Aspect Oriented Programming) 面向切面编 ...

  10. c++项目经验分享

    1.C++的const比C语言#define更好的原因? 首先,它能够明确指定类型,有类型检查功能. 其次,可以使用C++的作用域规则将定义限制在特定的函数[常函数]或文件中. 第三,可以将const ...