wxDev.fr, le portail francophone consacré à wxWidgets ! ( The french portal for wxWidgets )  
Esp. membre
Recheche rapide



Recherche avancée
Statistiques
Membres inscrits :2359

Membres en ligne : 0
Invités en ligne : 1

Valid XHTML 1.0 Transitional

Valid CSS2

Menu forum (navigation):
Pages: 1  
 
Accueil » Accueil forums » Développement C/C++
» RGBA
Conversation : RGBA
farfou (Membre)
Inscrit le : 02-10-2008
Messages: 19
Snippets: 0
Tutoriels: 0
Hors ligne
Salut,

Je souhaite afficher un buffer d'image codé en RGBA.
A l'heure actuelle je créé une wxImage à partir d'un buffer en RGB que je transforme ensuite en wxBitmap pour l'afficher. Cependant je n'ai pas trouver la facon de faire la même chose en RGBA...

Si vous avez une solution à me proposer je vous en serais très reconnaissant.
02-10-2008 19:02:16  Re: RGBA #2
Gandi (Gourou de la secte)
Lieu: Clermont-Ferrand
Inscrit le : 10-10-2007
Messages: 216
Snippets: 5
Tutoriels: 0
Site web
Hors ligne
Tout se passe dans wxImage.

L'image que tu vas charger peut avoir ou pas de canal alpha.
Pour cela tu as HasAlpha.
Si il en possède pas tu peux faire InitAlpha puis ensuite tu peux initialiser le canal Alpha selon les valeurs que tu souhaites grâce à SetAlpha.

Ensuite tu convertis en bitmap et normalement si je comprend bien l'anglais ça devrait marcher.
wxBitmap

This class encapsulates the concept of a platform-dependent bitmap, either monochrome or colour or colour with alpha channel support.

"Les ordinateurs ne remplaceront jamais les livres. Vous ne pouvez pas vous mettre sur une pile de disquettes pour atteindre le haut de votre armoire" ( Sam Ewing )
02-10-2008 19:40:49  Re: RGBA #3
gbdivers (Membre)
Inscrit le : 05-03-2008
Messages: 92
Snippets: 2
Tutoriels: 0
Hors ligne
Pas très claire comme question... un peu de code aide toujours à mieux comprendre (de mon point de vue :))

