abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
eParkomat, startup z ČR, postoupil mezi finalisty evropského akcelerátoru ChallengeUp!
Robot na pivo mu otevřel dveře k opravdovému byznysu
Internet věcí: Propojený svět? Už se to blíží...
dnes 16:24 | Nová verze

Byla vydána Mageia 5.1. Jedná se o první opravné vydání verze 5, jež vyšla v červnu loňského roku (zprávička). Uživatelům verze 5 nepřináší opravné vydání nic nového, samozřejmě pokud pravidelně aktualizují. Vydání obsahuje všechny aktualizace za posledního téměř půldruhého roku. Mageia 5.1 obsahuje LibreOffice 4.4.7, Linux 4.4.32, KDE4 4.14.5 nebo GNOME 3.14.3.

Ladislav Hagara | Komentářů: 0
dnes 13:42 | Pozvánky

V Praze probíhá konference Internet a Technologie 16.2, volné pokračování jarní konference sdružení CZ.NIC. Konferenci lze sledovat online na YouTube. K dispozici je také archiv předchozích konferencí.

Ladislav Hagara | Komentářů: 0
včera 22:44 | Komunita

Joinup informuje, že Mnichov používá open source groupware Kolab. V srpnu byl dokončen dvouletý přechod na toto řešení. V provozu je asi 60 000 poštovních schránek. Nejenom Kolabu se věnoval Georg Greve ve své přednášce Open Source: the future for the European institutions (SlideShare) na konferenci DIGITEC 2016, jež proběhla v úterý 29. listopadu v Bruselu. Videozáznam přednášek z hlavního sálu je ke zhlédnutí na Livestreamu.

Ladislav Hagara | Komentářů: 15
včera 15:30 | Zajímavý projekt

Společnost Jolla oznámila v příspěvku Case study: Sailfish Watch na svém blogu, že naportovala Sailfish OS na chytré hodinky. Využila a inspirovala se otevřeným operačním systémem pro chytré hodinky AsteroidOS. Použita je knihovna libhybris. Ukázka ovládání hodinek na YouTube.

Ladislav Hagara | Komentářů: 8
včera 14:15 | Nová verze

Byla vydána verze 7.1.0 skriptovacího jazyka PHP používaného zejména k vývoji dynamických webových stránek. Jedná se o první stabilní verzi nejnovější větvě 7.1. Přehled novinek v dokumentaci. Podrobnosti v ChangeLogu. K dispozici je také příručka pro přechod z PHP 7.0.x na PHP 7.1.x.

Ladislav Hagara | Komentářů: 2
včera 12:55 | Nová verze

Google Chrome 55 byl prohlášen za stabilní. Nejnovější stabilní verze 55.0.2883.75 tohoto webového prohlížeče přináší řadu oprav a vylepšení (YouTube). Opraveno bylo také 36 bezpečnostních chyb. Mariusz Mlynski si například vydělal 22 500 dolarů za 3 nahlášené chyby (Universal XSS in Blink).

Ladislav Hagara | Komentářů: 4
včera 11:55 | Pozvánky

Máte rádi svobodný software a hardware nebo se o nich chcete něco dozvědět? Přijďte na 135. sraz spolku OpenAlt, který se bude konat ve čtvrtek 8. prosince od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Sraz bude tentokrát tématický. Bude retro! K vidění budou přístroje jako Psion 5mx nebo Palm Z22. Ze svobodného hardwaru pak Openmoko nebo čtečka WikiReader. Přijďte se i vy pochlubit svými legendami, nebo alespoň na pivo. Moderní hardware má vstup samozřejmě také povolen.

xkucf03 | Komentářů: 0
včera 00:10 | Nová verze

Byla vydána verze 3.2 svobodného systému pro detekci a prevenci průniků a monitorování bezpečnosti počítačových sítí Suricata. Z novinek lze zmínit například podporu protokolů DNP3 a CIP/ENIP, vylepšenou podporu TLS a samozřejmě také aktualizovanou dokumentaci.

Ladislav Hagara | Komentářů: 0
1.12. 21:00 | Nová verze

Byla vydána beta verze Linux Mintu 18.1 s kódovým jménem Serena. Na blogu Linux Mintu jsou hned dvě oznámení. První o vydání Linux Mintu s prostředím MATE a druhé o vydání Linux Mintu s prostředím Cinnamon. Stejným způsobem jsou rozděleny také poznámky k vydání (MATE, Cinnamon) a přehled novinek s náhledy (MATE, Cinnamon). Linux Mint 18.1 bude podporován až do roku 2021.

Ladislav Hagara | Komentářů: 0
1.12. 16:42 | Nová verze

