Forum de la communauté SFML

Aide => Graphique => Discussion démarrée par: LD_FLO le Avril 12, 2015, 07:38:50 pm

Titre: LoadFromMemory d'une bitmap
Posté par: LD_FLO le Avril 12, 2015, 07:38:50 pm
Bonjour, j'ai implémenté la possibilité de pouvoir utiliser le presse papier dans mon application (pour les images). Pour l'exportation (application vers extérieur) aucun problème, mais pour l'importation je me pose des questions:

Qu'est ce que doit lire la fonction LoadFromMemory exactement ? Est-ce le tableau des pixels de l'image (son contenu), ou bien l'image entière (avec le header) ?
Titre: Re : LoadFromMemory d'une bitmap
Posté par: Laurent le Avril 12, 2015, 10:33:34 pm
Je pense que la documentation

Citer
Load the image from a file in memory.

The supported image formats are bmp, png, tga, jpg, gif, psd, hdr and pic.

... ainsi que le tutoriel

Citer
Vous pouvez aussi charger une image depuis un fichier en mémoire (loadFromMemory)

... ainsi que potentiellement le fait de prendre 2 minutes pour essayer ;) tendent assez clairement vers la réponse. Non ?
Titre: Re : LoadFromMemory d'une bitmap
Posté par: LD_FLO le Avril 12, 2015, 10:50:30 pm
J'ai ma réponse, mais c'était plutôt laborieux.
J'en profite pour poster mon code.
Deux fonctions: une pour stocker une image dans le presse-papier, l'autre pour charger une image depuis le presse papier.
Compatible en exportation vers GIMP, Paint, et beaucoup d'autres, mais pas Photoshop...
Compatible en importation depuis presque tout le monde, mais avec parfois des problèmes de transparence.

En attente d'amélioration.
#include <windows.h>

int copy_to_clipboard(sf::Image *image)
{
        sf::Uint8* buffer;
        HGLOBAL clipbuffer;
       
        int buflen = image->getSize().x*image->getSize().y*4;
       
        //Header
        BITMAPINFOHEADER header;
        header.biSize = sizeof(BITMAPINFOHEADER);
        header.biWidth = image->getSize().x;
        header.biHeight = -image->getSize().y;
        header.biPlanes = 1;
        header.biBitCount = 32;
        header.biCompression = BI_RGB;
        header.biSizeImage = 0;
        header.biXPelsPerMeter = 2835;
        header.biYPelsPerMeter = 2835;
        header.biClrUsed = 0;
        header.biClrImportant = 0;
       
        if (!OpenClipboard(NULL)) {return 1;}

        EmptyClipboard();
        clipbuffer = GlobalAlloc(GMEM_MOVEABLE, buflen + sizeof(BITMAPINFOHEADER));

        if ((buffer = (sf::Uint8*)GlobalLock(clipbuffer)) == NULL)
        {
                GlobalUnlock(clipbuffer);
                CloseClipboard();
                return 2;
        }

        memcpy(buffer, &header, sizeof(BITMAPINFOHEADER));
        memcpy(buffer + sizeof(BITMAPINFOHEADER), image->getPixelsPtr(), buflen);
       
        GlobalUnlock(clipbuffer);
        SetClipboardData(CF_DIB, clipbuffer);

        CloseClipboard();
        GlobalFree(clipbuffer);
        return 0;
}

sf::Image* get_clipboard()
{
        sf::Uint8* buffer;
        HANDLE hData;

        if (!OpenClipboard(NULL)) {return NULL;}
        if ((hData = GetClipboardData(CF_DIB)) == NULL) {return NULL;}
        if ((buffer = (sf::Uint8*)GlobalLock(hData)) == NULL) {return NULL;}
        GlobalUnlock(hData);
        CloseClipboard();

        int* SIZE_HEADER = (int*)(buffer);
        int* NBR_BIT = (int*)(buffer+14);
        int* width = (int*)(buffer+4);
        int* height = (int*)(buffer+8);

        int buflen = (*width)*std::abs(*height)*(*NBR_BIT/8) + *SIZE_HEADER;
        sf::Uint8* buffer2 = new sf::Uint8[buflen+sizeof(BITMAPFILEHEADER)];

        //Header
        BITMAPFILEHEADER header;
        header.bfType = 0x4D42;
        header.bfSize = 0;
        header.bfReserved1 = 0;
        header.bfReserved2 = 0;
        header.bfOffBits = sizeof(BITMAPFILEHEADER) + *SIZE_HEADER;

        memcpy(buffer2, &header, sizeof(BITMAPFILEHEADER));
        memcpy(buffer2 + sizeof(BITMAPFILEHEADER), buffer, buflen);

        sf::Image* image = new sf::Image();
        image->loadFromMemory(buffer2, buflen+sizeof(BITMAPFILEHEADER));

        return image;
}