Je vais faire un petit résumé de ce que je sais là dessus (ou que je crois savoir... parfois c'est pas pareil:()

- wxBitmap est codé en RGBA
codé en mémoire comme un tableau : ...RGBARGBARGBA...
chaque lettre correspond à 1 canal (rouge, vert, bleu, alpha) de chaque pixel codé sur profondeur de l'image octets (8 bits, 16, 32...)
donc pour une image 32 bits (4 octets), 1 pixel = 32 bits, 1 image 200*200 = 200*200*32 = 1250 ko

pour y acceder, on peut utiliser la class (peu docuementé) de wx :

Code wxWidgets:

wxBitmap bitmap; // la bitmap utilisée
wxNativePixelData data(bitmap); // on crée un conteneur
unsigned char* pd = (unsigned char*) &data.GetPixels().Data();
wxNativePixelData::Iterator pixel(data); // un pointeur sur les pixels
 
pixel.Red() = 128; // codé sur 8 bits = 0 à 255
pixel.Green() = 0;
pixel.Blue() = 255;
pixel.Alpha() = 128;
 
pixel++ // on se déplace dans le bitmap
pixel.Offset(data, x, y);
pixel.OffsetX(data, x);
pixel.OffsetY(data, y);


voir pour les détails :
http:/docs.wxwidgets.org/trunk/classwx_pixel_data.html
http:/docs.wxwidgets.org/trunk/classwx_ … rator.html

- Pour wxImage, le codage est un peu différent. Tu as un tableau RGB et un tableau A séparé
Tu récupère un pointeur sur ces canaux avec les fonctions :

Code wxWidgets:

unsigned char* wxImage::GetAlpha() const;
unsigned char* wxImage::GetData() const;

(utilise la fonction bool wxImage::HasAlpha() pour savoir si l'image à un canal alpha)

Ensuite, tu travailles avec les buffers de la meme facon :

Code wxWidgets:

wxImage image;
unsigned char* data = image.GetData();
int pixel = (y * image.GetWidth() + x) * 3; // offset du pixel de coordonnées (x,y)
data[pixel] = 128; // canal R
data[pixel+1] = 0; // canal G
data[pixel+2] = 255; // canal B
 
if(HasAlpha())
{
    unsigned char* alpha = image.GetAlpha();
    int pixel = y * image.GetWidth() + x; // offset du pixel de coordonnées (x,y)
    alpha[pixel] = 128; // on modifie le canal alpha
    char value = alpha[pixel]; // on lit le canal alpha
}


Et bien sur, tu peux aussi utiliser les fonctions standard du c++ pour remplir ton image :

Code wxWidgets:

memset(data, 0, image.GetWidth()*image.GetHeight()*3); // efface l'image
memcpy(data_dst, data_src, image.GetWidth()*image.GetHeight()*3); // copie d'images


Voila, j'espère avoir répondu un peu a ta question

EDIT: après vérification, on doit utiliser wxNativePixelData (profondeur d'image dependant du système) ou wxAlphaPixelData (toujours en 32 bits)

Dernière modification par gbdivers (03-10-2008 16:58:19)

03-10-2008 11:23:42  Re: RGBA #4
farfou (Membre)
Inscrit le : 02-10-2008
Messages: 19
Snippets: 0
Tutoriels: 0
Hors ligne
Merci Gandi, mais mon problème était justement que dans wxImage les données RGB et le canal Alpha sont séparés.

Merci gbdivers, c'est bien ce qui m'intéressait de savoir que wxBitmap est bien codé en RGBA.

Je vais me pencher sur ta méthode avec wxNativePixelData mais ce que je voudrais en fait c'est créer un bitmap à partir d'un tableau de données déjà existant.
J'ai vu que je pouvais utiliser ce constructeur de wxBitmap:

Code wxWidgets:

wxBitmap::wxBitmap(const char bits[], int width, int height, int depth = 1)


avec un tableau de char et depth = 32 mais la doc à l'air de prévenir que mon image pourrais apparaître en noir et blanc sur d'autres OS que Windows.

http://docs.wxwidgets.org/trunk/classwx_bitmap.html

Voici mon code de test:

Code wxWidgets:

unsigned long *Pt_LcdBufferImage = (unsigned long *) malloc(416 * 270 * sizeof(long));
memset(Pt_LcdBufferImage, 0, 416 * 270 * 4 * sizeof(long));
 
for (int i = 0; i < 50000; i++)
    Pt_LcdBufferImage[i] = 0xFF00FF00UL;
 
bitmap = new wxBitmap((const char *)Pt_LcdBufferImage, 416, 270, 32);


Voilà, donc ça marche très bien mais est-ce portable???

Dernière modification par farfou (03-10-2008 11:37:21)

03-10-2008 13:20:50  Re: RGBA #5
gbdivers (Membre)
Inscrit le : 05-03-2008
Messages: 92
Snippets: 2
Tutoriels: 0
Hors ligne
En effet, ce n'est pas portable :(

Voici un extrait du fichier wx/rawbmp.h qui définit les formats de bitmap en fonction de la plateforme :

Code wxWidgets:

// wxImage format is common to all platforms
typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxImagePixelFormat;
 
// the (most common) native bitmap format without alpha support
#if defined(__WXMSW__)
    // under MSW the RGB components are reversed, they're in BGR order
    typedef wxPixelFormat<unsigned char, 24, 2, 1, 0> wxNativePixelFormat;
 
    #define wxPIXEL_FORMAT_ALPHA 3
#elif defined(__WXMAC__)
    // under Mac, first component is unused but still present, hence we use
    // 32bpp, not 24
    typedef wxPixelFormat<unsigned char, 32, 1, 2, 3> wxNativePixelFormat;
 
    #define wxPIXEL_FORMAT_ALPHA 0
#elif defined(__WXCOCOA__)
    // Cocoa is standard RGB or RGBA (normally it is RGBA)
    typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxNativePixelFormat;
 
    #define wxPIXEL_FORMAT_ALPHA 3
#elif defined(__WXGTK__)
    // Under GTK+ 2.X we use GdkPixbuf, which is standard RGB or RGBA
    typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxNativePixelFormat;
 
    #define wxPIXEL_FORMAT_ALPHA 3
#elif defined(__WXDFB__)
    // Under DirectFB, RGB components are reversed, they're in BGR order
    typedef wxPixelFormat<unsigned char, 24, 2, 1, 0> wxNativePixelFormat;
 
    #define wxPIXEL_FORMAT_ALPHA 3
#endif
 
// the (most common) native format for bitmaps with alpha channel
#ifdef wxPIXEL_FORMAT_ALPHA
    typedef wxPixelFormat<unsigned char, 32,
                          wxNativePixelFormat::RED,
                          wxNativePixelFormat::GREEN,
                          wxNativePixelFormat::BLUE,
                          wxPIXEL_FORMAT_ALPHA> wxAlphaPixelFormat;
#endif // wxPIXEL_FORMAT_ALPHA

On voit en particulier que sous Win, le format est BGR sur 24 bits, sous Mac le format est BGR sous 32 bits et sous linux, le format est RGB sous 24 bits !


Donc, sois tu adaptes ton code en fonction de l'environnement (avec des #ifdef), sois tu utilises wxNativePixelData qui est indépendant de la plateforme, sois tu utilises un wxImage (qui a un encodage fixe indépendant de la plateforme)

Le plus efficace (a mon avis) est d'utiliser wxNativePixelData si tu veux travailler sur les bitmap en bas niveau
Si tu dois travailler sur des données provenant d'une librairie et que le format est le meme que le système, un simple memcpy. Sinon, ecris ton Blit toi meme qui adaptera les formats


Petite remarque concernant l'exemple de code que tu as donné
tu utilises un unsigned long*, ca qui n'est pas très prudent. De mémoire, le long est définit comme étant codé sur 2 fois plus d'octets que l'integer... en fonction du système (en particulier pour les 32 bits ou les 64 bits), l'encodage peut se faire sur 4 ou 8 octets.
Il vaut mieux utiliser un unsigned char*, se déplacer en incrémantant de 4*sizeof(char) et en accédant aux canaux en incrémantant de canal*sizeof(char).
----------
Voici un petit exemple de code pour illustrer ce que j'ai raconté :

J'utilise la bibliothèque AGG (Anti Grain Geometry, wwwantigrain.com) qui permet de faire des rendus 2d de qualité. Cette bibliothèque travaille avec des formats de bitmaps indépendant de la plateforme.
Dans ce code, j'utilise un buffer RGB dans agg pour dessiner puis je copie ce buffer dans un wxBitmap en utilisant un wxNativePixelData :

Code wxWidgets:

{
    wxFrame* frame = new wxFrame(this, wxID_ANY, _("title"));
    wxBitmap* bitmap;
    int frame_width = 200;
    int frame_height = 200;
    {
        // le buffer de agg (agg:int8u == unsigned char)
        agg::int8u* buffer = new agg::int8u[frame_width * frame_height * 3];
 
        // on dessine...
        memset(buffer, 255, frame_width * frame_height * 3);
        agg::rendering_buffer rbuf(buffer, frame_width, frame_height, frame_width * 3);
        agg::pixfmt_rgb24 pixf(rbuf);
 
        agg::int8u* amask_buf = new agg::int8u[frame_width * frame_height];
        agg::rendering_buffer amask_rbuf(amask_buf, frame_width, frame_height, frame_width);
        agg::amask_no_clip_gray8 amask(amask_rbuf);
 
        agg::pixfmt_amask_adaptor<agg::pixfmt_rgb24, agg::amask_no_clip_gray8> pixf_amask(pixf, amask);
        unsigned i;
        for(i = 0; i < frame_height; ++i)
        {
            unsigned val = 255 * i / frame_height;
            memset(amask_rbuf.row_ptr(i), val, frame_width);
        }
        agg::rgba8 span[frame_width];
        for(i = 0; i < frame_width; ++i)
        {
            agg::rgba c(380.0 + 400.0 * i / frame_width, 0.8);
            span[i] = agg::rgba8(c);
        }
        for(i = 0; i < frame_height; ++i)
        {
            pixf_amask.blend_color_hspan(0, i, frame_width, span, 0);
        }
        delete [] amask_buf;
 
        // on crée le wxBitmap et les pointeurs
        bitmap = new wxBitmap(frame_width, frame_height);
        wxNativePixelData data(*bitmap);
        wxNativePixelData::Iterator pixel(data);
        unsigned char* pBuffer = buffer;
 
        // on copie
        for(int i=0; i<(frame_width*frame_height); ++i)
        {
            pixel.Red() = *pBuffer; pBuffer++;
            pixel.Green() = *pBuffer; pBuffer++;
            pixel.Blue() = *pBuffer; pBuffer++;
            pixel++;
        }
 
        delete [] buffer;
    }
    wxStaticBitmap* ctrl = new wxStaticBitmap(frame, -1, *bitmap);
    frame->Show();
}


PS : ok Xaviou, je vais faire les snippets la dessus :) EDIT : ou peut etre un tuto pour utilsier AGG dans wx si ca interesse quelqu'un

Dernière modification par gbdivers (03-10-2008 14:41:23)

03-10-2008 14:42:27  Re: RGBA #6
farfou (Membre)
Inscrit le : 02-10-2008
Messages: 19
Snippets: 0
Tutoriels: 0
Hors ligne
Merci beaucoup pour ta réponse. Ca m'éclaire beaucoup.
En effet, j'ai d'abord défini un tableau de char à la place des long et testé en remplissant comme ceci:

Code wxWidgets:

for (i = 0; i < 50000; i+=4)
{
    Pt_LcdBufferImage[i] = 255;
    Pt_LcdBufferImage[i+1] = 0;
    Pt_LcdBufferImage[i+2] = 0;


et exactement comme tu viens de me l'expliquer, le rouge et le bleu étaient inversés (je suis sous windows).
Je suis passé aux long pour pouvoir entrer les couleurs par leur code pour respecter les conventions du programme que je suis en train de modifier, meme si cela induit que le programme tournera uniquement sur une machine 32 bits. Merci du conseil toutefois.
Avec les long la couleur affichée est la bonne! Alors n'est-ce vraiment pas  portable? (Je n'ai pas de Linux ou de Mac sous la main pour tester...)

Mon problème avec ta solution est que je doit utiliser un tableau en rgba déjà existant. Et je n'ai pas bien compris comment faire. Il n'y a pas de constructeur le permettant et lorsque tu me propose

gbdivers:
Si tu dois travailler sur des données provenant d'une librairie et que le format est le meme que le système, un simple memcpy. Sinon, ecris ton Blit toi meme qui adaptera les formats
je crois comprendre que sois je ne suis toujours pas portable soit je dois écrire un Blit mais je ne sais pas ce que c'est...
03-10-2008 16:45:15  Re: RGBA #7
gbdivers (Membre)
Inscrit le : 05-03-2008
Messages: 92
Snippets: 2
Tutoriels: 0
Hors ligne
Avec des long, ta solution n'est (peut etre) pas portable.
Pour la profondeur des pixels, tu forces à 32 bits, donc tu n'auras de problème de compatibilité (sinon sous win, c'est 24 bits, 32 sous mac et linux).
Par contre, l'encodage RGB ou BGR, je ne sais pas si wxBitmap corrige ce problème. Si ca n'est pas le cas, alors le bleu se code 0x0000FF00UL sous linux et 0xFF000000UL sous win. Si tu as bien du bleu avec 0x0000FF00UL sous win, cela veut dire que le fait de forcer la profondeur à 32 bits permet d'utiliser le format par defaut de wxBitmap (c'est  à dire wxAlphaPixelFormat = RGBA 32 bits)
wxWidgets Doc:
wxBitmap(int width, int height, int depth = -1)