Byl vydán Devuan Jessie 1.0 Beta 2. Jedná se o druhou beta verzi forku Debianu bez systemd představeného v listopadu 2014 (zprávička). První beta verze byla vydána v dubnu letošního roku (zprávička). Jedna z posledních přednášek věnovaných Devuanu proběhla v listopadu na konferenci FSCONS 2016 (YouTube, pdf).

Ladislav Hagara | Komentářů: 0
Kolik máte dat ve svém domovském adresáři na svém primárním osobním počítači?
 (32%)
 (24%)
 (29%)
 (7%)
 (5%)
 (3%)
Celkem 767 hlasů
 Komentářů: 50, poslední 29.11. 15:50
Rozcestník
Reklama

Dotaz: Screenshot obrazovky C/C++

25.2. 22:09 Marecek
Screenshot obrazovky C/C++
Přečteno: 809×

Ahoj, potreboval bych pomoct navect na smer, chtel bych pod linuxem delat screenshot obrazovky v C/C++ a presnaset to po siti na druhy stroj, presnos po LAN uz mam vyresen (klient-server) pres sockety v C, je to tedy dost pracne, ale funguje to. (pokud by nekdo dal tip i na nejake knihovny co usnadnuji praci se sockety nebudu se zlobit), ted mi vrta hlavou jak udelat ten screenshot, treba ho delat 5x za sekundu.

Dekuji. Marecek

Odpovědi

25.2. 22:44 mimi.vx | skóre: 37 | blog: Mimi.VX | Praha
Rozbalit Rozbalit vše Re: Screenshot obrazovky C/C++

koukni na imlib2

USE="-gnome -kde";turris
27.2. 12:34 Marecek
Rozbalit Rozbalit vše Re: Screenshot obrazovky C/C++

Diky, docela zajimava knihovna.

