zoukankan      html  css  js  c++  java
  • 基于gtk的imshow:用stb_image读取图像并用gtk显示

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

  • 相关阅读:
    玩转二叉树(二叉树的遍历)
    树的遍历(25分)
    树的遍历(25分)
    Java并发框架——AQS之怎样使用AQS构建同步器
    利用jsonrpc技术包装uiautomator
    HDU2059 龟兔赛跑 【DP】
    Android 利用WebViewJavascriptBridge 实现js和java的交互(一)
    玩转web之json(五)---将表单通过serialize()方法获取的值转成json
    网络暴力信号:你家的青少年是受害者或加害者吗?
    greenplum全量恢复gprecoverseg -F出现Unable to connect to database时的相关分析及解决方法
  • 原文地址:https://www.cnblogs.com/zjutzz/p/10960235.html
Copyright © 2011-2022 走看看