Форум русскоязычного сообщества Ubuntu


Считаете, что Ubuntu недостаточно дружелюбна к новичкам?
Помогите создать новое Руководство для новичков!

Автор Тема: Сделать скриншот экрана средствами СИ  (Прочитано 2167 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн aleksey_bakholdin

  • Автор темы
  • Новичок
  • *
  • Сообщений: 3
    • Просмотр профиля
Добрый день! Подскажите как реализовать именно на СИ, спасибо. ???

Оффлайн qub

  • Новичок
  • *
  • Сообщений: 41
    • Просмотр профиля
Re: Сделать скриншот экрана средствами СИ
« Ответ #1 : 13 Июня 2015, 20:16:47 »
Вот GTK2 пример, у меня заработал. Заставить работать код с использованием GTK3 не получается.
#include <gtk/gtk.h>
#include <gdk/gdk.h>

static gboolean save_screenshot(GdkWindow * gdk_window,
                                const gchar * screenshot_path)
{
    GdkPixbuf * pixbuf;
    gint x;
    gint y;
    gint width;
    gint height;
    gint depth;
    gboolean success;

    g_assert(NULL != gdk_window);
    g_assert(NULL != screenshot_path);

    gdk_window_get_geometry(gdk_window, &x, &y, &width, &height, &depth);
    pixbuf = gdk_pixbuf_get_from_drawable(NULL , gdk_window, gdk_colormap_get_system(), 0, 0, 0, 0, width, height);
    if (NULL == pixbuf) {
        g_warning("gdk_pixbuf_get_from_drawable failed.");
        return FALSE;
    }
    success = gdk_pixbuf_save(pixbuf, screenshot_path, "png", NULL, NULL);
    g_object_unref(pixbuf);
    return success;
}

gboolean button_clicked(GtkWidget* widget) {

GdkWindow *root_window;
root_window = gdk_get_default_root_window ();

save_screenshot(root_window, "./1.png");
 
 return TRUE;
}

int main(int argc, char **argv) {

 GtkWidget *window = NULL;
 GtkWidget *button = NULL;
 GtkWidget *fixed = NULL;
 
 gtk_init(&argc, &argv);
 
 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 
 gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
 
 g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
 fixed = gtk_fixed_new();
 
 gtk_container_add(GTK_CONTAINER(window), fixed);
 
 button = gtk_button_new_with_label("Save");
 
 g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), NULL);
 
 gtk_fixed_put(GTK_FIXED(fixed), button, 55, 10);

 gtk_widget_show_all(window);
 
 gtk_main();
 
 return 0;
 
}

Вот пример на Qt, сам я не пробывал собирать данный пример. http://doc.qt.io/qt-5/qtwidgets-desktop-screenshot-example.html
« Последнее редактирование: 13 Июня 2015, 20:21:24 от qub »

Оффлайн aleksey_bakholdin

  • Автор темы
  • Новичок
  • *
  • Сообщений: 3
    • Просмотр профиля
Re: Сделать скриншот экрана средствами СИ
« Ответ #2 : 14 Июня 2015, 02:19:19 »
 :)

Спасибо, направление понял, буду разбираться

Оффлайн f-dzmitry

  • Участник
  • *
  • Сообщений: 168
    • Просмотр профиля
Re: Сделать скриншот экрана средствами СИ
« Ответ #3 : 14 Июня 2015, 14:17:58 »
Вот GTK2 пример, у меня заработал. Заставить работать код с использованием GTK3 не получается.
#include <gtk/gtk.h>
#include <gdk/gdk.h>

static gboolean save_screenshot(GdkWindow * gdk_window,
                                const gchar * screenshot_path)
{
    GdkPixbuf * pixbuf;
    gint x;
    gint y;
    gint width;
    gint height;
    gint depth;
    gboolean success;

    g_assert(NULL != gdk_window);
    g_assert(NULL != screenshot_path);

    gdk_window_get_geometry(gdk_window, &x, &y, &width, &height, &depth);
    pixbuf = gdk_pixbuf_get_from_drawable(NULL , gdk_window, gdk_colormap_get_system(), 0, 0, 0, 0, width, height);
    if (NULL == pixbuf) {
        g_warning("gdk_pixbuf_get_from_drawable failed.");
        return FALSE;
    }
    success = gdk_pixbuf_save(pixbuf, screenshot_path, "png", NULL, NULL);
    g_object_unref(pixbuf);
    return success;
}

gboolean button_clicked(GtkWidget* widget) {

GdkWindow *root_window;
root_window = gdk_get_default_root_window ();

save_screenshot(root_window, "./1.png");
 
 return TRUE;
}

int main(int argc, char **argv) {

 GtkWidget *window = NULL;
 GtkWidget *button = NULL;
 GtkWidget *fixed = NULL;
 
 gtk_init(&argc, &argv);
 
 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 
 gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
 
 g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
 fixed = gtk_fixed_new();
 
 gtk_container_add(GTK_CONTAINER(window), fixed);
 
 button = gtk_button_new_with_label("Save");
 
 g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), NULL);
 
 gtk_fixed_put(GTK_FIXED(fixed), button, 55, 10);

 gtk_widget_show_all(window);
 
 gtk_main();
 
 return 0;
 
}