Creates a new bitmap. A depth of -1 indicates the depth of the current screen or visual. Some platforms only support 1 for monochrome and -1 for the current colour setting. Beginning with version 2.5.4 of wxWidgets a depth of 32 including an alpha channel is supported under MSW, Mac and GTK+.
Dans ce cas (a priori), ta solution est portable puisque tu n'utilises le format de wxBitmap par defaut (a vérifier... je mets beaucoup de conditionnel parce que je n'ai pas testé)

Personnelement, je n'utiliserais pas quand meme 0x0000FF00UL. C'est trop dependant de l'encodage (et ca fait un peu "constante magique")

Un Blit est une copie d'image vers une image (un memcpy spécial). Voir wxDC::Blit() par exemple.
Un exemple de code se trouve dans les dernières lignes du code précedent.

Un exemple de Blit simplifié, dérivé du Blit de wxDC, pour écrire depuis un flux vers un wxBitmap, serait :

Code wxWidgets:

wxBitmap* CreateBitmapFromBuffer(unsigned char* pBuffer, wxCoord width, wxCoord height, wxString inputBufferType = wxT("RGBA"))
{
    // on crée le wxBitmap et les pointeurs
    bitmap = new wxBitmap(width, height);
    wxNativePixelData data(*bitmap);
    wxNativePixelData::Iterator pixel(data);
    unsigned char* pBuffer = buffer;
 
    if(inputBufferType == wxT("RGB")
    {
        // on copie depuis un RGB
        for(int i=0; i<(width*height); ++i)
        {
            pixel.Red() = *pBuffer; pBuffer++;
            pixel.Green() = *pBuffer; pBuffer++;
            pixel.Blue() = *pBuffer; pBuffer++;
            pixel++;
        }
    }
    else if(inputBufferType == wxT("RGBA"))
    {
        // on copie depuis un RGBA
        for(int i=0; i<(width*height); ++i)
        {
            pixel.Red() = *pBuffer; pBuffer++;
            pixel.Green() = *pBuffer; pBuffer++;
            pixel.Blue() = *pBuffer; pBuffer++;
            /*pixel.Alpha() = *pBuffer; vérifier que le canal alpha existe avant...*/ pBuffer++;
            pixel++;
        }
    }
    else if(inputBufferType == wxT("BGR"))
    {
        // on copie depuis un RGB
        for(int i=0; i<(width*height); ++i)
        {
            pixel.Blue() = *pBuffer; pBuffer++;
            pixel.Green() = *pBuffer; pBuffer++;
            pixel.Red() = *pBuffer; pBuffer++;
            pixel++;
        }
    }
}


Il est quand meme préférable d'utiliser les constantes de compilation (__WXMSW__, __WXGTK__...) pour éviter des tests inutiles dans la plus part des cas.


Dans tous les cas, utiliser directement les buffers est dangereux. A utilser avec précaution (ou pas du tout)

C'est pour quel type de projet que tu utilises les buffers ? (si c'est pas indiscret) Ne peux tu pas utiliser les fonctions Draw... de wxDC ?
----------
Pour complément et pour notes

