12 votes

Gdiplus::Bitmap en tableau BYTE?

Voici ma tentative (mélange moche de GDI+ et GDI...)

// ...
BYTE               pixels[BMP_WIDTH * BMP_HEIGHT * BMP_BPP];
HBITMAP            hBitmap;
Gdiplus::Bitmap    cBitmap(BMP_WIDTH, BMP_HEIGHT, PixelFormat32bppRGB);
Gdiplus::Graphics  cGraphics(&cBitmap);
Gdiplus::Pen       cPen(Gdiplus::Color(255, 255, 0, 0));

cGraphics.DrawRectangle(&cPen, 0, 0, cBitmap.GetWidth() - 1, cBitmap.GetHeight() - 1);

// et là ça devient vraiment moche, j'aimerais changer cela...
cBitmap.GetHBITMAP(Gdiplus::Color(255, 255, 255), &hBitmap);
GetBitmapBits(hBitmap, sizeof(pixels), pixels);
// ...

Quelqu'un m'a dit d'utiliser LockBits mais je n'ai vraiment pas compris comment. J'ai essayé, mais j'ai échoué donc je ne vais pas poster cette tentative non plus.

7voto

Kirill V. Lyadvinsky Points 47627

Vous pourriez utiliser Bitmap::LockBits pour accéder à un tableau de données brut. Ici vous pouvez lire sur comment utiliser Bitmap::LockBits.

7voto

SaeidMo7 Points 449

Voici quelque chose que j'ai écrit qui renvoie un vecteur de vecteurs (les vecteurs contenus représentant des colonnes de pixels dans l'image) lorsqu'on lui passe un chemin de fichier :

#include 
std::vector> getPixels(const wchar_t *filename, int &width, int &height) {
    Gdiplus::Bitmap bitmap(filename);

    //Transmettre la largeur et la hauteur, car elles sont utiles pour accéder aux pixels dans le vecteur de vecteurs.
    width = bitmap.GetWidth();
    height = bitmap.GetHeight();

    auto *bitmapData = new Gdiplus::BitmapData;

    //Verrouiller tout le bitmap pour que nous puissions facilement lire les données des pixels.
    Gdiplus::Rect rect(0, 0, width, height);
    bitmap.LockBits(&rect, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, bitmapData);

    //Obtenir les pixels individuels de la zone verrouillée.
    auto *pixels = static_cast(bitmapData->Scan0);

    //Vecteur de vecteurs ; chaque vecteur est une colonne.
    std::vector> resultPixels(width, std::vector(height));

    const int stride = abs(bitmapData->Stride);
    for(int x = 0; x < width; x++) {
        for(int y = 0; y < height; y++) {
            //Obtenir la couleur du pixel à partir du tableau de pixels que nous avons obtenu précédemment.
            const unsigned pxColor = pixels[y * stride / 4 + x];

            //Obtenir chaque composante de couleur individuelle. Les couleurs des bitmaps sont dans l'ordre inverse.
            const unsigned red = (pxColor & 0xFF0000) >> 16;
            const unsigned green = (pxColor & 0xFF00) >> 8;
            const unsigned blue = pxColor & 0xFF;

            //Combinez les valeurs dans un format RGB plus typique (par opposition à la manière des bitmaps).
            const int rgbValue = RGB(red, green, blue);

            //Attribuer cette valeur RGB à l'emplacement du pixel dans le vecteur de vecteurs.
            resultPixels[x][y] = rgbValue;
        }
    }

    //Déverrouiller les bits que nous avions verrouillés précédemment.
    bitmap.UnlockBits(bitmapData);
    return resultPixels;
}

4voto

rmp Points 437

Voici comment je le ferais en utilisant GDIPlus Bitmap.LockBits méthode définie dans l'en-tête GdiPlusBitmap.h :

Remarquez que comme les bitmaps sont généralement alignés sur des DWORD, vous voudrez peut-être supprimer ces données inutilisées qui étaient nécessaires pour l'alignement, comme malat l'a correctement commenté..

    Gdiplus::BitmapData bitmapData;
    Gdiplus::Rect rect(0, 0, bitmap.GetWidth(), bitmap.GetHeight());

    // obtenir les données du bitmap
    if(Gdiplus::Ok == bitmap.LockBits(
                        &rect, // Une structure de rectangle qui spécifie la partie du Bitmap à verrouiller.
                        Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeWrite, // Les valeurs ImageLockMode qui spécifient le niveau d'accès (lecture/écriture) pour le Bitmap.
                        bitmap.GetPixelFormat(),// Les valeurs PixelFormat qui spécifient le format des données du Bitmap.
                        &bitmapData // BitmapData qui contiendra les informations sur l'opération de verrouillage.
                        ))
    {
         // obtenir la longueur des données du bitmap en octets
         int len = bitmapData.Height * std::abs(bitmapData.Stride);

         BYTE* buffer = new BYTE[len];
         memcpy(bitmapData.Scan0, buffer, len); // copier dans un tableau de BYTE

         //... 

         // nettoyage
         bitmap.UnlockBits(&bitmapData);        
         delete []buffer;
    }

3voto

GarethOwen Points 2406

Avez-vous essayé de fournir les octets lorsque vous créez le bitmap :

int width = BMP_WIDTH;
int height = BMP_HEIGHT;
int stride = 4 * width;
BYTE bytes[stride * height];

Gdiplus::Bitmap  cBitmap(width, height, stride, PixelFormat32bppRGB, bytes);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X