Вот пример на Qt, сам я не пробывал собирать данный пример. http://doc.qt.io/qt-5/qtwidgets-desktop-screenshot-example.html
А если KDE!
void next(){next();};

Оффлайн qub

  • Новичок
  • *
  • Сообщений: 41
    • Просмотр профиля
Re: Сделать скриншот экрана средствами СИ
« Ответ #4 : 14 Июня 2015, 16:20:46 »
А если KDE!
А что KDE? Будет работать и в KDE.

Оффлайн f-dzmitry

  • Участник
  • *
  • Сообщений: 168
    • Просмотр профиля
Re: Сделать скриншот экрана средствами СИ
« Ответ #5 : 15 Июня 2015, 19:28:26 »
XImage *image; GC graph_ctx;

image = XGetImage (display, default_root_window, 0, 0, 1280, 1024, AllPlanes, ZPixmap);

XPutImage (display, pix, graph_ctx, image, 0, 0, 0, 0, 1280, 1024);
:coolsmiley:
void next(){next();};

Оффлайн qub

  • Новичок
  • *
  • Сообщений: 41
    • Просмотр профиля
Re: Сделать скриншот экрана средствами СИ
« Ответ #6 : 16 Июня 2015, 21:02:03 »
XImage *image; GC graph_ctx;

image = XGetImage (display, default_root_window, 0, 0, 1280, 1024, AllPlanes, ZPixmap);

XPutImage (display, pix, graph_ctx, image, 0, 0, 0, 0, 1280, 1024);
:coolsmiley:
Тоже вариант, действительно работает. Ниже пример я взял с сайта http://stackoverflow.com/questions/8249669/how-do-take-a-screenshot-correctly-with-xlib
Вот пример реализации:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <libpng/png.h>

extern int errno;

int main( void ) {
    Display *display = XOpenDisplay(NULL);
   Window root = DefaultRootWindow(display);

   XWindowAttributes gwa;

   XGetWindowAttributes(display, root, &gwa);
   int width = gwa.width;
   int height = gwa.height;


   XImage *image = XGetImage(display,root, 0,0 , width,height,AllPlanes, ZPixmap);

   unsigned char *array = new unsigned char[width * height * 3];

   unsigned long red_mask = image->red_mask;
   unsigned long green_mask = image->green_mask;
   unsigned long blue_mask = image->blue_mask;

 int code = 0;
   FILE *fp;
   png_structp png_ptr;
   png_infop png_info_ptr;
   png_bytep png_row;

   // Open file
   fp = fopen ("test.png", "wb");
   if (fp == NULL)
     {
       fprintf (stderr, "Could not open file for writing\n");
       code = 1;
     }

   // Initialize write structure
   png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   if (png_ptr == NULL)
     {
       fprintf (stderr, "Could not allocate write struct\n");
       code = 1;
     }

   // Initialize info structure
   png_info_ptr = png_create_info_struct (png_ptr);
   if (png_info_ptr == NULL)
     {
       fprintf (stderr, "Could not allocate info struct\n");
       code = 1;
     }

   // Setup Exception handling
   if (setjmp (png_jmpbuf (png_ptr)))
     {
       fprintf(stderr, "Error during png creation\n");
       code = 1;
     }

   png_init_io (png_ptr, fp);

   // Write header (8 bit colour depth)
   png_set_IHDR (png_ptr, png_info_ptr, width, height,
         8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
         PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

   // Set title
   char *title = "Screenshot";
   if (title != NULL)
     {
       png_text title_text;
       title_text.compression = PNG_TEXT_COMPRESSION_NONE;
       title_text.key = "Title";
       title_text.text = title;
       png_set_text (png_ptr, png_info_ptr, &title_text, 1);
     }

   png_write_info (png_ptr, png_info_ptr);

   // Allocate memory for one row (3 bytes per pixel - RGB)
   png_row = (png_bytep) malloc (3 * width * sizeof (png_byte));

   // Write image data
   int x, y;
   for (y = 0; y < height; y++)
     {
       for (x = 0; x < width; x++)
     {
       unsigned long pixel = XGetPixel (image, x, y);

       unsigned char blue = pixel & blue_mask;
       unsigned char green = (pixel & green_mask) >> 8;
       unsigned char red = (pixel & red_mask) >> 16;
       png_byte *ptr = &(png_row[x*3]);
       ptr[0] = red;
       ptr[1] = green;
       ptr[2] = blue;
     }
       png_write_row (png_ptr, png_row);
     }

   // End write
   png_write_end (png_ptr, NULL);

   // Free
   fclose (fp);
   if (png_info_ptr != NULL) png_free_data (png_ptr, png_info_ptr, PNG_FREE_ALL, -1);
   if (png_ptr != NULL) png_destroy_write_struct (&png_ptr, (png_infopp)NULL);
   if (png_row != NULL) free (png_row);
}

Оффлайн FixNix

  • Участник
  • *
  • Сообщений: 208
    • Просмотр профиля
Re: Сделать скриншот экрана средствами СИ
« Ответ #7 : 17 Июня 2015, 22:36:45 »
Вот GTK2 пример, у меня заработал. Заставить работать код с использованием GTK3 не получается.
Подправил Ваш пример для GTK3:
/* gcc filename.c `pkg-config --cflags --libs gtk+-3.0` -o filename */
#include <gtk/gtk.h>
#include <gdk/gdk.h>

static gboolean save_screenshot(GdkWindow * gdk_window,
                                const gchar * screenshot_path)
{
    GdkPixbuf * pixbuf;
    gint x;
    gint y;
    gint width;
    gint height;
    gboolean success;

    g_assert(NULL != gdk_window);
    g_assert(NULL != screenshot_path);

    gdk_window_get_geometry(gdk_window, &x, &y, &width, &height);
    pixbuf = gdk_pixbuf_get_from_window (gdk_window, x, y, width, height);

    if (NULL == pixbuf) {
        g_warning("failed.");
        return FALSE;
    }
    success = gdk_pixbuf_save(pixbuf, screenshot_path, "png", NULL, NULL);
    g_object_unref(pixbuf);
    return success;
}

gboolean button_clicked(GtkWidget* widget) {

GdkWindow *root_window;
root_window = gdk_get_default_root_window ();

save_screenshot(root_window, "./1.png");
 
 return TRUE;
}

int main(int argc, char **argv) {

 GtkWidget *window = NULL;
 GtkWidget *button = NULL;
 GtkWidget *fixed = NULL;
 
 gtk_init(&argc, &argv);
 
 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 
 gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
 
 g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
 fixed = gtk_fixed_new();
 
 gtk_container_add(GTK_CONTAINER(window), fixed);
 
 button = gtk_button_new_with_label("Save");
 
 g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), NULL);
 
 gtk_fixed_put(GTK_FIXED(fixed), button, 55, 10);

 gtk_widget_show_all(window);
 
 gtk_main();
 
 return 0;
 
}