Pour connaitre les paramètres utilisés sur un système donné :

Code wxWidgets:

wxPixelFormat::ChannelType // type de base utilisé (en général unsigned char)
wxPixelFormat::BitsPerPixel // nombre de bits par pixel
wxPixelFormat::RED
wxPixelFormat:: GREEN
wxPixelFormat::BLUE

Dernière modification par gbdivers (03-10-2008 17:08:23)

03-10-2008 17:13:06  Re: RGBA #8
farfou (Membre)
Inscrit le : 02-10-2008
Messages: 19
Snippets: 0
Tutoriels: 0
Hors ligne
Tu as raison, ca marchait par ce que j'utilisais les codes couleur de windows...
Ce qui est sur c'est que je ne peux pas récrire tout le projet qui est basé sur le buffer.
En tout cas je te remercie beaucoup et je m'y replonge avec tes précieux conseils des lundi.
----------
Heu...
En fait dans mon projet le bleu est défini 0xFF0000FFUL ???

Dernière modification par farfou (03-10-2008 17:16:13)

03-10-2008 17:38:12  Re: RGBA #9
gbdivers (Membre)
Inscrit le : 05-03-2008
Messages: 92
Snippets: 2
Tutoriels: 0
Hors ligne
oui, en BGR 32 bits : 0xFF(bleu)00(vert)00(rouge)FF(ignoré, correspond a alpah)UL

