天天看點

GTK進階學習:GTK實作截圖功能( 可以指定截圖範圍 )

按按鈕截圖,圖檔儲存在目前路徑為“save.png”:

#include <gtk/gtk.h>
#include <cairo.h>

/********************************************************
功能:指定視窗區域截圖,需要包含頭檔案cairo.h 
參數:
  area:     需要截圖的視窗指針
  x, y, w, h: 截圖的範圍
  path_name:  儲存圖檔的路徑名字,如 "./image/test.png"
傳回值:截圖的圖檔pixbuf,失敗傳回NULL
*********************************************************/
GdkPixbuf *screenshot(GtkWidget *area, int x, int y, int w, int h, char *path_name)
{
  GdkPixbuf *pixbuf = NULL;
  pixbuf = gdk_pixbuf_get_from_drawable(NULL, area->window, NULL,
            x, y, 0, 0, w, h);  //取到矩形區域圖檔
  if(NULL == pixbuf){  // 如果沒有擷取成功,結束函數
    printf("gdk_pixbuf_get_from_drawable failed\n");
    return  NULL;
  }

  cairo_surface_t *surface = NULL;
  cairo_t *cr;
  // 建立一個 Cairo 外觀 
  surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, w, h) ;
  // 一個 Cairo 環境
  cr = cairo_create( surface) ; 
  
  // 給cr繪圖
  gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
  cairo_paint(cr);
  
  // 截圖
  cairo_surface_write_to_png ( surface, path_name ) ;
  
  
  // 釋放相應資源
  cairo_destroy(cr) ;
  cairo_surface_destroy( surface) ;
  //g_object_unref(pixbuf);
  
  return pixbuf;
}    




/* 功能:  設定背景圖
 * widget: 主視窗
 * w, h:   圖檔的大小
 * path:  圖檔路徑
 */
void chang_background(GtkWidget *widget, int w, int h, const gchar *path)
{
  gtk_widget_set_app_paintable(widget, TRUE);    //允許視窗可以繪圖
  gtk_widget_realize(widget);  

  /* 更改背景圖時,圖檔會重疊
   * 這時要手動調用下面的函數,讓視窗繪圖區域失效,産生視窗重繪制事件(即 expose 事件)。
   */
  gtk_widget_queue_draw(widget);

  GdkPixbuf *src_pixbuf = gdk_pixbuf_new_from_file(path, NULL);  // 建立圖檔資源對象
  // w, h是指定圖檔的寬度和高度
  GdkPixbuf *dst_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, w, h, GDK_INTERP_BILINEAR);

  GdkPixmap *pixmap = NULL;

  /* 建立pixmap圖像; 
   * NULL:不需要蒙版; 
   * 123: 0~255,透明到不透明
   */
  gdk_pixbuf_render_pixmap_and_mask(dst_pixbuf, &pixmap, NULL, 128);
  // 通過pixmap給widget設定一張背景圖,最後一個參數必須為: FASLE
  gdk_window_set_back_pixmap(widget->window, pixmap, FALSE);

  // 釋放資源
  g_object_unref(src_pixbuf);
  g_object_unref(dst_pixbuf);
  g_object_unref(pixmap);
}

// 按鈕"clicked"信号的處理函數
void deal_button(GtkWidget *w, gpointer data)
{
  // 截圖,指定視窗區域為(0, 0, 300, 300),在目前路徑儲存圖檔為save.png
  screenshot(GTK_WIDGET(data), 0, 0, 300, 300, "save.png");
}

int main( int argc, char *argv[])
{
  gtk_init(&argc, &argv);

  //主視窗操作
  GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  gtk_window_set_title(GTK_WINDOW(window), "設定視窗背景圖");
  gtk_widget_set_size_request(window, 500, 450);

  chang_background(window, 500, 400, "image.jpg");  // 設定視窗背景圖
  
  GtkWidget *table = gtk_table_new(3, 3, TRUE);   // 表格布局,3行3列
  gtk_container_add(GTK_CONTAINER(window), table); // 容器加入視窗

  // 截圖按鈕
  GtkWidget *button = gtk_button_new_with_label("截圖");
  gtk_table_attach_defaults(GTK_TABLE(table), button, 2, 3, 2, 3); 
  // 處理按鈕的信号,把視窗指針window傳給回調函數deal_button()
  g_signal_connect(button, "clicked", G_CALLBACK(deal_button), window);
  

  gtk_widget_show_all(window); // 顯示所有部件

  gtk_main();
  
  return 0;
}      

程式運作效果圖:

GTK進階學習:GTK實作截圖功能( 可以指定截圖範圍 )

截出來的圖檔:

GTK進階學習:GTK實作截圖功能( 可以指定截圖範圍 )