Если нужно для отдельных окон, вот мой простой пример: https://forum.ubuntu.ru/index.php?topic=261423.0.
ubuntu 16.04 x64 - комп. на работе и ноут дома, Nautilus Nemo (2.8.7) для Unity.
Если хочешь сделать что-то хорошо, сделай это сам.

Оффлайн qub

  • Новичок
  • *
  • Сообщений: 41
    • Просмотр профиля
Re: Сделать скриншот экрана средствами СИ
« Ответ #8 : 18 Июня 2015, 05:38:23 »
Вот GTK2 пример, у меня заработал. Заставить работать код с использованием GTK3 не получается.
Подправил Ваш пример для GTK3:
/* gcc filename.c `pkg-config --cflags --libs gtk+-3.0` -o filename */
#include <gtk/gtk.h>
#include <gdk/gdk.h>

static gboolean save_screenshot(GdkWindow * gdk_window,
                                const gchar * screenshot_path)
{
    GdkPixbuf * pixbuf;
    gint x;
    gint y;
    gint width;
    gint height;
    gboolean success;

    g_assert(NULL != gdk_window);
    g_assert(NULL != screenshot_path);

    gdk_window_get_geometry(gdk_window, &x, &y, &width, &height);
    pixbuf = gdk_pixbuf_get_from_window (gdk_window, x, y, width, height);

    if (NULL == pixbuf) {
        g_warning("failed.");
        return FALSE;
    }
    success = gdk_pixbuf_save(pixbuf, screenshot_path, "png", NULL, NULL);
    g_object_unref(pixbuf);
    return success;
}

gboolean button_clicked(GtkWidget* widget) {

GdkWindow *root_window;
root_window = gdk_get_default_root_window ();

save_screenshot(root_window, "./1.png");
 
 return TRUE;
}

int main(int argc, char **argv) {

 GtkWidget *window = NULL;
 GtkWidget *button = NULL;
 GtkWidget *fixed = NULL;
 
 gtk_init(&argc, &argv);
 
 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 
 gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
 
 g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
 fixed = gtk_fixed_new();
 
 gtk_container_add(GTK_CONTAINER(window), fixed);
 
 button = gtk_button_new_with_label("Save");
 
 g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), NULL);
 
 gtk_fixed_put(GTK_FIXED(fixed), button, 55, 10);

 gtk_widget_show_all(window);
 
 gtk_main();
 
 return 0;
 
}

Если нужно для отдельных окон, вот мой простой пример: https://forum.ubuntu.ru/index.php?topic=261423.0.
Спасибо, пригодится.

 

Страница сгенерирована за 0.033 секунд. Запросов: 26.