V2rifie en utilisant 0xFF000000UL par exemple.

En 24 bits, tu aurais utilisé 0xFF0000 (mais pas avec des long)
06-10-2008 09:59:33  Re: RGBA #10
farfou (Membre)
Inscrit le : 02-10-2008
Messages: 19
Snippets: 0
Tutoriels: 0
Hors ligne
Salut!
Bon week-end?
Je commence à cerner le problème, mon buffer à l'air d'être en ARGB!!!

Code wxWidgets:

//Some Color
#define    COLOR_WHITE                0xFFFFFFFFUL
#define    COLOR_BLACK                0xFF000000UL
#define    COLOR_RED                0xFFFF0000UL
#define    COLOR_GREEN                0xFF00FF00UL
#define    COLOR_BLUE                0xFF0000FFUL
#define    COLOR_GREY                0xFFB4B4B4UL

Je vais, je pense, utiliser une fonction comme la tienne qui me transforme ça en wxNativePixelData. Tant pis pour la simple recopie mémoire, mais le problème de portabilité devrait être résolu.
Encore merci énormément pour ton aide.
----------
J'ai un bug à l'exécution en utilisant un Blit comme tu me l'as expliqué (access violation).

Code wxWidgets:

int i;
bitmap = new wxBitmap(416, 270);
wxNativePixelData data(*bitmap);
wxNativePixelData::Iterator pixel(data);
//Pt_LcdBufferImage est un unsigned long* global
unsigned char *pBuffer = (unsigned char *)Pt_LcdBufferImage;
 