Jendа avatar 26.2. 11:23 Jendа | skóre: 73 | blog: Výlevníček | JO70FB
Rozbalit Rozbalit vše Re: Screenshot obrazovky C/C++
Co na to spustit externí program (scrot, import, …) a nechat si data vypsat v nějakém hezkém formátu (PPM) na jeho stdout?
26.2. 19:29 Jardík
Rozbalit Rozbalit vše Re: Screenshot obrazovky C/C++
xcb_connect, pak xcb_get_setup, tam najdeš screen a id 'root' okna, jeho velikost a jeho visual (což je něco jako jaká je barevná hloubka a formát dat. Pak přes SHM utvoříš blok paměti a pošleš xkám request na kopii okna to tý bitmapy. Až to udělá, pošle ti info, že je hotovo, a můžeš to poslat přes socket.
27.2. 12:36 Marecek
Rozbalit Rozbalit vše Re: Screenshot obrazovky C/C++

Joo, to by mohlo byt ono, prostuduji to.

Ja zacal studovat nejaky opensource grabber obrazovaky, ale je to prilis mnoho kodu nez izoluji to co hledam.

Dekuji. M

27.2. 20:45 Jardík
Rozbalit Rozbalit vše Re: Screenshot obrazovky C/C++
Není to dokonalé, možná tam chybí někde chybové kontroly, možná je tam někde memory leak, ale nechtělo se mi s tím dělat moc dlouho. V komentáři je označeno místo, kde zpracovat výsledná data.
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>
#include <xcb/shm.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <sys/ipc.h>
#include <sys/shm.h>


enum {
    SCR_ERR_OK,
    SCR_ERR_CONNECTION_FAIL,
    SCR_ERR_CONNECTION_ERR,
    SCR_ERR_INVALID_SCREEN,
    SCR_ERR_SHM_NOT_SUPPORTED,
    SCR_ERR_INVALID_VISUAL,
    SCR_ERR_INVALID_PIXMAP_FORMAT,
    SCR_ERR_UNSUPPORTED_VISUAL,
    SCR_ERR_IMAGE_EMPTY,
    SCR_ERR_IMAGE_TOO_LARGE,
    
    SCR_ERR_SHMGET_FAILED,
    SCR_ERR_SHM_ATTACH_FAILED,
    SCR_ERR_GET_IMAGE_FAILED,
    SCR_ERR_GET_IMAGE_RACE_CONDITION
};

struct screenshoter
{
    xcb_connection_t *con;
    xcb_setup_t const *setup;
    xcb_screen_t *screen;
    int screen_num;

    xcb_depth_t const* depth;
    xcb_visualtype_t const* visual;
    xcb_format_t const* pixformat;

    xcb_query_extension_reply_t const* shm_ext;

    xcb_shm_seg_t shm_seg;

    struct {
        unsigned char *data;
        size_t stride, size;
    } image;
};

int receive_screenshot(struct screenshoter *scr)
{
    xcb_shm_get_image_cookie_t img_ck = xcb_shm_get_image(scr->con, scr->screen->root,
            0, 0, scr->screen->width_in_pixels, scr->screen->height_in_pixels,
            UINT32_MAX, XCB_IMAGE_FORMAT_XY_PIXMAP, scr->shm_seg, 0);
    xcb_generic_error_t *err = NULL;
    xcb_shm_get_image_reply_t *img_rep = xcb_shm_get_image_reply(scr->con, img_ck, &err);
    if (!img_rep) {
        if (err) free(err);
        return SCR_ERR_GET_IMAGE_FAILED;
    }

    if (img_rep->size != scr->image.size ||
            img_rep->visual != scr->screen->root_visual ||
            img_rep->depth != scr->depth->depth)
    {
        free(img_rep);
        return SCR_ERR_GET_IMAGE_RACE_CONDITION;
    }

    free(img_rep);
    return 0;
}

int create_shm_seg_and_image(struct screenshoter *scr)
{
    // check if sreen has non-zero dimensions
    if (scr->screen->width_in_pixels == 0 ||
            scr->screen->height_in_pixels == 0)
        return SCR_ERR_IMAGE_EMPTY;

    // XCB doesn't run on platforms with non-8bit char, so char is 8bits
    // We only support depth, bits_per_pixel and scanline_pad that is multiple
    // of whole bytes
    //
    // NOTE: shm extension seems to return packed image data, bits_per_pixel and scanline_pad
    //       are not used
    if (scr->depth->depth % 8 != 0)
        return SCR_ERR_UNSUPPORTED_VISUAL;

    size_t bytes_per_pixel = scr->depth->depth / 8;

    // Calculate stride, first multiply width by bytes_per_pixel
    size_t stride = scr->screen->width_in_pixels;
    if (SIZE_MAX / stride < bytes_per_pixel)
        return SCR_ERR_IMAGE_TOO_LARGE;
    stride *= bytes_per_pixel;

    // now multiply by height, to get image size in bytes
    scr->image.stride = stride;
    if (SIZE_MAX / stride < scr->screen->height_in_pixels)
        return SCR_ERR_IMAGE_TOO_LARGE;
    scr->image.size = stride * scr->screen->height_in_pixels;

    int shmid = shmget(IPC_PRIVATE, scr->image.size, IPC_CREAT | 0777);
    if (shmid == -1)
        return SCR_ERR_SHMGET_FAILED;

    scr->image.data = shmat(shmid, NULL, 0);
    if (scr->image.data == (void*)-1) {
        shmctl(shmid, IPC_RMID, NULL);
        return SCR_ERR_SHM_ATTACH_FAILED;
    }

    // Generate shm segment id
    scr->shm_seg = xcb_generate_id(scr->con);
    // attach our file to it, use checked call so we can block for reply
    xcb_void_cookie_t attach_ck = xcb_shm_attach_checked(scr->con,
            scr->shm_seg, shmid, 0);
    // wait for reply
    xcb_generic_error_t *attach_err = xcb_request_check(scr->con, attach_ck);
    // we don't need shmid anymore after the request was processed by X
    shmctl(shmid, IPC_RMID, NULL);
    // check attach error
    if (attach_err) {
        free(attach_err);
        shmdt(scr->image.data);
        return SCR_ERR_SHM_ATTACH_FAILED;
    }

    return 0;
}

void free_shm_seg_and_image(struct screenshoter *scr)
{
    xcb_shm_detach(scr->con, scr->shm_seg);
    shmdt(scr->image.data);
}

int find_default_screen(struct screenshoter *scr)
{
    if (scr->screen_num < 0)
        return SCR_ERR_INVALID_SCREEN;
    
    xcb_screen_iterator_t iter = xcb_setup_roots_iterator(scr->setup);
    for (int i = 0; i < scr->screen_num; ++i) {
        if (iter.rem == 0)
            return SCR_ERR_INVALID_SCREEN;
        xcb_screen_next(&iter);
    }
    scr->screen = iter.data;
    return 0;
}

int detect_root_visual(struct screenshoter *scr)
{
    xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(scr->screen);
    for (;;) {
        xcb_depth_t const *depth = depth_iter.data;
        int visuals_len = xcb_depth_visuals_length(depth);
        if (visuals_len <= 0)
            break;
        xcb_visualtype_t const *visuals = xcb_depth_visuals(depth);

        for (int i = 0; i < visuals_len; ++i) {
            if (visuals[i].visual_id == scr->screen->root_visual) {
                scr->depth = depth;
                scr->visual = &visuals[i];
                return 0;
            }
        }

        if (depth_iter.rem == 0)
            break;
        xcb_depth_next(&depth_iter);
    }

    return SCR_ERR_INVALID_VISUAL;
}

int detect_pixmap_format(struct screenshoter *scr)
{
    int formats_len = xcb_setup_pixmap_formats_length(scr->setup);
    if (formats_len > 0) {
        xcb_format_t const *formats = xcb_setup_pixmap_formats(scr->setup);
        for (int i = 0; i < formats_len; ++i) {
            if (formats[i].depth == scr->depth->depth) {
                scr->pixformat = &formats[i];
                return 0;
            }
        }
    }
    return SCR_ERR_INVALID_PIXMAP_FORMAT;
}

int get_screenshot(void)
{
    struct screenshoter scr;
    int err = 0;

    // connect
    scr.con = xcb_connect(NULL, &scr.screen_num);
    if (!scr.con)
        return SCR_ERR_CONNECTION_FAIL;

    // check errors
    if (xcb_connection_has_error(scr.con)) {
        err = SCR_ERR_CONNECTION_ERR;
        goto retDisconnect;
    }

    // get setup and prefetch shm extension
    scr.setup = xcb_get_setup(scr.con);
    xcb_prefetch_extension_data(scr.con, &xcb_shm_id);
    xcb_flush(scr.con);

    // find screen
    err = find_default_screen(&scr);
    if (err != 0)
        goto retDisconnect;

    // detect visual
    err = detect_root_visual(&scr);
    if (err != 0)
        goto retDisconnect;

    // and pixmap format for root depth
    err = detect_pixmap_format(&scr);
    if (err != 0)
        goto retDisconnect;

    // get shm extension
    scr.shm_ext = xcb_get_extension_data(scr.con, &xcb_shm_id);
    if (!scr.shm_ext->present) {
        err = SCR_ERR_SHM_NOT_SUPPORTED;
        goto retDisconnect;
    }

    // create shm segment
    err = create_shm_seg_and_image(&scr);
    if (err != 0)
        goto retDisconnect;

    err = receive_screenshot(&scr);
    if (err == 0) {
        // TODO: process image data here

        // Image data is in scr.image.data, its bytesize is in scr.image.size,
        // its stride bytesize is in scr.image.stride, its width is in
        // scr.screen->width_in_pixels, height in scr.screen->height_in_pixels,
        // depth (in bits) is in scr.depth->depth. Visual format is in
        // scr.visual (red_mask, green_mask, blue_mask). Image data byteorder is
        // in scr.setup->image_byte_order
    }

    free_shm_seg_and_image(&scr);
    xcb_flush(scr.con);
retDisconnect:
    xcb_disconnect(scr.con);
    return err;
}


int main()
{
    int err = get_screenshot();
    fprintf(stderr, "err = %d\n", err);

    return 0;
}

1.3. 12:13 Marecek
Rozbalit Rozbalit vše Re: Screenshot obrazovky C/C++

To je super, zacina mi to pozvolna "tapat", z ceho to je vykostene (pokud z neceho vetsiho) ?

Marecek

2.3. 12:19 Jardík
Rozbalit Rozbalit vše Re: Screenshot obrazovky C/C++
Né, napsal jsem to sám podle dokumentace k xcb. Je to v public domain, můžeš si s tém dělat, co chceš.
2.3. 12:24 Jardík
Rozbalit Rozbalit vše Re: Screenshot obrazovky C/C++
Jinak komentáře jsou občas mimo, já to pak editoval a nějaké jsem nezměnil. Třeba místo shmget() jsem tam měl memfd_create(), ale pak jsem zjistil, že je to docela nový syscall a že ani není wrapper v glibc, co je v ubuntu 15.10 no tomhle pc, tak jsem to na poslední chvíli měnil a snad nenasekal moc chyb.
2.3. 22:03 jkkjflsj
Rozbalit Rozbalit vše Re: Screenshot obrazovky C/C++
Nejsem si úplně jistý, jak moc je myšlena otázka vážně, případně jak moc vážně jsou myšlené odpovědi. Nicméně snadné řešení jak screnshotů tak socketů poskytuje kde jaká knihovna. Mě osobně se pohodlně pracuje s wxWidgets.

Pokud mermomocí vyžadujete jen tu nejzákladnější (xlib), pak mě příjde odpověď How do take a screenshot correctly with xlib? vyčerpávající. Člověk může být akorát na rozpacích z formátu do kterého se obrázek ukládá.

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267   www.czech-server.cz
© 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.