//Le buffer contient des valeurs commes celle définis dans le post précédent. Ici je met du jaune
for (i = 0; i < 50000; i++)
    Pt_LcdBufferImage[i] = 0xFFFFFF00UL;
 
for(i = 0; i<(416*270); ++i)
{
    pBuffer++;
    pixel.Red() = *pBuffer; pBuffer++;
    pixel.Green() = *pBuffer; pBuffer++;
    pixel.Blue() = *pBuffer; pBuffer++;
    pixel++;
}

Dernière modification par farfou (06-10-2008 11:30:43)

06-10-2008 14:11:21  Re: RGBA #11
gbdivers (Membre)
Inscrit le : 05-03-2008
Messages: 92
Snippets: 2
Tutoriels: 0
Hors ligne
j'ai copié ton code en ajoutant unsigned long* Pt_LcdBufferImage = new unsigned long[50000]; pour initialiser ton buffer...

Et je n'ai pas de message d'erreur !

Petite remaque concernant ton code. Tu initialises ton Pt_LcdBufferImage avec 50000 points et tu en lis 416*270 = 112320 points
06-10-2008 14:54:23  Re: RGBA #12
farfou (Membre)
Inscrit le : 02-10-2008
Messages: 19
Snippets: 0
Tutoriels: 0
Hors ligne
En fait Pt_LcdBufferImage était initialisé à la création de la fenêtre que voici:

Code wxWidgets:

MainFrame::MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size): wxFrame((wxFrame *)NULL, -1, title, pos, size, wxDEFAULT_FRAME_STYLE|wxFULL_REPAINT_ON_RESIZE)
{
    int i;
 
    Connect(wxEVT_PAINT, wxPaintEventHandler(MainFrame::OnPaint));
    Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainFrame::OnKeyDown));
        Connect(wxEVT_TIMER, wxCommandEventHandler(MainFrame::OnTimer));
 
    timer = new wxTimer(this, 1);
    timer->Start(3000);
 
    Pt_LcdBufferImage = (unsigned long *) malloc(416 * 270 * 4 * sizeof(char));
    memset(Pt_LcdBufferImage, 0, 416 * 270 * 4 * sizeof(char));
 
    for (i = 0; i < 50000; i+=6)
    {
                //Les couleurs telles que définies dans mon projet ont l'air d'être en ARGB!!!
        Pt_LcdBufferImage[i]   = 0xFFFFFFFFUL;    //blanc
        Pt_LcdBufferImage[i+1] = 0xFF000000UL;    //noir
        Pt_LcdBufferImage[i+2] = 0xFFFF0000UL;    //rouge
        Pt_LcdBufferImage[i+3] = 0xFF00FF00UL;    //vert
        Pt_LcdBufferImage[i+4] = 0xFF0000FFUL;    //bleu
        Pt_LcdBufferImage[i+5] = 0xFFB4B4B4UL;    //gris
    }
 
        //Mon ancienne méthode qui n'est surement pas portable
    //bitmap = new wxBitmap(*image);
    //bitmap = new wxBitmap((const char *)Pt_LcdBufferImage, 416, 270, 32);
 
        //Ta méthode qui provoque un message d'erreur
    bitmap = new wxBitmap(416, 270, 32);
    wxAlphaPixelData data(*bitmap);
    wxAlphaPixelData::Iterator pixel(data);
    unsigned char *pBuffer = (unsigned char *)Pt_LcdBufferImage;
 
    FILE *f = fopen("res.txt", "w");
    for(i = 0; i < (416 * 270 * 4); i+=4, pixel++)
    {
        //pixel.Alpha() = pBuffer[i];
        pixel.Red() = pBuffer[i+1];
        pixel.Green() = pBuffer[i+2];
        pixel.Blue() = pBuffer[i+3];
 
        fprintf(f, "%X\n%d %d %d %d\n\n",Pt_LcdBufferImage[i], pBuffer[i], pBuffer[i+1], pBuffer[i+2], pBuffer[i+3]);
    }
    fclose(f);
}

et voila ce que j'obtiens dans mon fichier text:

255 255 255 255

0 0 0 255

0 0 255 255

0 255 0 255

255 0 0 255

180 180 180 255

...

Dans pBuffer les couleurs ont l'air d'avoir été transformées en BGRA, standard de Windows. Quand???
Je suis largué là...

Dernière modification par farfou (06-10-2008 15:05:07)

06-10-2008 15:50:12  Re: RGBA #13
gbdivers (Membre)
Inscrit le : 05-03-2008
Messages: 92
Snippets: 2
Tutoriels: 0
Hors ligne
le code tourne, c'est deja ca :)

en mettant :

Code Cpp:

for(i = 0; i < 20; ++i)
    fprintf(f, "%X ",Pt_LcdBufferImage[i]);


j'obtiens ca:

Code:

FFFFFFFF FF000000 FFFF0000 FF00FF00 FF0000FF FFB4B4B4 
FFFFFFFF FF000000 FFFF0000 FF00FF00 FF0000FF FFB4B4B4
FFFFFFFF FF000000 FFFF0000 FF00FF00 FF0000FF FFB4B4B4
...


En mettant :

Code Cpp:

for(i = 0; i < 20*4; ++i)
    fprintf(f, "%d ", pBuffer[i]);


j'obtiens :

Code:

255 255 255 255 
  0   0   0 255
  0   0 255 255
  0 255   0 255
255   0   0 255
180 180 180 255
255 255 255 255
...


Conclusion : Je n'ai pas trouvé sur internet comment été codé les long en mémoire., mais à priori les bits de poids faibles des long sont en premier en mémoire...
De toute facon, tu lis et ecris des bits indépendement de l'encodage RGB. Donc le problème ne vient pas du format de bitmap.

Je confirme ce que j'ai dis plus tot : utilisé des long et des constantes de couleurs est risqué : tu n'es pas sur de la taille des long en mémoire, tu n'es pas sur de l'encodage des longs, tu n'es pas sur de l'encodage des couleurs en mémoire...


L'approche que j'utiliserais :
Question : qu'est qu'on connait de la structure de couleur ?
Réponse : RGB 32 bits = 4 char codant chacun 1 canal
j'utiliserais donc une structure pour lire le buffer :

Code wxWidgets:

class RGBA
{
    public :
        RGBA(char r, char g, char b, char a)
            { R=r; G=g; B=b; A=a; }
        char R;
        char G;
        char B;
        char A;
};


Ton buffer est donc codé par un tableau de RGBA :

Code Cpp:

RGBA pBuffer[] = (RGBA*) Pt_LcdBufferImage;


Tu accedes aux éléments par :

Code Cpp:

char r = pBuffer[index].R;
char g = pBuffer[index].G;
char b = pBuffer[index].B;
char a = pBuffer[index].A;


Une couleur se code donc :

Code Cpp:

RGBA rouge = RGBA(255, 0, 0, 255);
RGBA vert = RGBA(0, 255, 0, 255);
RGBA bleu = RGBA(0, 0, 255, 255);
RGBA gris = RGBA(180, 180, 180, 256);


Pour lire ou écrire dans ton buffer, tu utilise cette structure :

Code Cpp:

for(int index=0; index<(416*270); ++index)
    pBuffer[index] = vert;


De cette facon, tu evites les erreurs, ton code est plus lisible (RGBA(0, 255, 0, 255) est plus claire que 0xFF00FF00UL et sera toujours correctement encodé en mémoire)...

EDIT : petite remarque concernant la performence : le compilateur optimise normalement ce code, ce qui fait que cela est aussi rapide qu'un memcpy

Dernière modification par gbdivers (06-10-2008 16:11:48)

06-10-2008 16:16:26  Re: RGBA #14
farfou (Membre)
Inscrit le : 02-10-2008
Messages: 19
Snippets: 0
Tutoriels: 0
Hors ligne
non, ça tourne et ça s'arrête, mon erreur est à l'exécution.
06-10-2008 16:37:06  Re: RGBA #15
gbdivers (Membre)
Inscrit le : 05-03-2008
Messages: 92
Snippets: 2
Tutoriels: 0
Hors ligne
Pardon, je pensais que ca fonctionnait
Chez moi, ca tourne sans problème ??

En mode debug, ca plante où ?
Si tu ajoutes des "std::cout << i << std::endl;" dans tes boucles, ca plante où ?


EDIT : j'ai ajouté "bitmap->SaveFile(_("/home/guillaume/Bureau/test.bmp"), wxBITMAP_TYPE_BMP);". l'image est correctement créée

Dernière modification par gbdivers (06-10-2008 16:46:42)

06-10-2008 16:52:17  Re: RGBA #16
farfou (Membre)
Inscrit le : 02-10-2008
Messages: 19
Snippets: 0
Tutoriels: 0
Hors ligne
je ne sais pas utiliser le mode debug mais avec des tests j'ai remarqué que ça plantait au 737eme tour.
06-10-2008 16:56:24  Re: RGBA #17
gbdivers (Membre)
Inscrit le : 05-03-2008
Messages: 92
Snippets: 2
Tutoriels: 0
Hors ligne
Bon, je seche...
737, c'est trop peu pour un dépassement de mémoire...

Je suis sous linux en ce moment, quand je repasse sous win, je testerais a nouveau.

Pour le moment, pas d'idée de comment trouver le problème (et sourtout pourquoi ca marche chez moi et pas chez toi)
06-10-2008 17:02:54  Re: RGBA #18
farfou (Membre)
Inscrit le : 02-10-2008
Messages: 19
Snippets: 0
Tutoriels: 0
Hors ligne
merci, moi aussi je seche...
Si tu es sous linux peux-tu tester si les couleurs sont bonnes avec la méthode

Code wxWidgets:

bitmap = new wxBitmap((const char *)Pt_LcdBufferImage, 416, 270, 32);

???

Dernière modification par farfou (08-10-2008 13:42:43)

06-10-2008 17:18:00  Re: RGBA #19
gbdivers (Membre)
Inscrit le : 05-03-2008
Messages: 92
Snippets: 2
Tutoriels: 0
Hors ligne
Ca ne marche qu'avec depth=1
06-10-2008 17:23:26  Re: RGBA #20
farfou (Membre)
Inscrit le : 02-10-2008
Messages: 19
Snippets: 0
Tutoriels: 0
Hors ligne
Merci quand même!
Menu forum (navigation):
Pages: 1  
 
Accueil » Accueil forums » Développement C/C++
» RGBA