IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Comment convertir une image 24 bits en 8 bits ?


Sujet :

Langage Delphi

  1. #1
    Membre du Club Avatar de James64
    Profil pro
    Inscrit en
    Février 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 99
    Points : 49
    Points
    49
    Par défaut Comment convertir une image 24 bits en 8 bits ?
    Salut !!

    Existe-t-il une méthode ou une commande pour convertir une image 24 bits en 8 bits ?

    Merci

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 53
    Points : 50
    Points
    50
    Par défaut Re: Conversion
    Citation Envoyé par James64
    Salut !!

    Existe-t-il une méthode ou une commande pour convertir une image 24 bits en 8 bits ?

    Merci
    en niveau de gris?
    sinon il me semble qu'on peut mettre modifier simplement les proprietés palette ou pixelformat du bitmap pour ca.

    regarde l'aide de delphi a tbitmap

  3. #3
    Membre du Club Avatar de James64
    Profil pro
    Inscrit en
    Février 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 99
    Points : 49
    Points
    49
    Par défaut
    Oui, en niveau de gris. Entre temps, g vu que la conversion 24bits-->8bits ne fonctionnait pas dans ce sens avec la fonction pixelformat. Il faut un algo...

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 560
    Points : 576
    Points
    576
    Par défaut
    Bonjour,

    Le plus simple est de créer un bitmap 8 bit est de copier le bitmap ou l'image 24 bit dedans.

    Le plus simple est naturellment de bitmap à bitmap.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Procedure ConvertbitmapTo8bits(Original: Tbitmap): TBitmap;
    var
      Arect: Trect;
    begin
       Result := Tbitmap.Create;
       Result.PixelForma := pf8bit;
       Result.width := Original.Width;
       Result.Height := Original.Height;
       ARect := rect(0, 0, Original.Width, Original.Height);
        Result.Canvas.CopyRect(Rect, Original.Canvas, Rect);
    end;
    Dans le cas D'une Image vers un bitmap c'est un peux plus complex.
    Une image peut être un bitmap, une icone ou autre suivant le type d'image charger.
    Si je charge une icone la proriété bitmap de l'image n'est pas renseigné, mais n'est pas à nil. Inversement si je charge une image (.Bmp par exemple) la propriété icon n'est pas renseigné mais n'est pas vide.

    L'astuce consite à convertire l'image en bitmap, puis de passer la bitmap en 8 bit.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    function ConvertPicturetoBitmap (Picture:TPicture): Tbitmap;
    begin
        Result := Tbitmap.create;
         Result.PixelFormat := pf24bit;
         Result.Width := tmpPicture.Width;
        Result.Height := tmpPicture.Height;
         Result.Canvas.Draw(0, 0, tmpPicture.Graphic);
    end;
    Attention n'oubliez pas de détruire les images créer par les fonctions

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 560
    Points : 576
    Points
    576
    Par défaut
    Désole, le temps que je tape mon texte, la question à évolué.

    Pour les niveaux de gris, j'ai vu quelque chose dans efgs (
    http://homepages.borland.com/efg2lab/).
    De toute manière c'est un site trés bien informé pour tous le graphisme.

  6. #6
    Membre du Club Avatar de James64
    Profil pro
    Inscrit en
    Février 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 99
    Points : 49
    Points
    49
    Par défaut
    Changement de programme... et de questions....désolé.

    Le but de mon prog était de seuiller une image. Ca marchait en 8 bits niveau de gris mais je voudrais le faire au final avec une 24 bits niveau de gris !!!!

    primo :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BitMap.LoadFromFile(AppPath+\image1.bmp');
    me génère une "erreur de lecture du flux" lorsque image1 est en 24 bits !!!??
    En 8 bits, ca marchait

    Secondo : le seuillage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for j := 0 to Bitmap.Height-1 do
            begin
                 p:=Bitmap.ScanLine[j]; // Récupère le niveau de couleur du pixel (j)
                 for i := 0 to Bitmap.Width-1 do
                 begin
                      if p[i] > seuil then p[i]:=255  // Avec (p[i] --> Bitmap.ScanLine[j][i])
                      else p[i]:=0;
                 end;
            end;
    avec p : pbytearray; Fonctionnait en 8 bits niveau de gris mais en 24, les valeurs de p vont surement changer ? Ca ne sera plus 255 ?

    -pkoi me génère-t-il une erreur de flux?
    -qu'est-ce qui change dans le prog du seuillage?

    Merci

  7. #7
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Image "24 bits" en niveaux de gris = image pour laquelle toutes les composantes R, V et B sont égales entre elles pour un pixel donné.
    Si sur l'image 8 bits, Pixel[I,J].Gris=V, alors sur l'image 24 bits tu auras Pixel[I,J].Rouge=Pixel[I,J].Vert=Pixel[I,J].Bleu=V. Ton maximum est bien toujours 255.

    Ensuite, la conversion Couleur->Niveaux de gris demande un calcul pondéré : Gris = Round(0.30 * Rouge) + (0.59 * Vert) + (0.11 * Bleu)

    Bien sûr, si tu sais déjà que ton image est en niveaux de gris, il te suffit de prendre une seule des composantes R, V ou B qui devient alors directement la valeur en niveaux de gris. Par contre, il faut toujours lire les 3 valeurs R, V et B car ta ligne a triplé de taille ! ;-)

    Pour ta question sur le flux, essaie de vérifier que tu n'as pas verrouillé les propriétés du bitmap. L'idéal est d'en créer un nouveau juste avant la lecture, puis de l'assigner (si besoin est) à un bitmap sur la fiche. Du moins, c'est ce que je fais, et je n'ai jamais eu cette erreur.

    Est-ce que ça répond à tes questions ?

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Citation Envoyé par James64
    Le but de mon prog était de seuiller une image. Ca marchait en 8 bits niveau de gris mais je voudrais le faire au final avec une 24 bits niveau de gris !!!!

    primo :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BitMap.LoadFromFile(AppPath+\image1.bmp');
    me génère une "erreur de lecture du flux" lorsque image1 est en 24 bits !!!??
    En 8 bits, ca marchait
    Les images 24 bits ne sont pas en niveau de gris, en tout cas pas pour les bmp. Peut être cela existe dans certains formats très spécialisés tels que ceux utilisés en imagerie médicale, mais je n'en ai jamais rencontré.

    Citation Envoyé par James64
    Secondo : le seuillage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for j := 0 to Bitmap.Height-1 do
            begin
                 p:=Bitmap.ScanLine[j]; // Récupère le niveau de couleur du pixel (j)
                 for i := 0 to Bitmap.Width-1 do
                 begin
                      if p[i] > seuil then p[i]:=255  // Avec (p[i] --> Bitmap.ScanLine[j][i])
                      else p[i]:=0;
                 end;
            end;
    avec p : pbytearray; Fonctionnait en 8 bits niveau de gris mais en 24, les valeurs de p vont surement changer ? Ca ne sera plus 255 ?

    -pkoi me génère-t-il une erreur de flux?
    Ton image doit avoir un problème.

    Citation Envoyé par James64
    -qu'est-ce qui change dans le prog du seuillage?
    Si ta valeur 24 bits représente vraiment un niveau de gris : absolument rien, si ce n'est que ton seuil doit aussi représenter un niveau de gris 24 bits.

    Si par contre ton image est en couleur alors tu dois convertir en niveau de gris. Le plus simple, mais pas le plus pertinent, est de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (p[i].R + p[i].G + p[i].B) / 3 > seuil then ...
    Sinon tu peux utiliser une conversion plus proche de la réalité physiques, comme celles défini par le CIE. par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if Round(0.299 * p[i].R + 0.587 * p[i].G + 0.114 * p[i].B) > seuil then ...

  9. #9
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par sovitec
    Les images 24 bits ne sont pas en niveau de gris, en tout cas pas pour les bmp.
    Si, mais c'est un abus de langage. Ca veut juste dire que l'image est en 24 bpp, mais que ses composantes R, V et B sont identiques entre elles. J'ai pas dit que c'était un format intelligent, vu la place qu'il consomme, mais ça existe.

    Citation Envoyé par sovitec
    Le plus simple, mais pas le plus pertinent, est de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (p[i].R + p[i].G + p[i].B) / 3 > seuil then ...
    Hautement déconseillé, ça...

    Citation Envoyé par sovitec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if Round(0.299 * p[i].R + 0.587 * p[i].G + 0.114 * p[i].B) > seuil then ...
    Merci, je n'avais plus les valeurs exactes sous la main.

  10. #10
    Membre du Club Avatar de James64
    Profil pro
    Inscrit en
    Février 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 99
    Points : 49
    Points
    49
    Par défaut
    Merci pour toutes vos précisions. Je vous tiens au courant....

  11. #11
    Membre du Club Avatar de James64
    Profil pro
    Inscrit en
    Février 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 99
    Points : 49
    Points
    49
    Par défaut
    rectificatif: c une image à couleurs vraies RVB 24 bits !

  12. #12
    Membre du Club Avatar de James64
    Profil pro
    Inscrit en
    Février 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 99
    Points : 49
    Points
    49
    Par défaut
    Mon image a bien une erreur !! g essayé avec une autre et ca marche.

    Merci pour votre aide

  13. #13
    Membre du Club Avatar de James64
    Profil pro
    Inscrit en
    Février 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 99
    Points : 49
    Points
    49
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if Round(0.299 * p[i].R + 0.587 * p[i].G + 0.114 * p[i].B) > seuil then ...
    Comment dois-je déclarer p dans ce cas là ?

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 53
    Points : 50
    Points
    50
    Par défaut
    Citation Envoyé par James64
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if Round(0.299 * p[i].R + 0.587 * p[i].G + 0.114 * p[i].B) > seuil then ...
    Comment dois-je déclarer p dans ce cas là ?
    p:pbytearray;

    (c'est un pointeur sur l'array de donnée qui compose ton image)

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Citation Envoyé par James64
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if Round(0.299 * p[i].R + 0.587 * p[i].G + 0.114 * p[i].B) > seuil then ...
    Comment dois-je déclarer p dans ce cas là ?
    Attention, j'ai utiliser cette notation parce que je ne sais pas comment on fait pour récupérer les composantes rouge, verte et bleue. L'important dans ce que j'ai dit est la formule (que Mac LAK a aussi donné pendant que je rédigeais ma réponse).

  16. #16
    Membre du Club Avatar de James64
    Profil pro
    Inscrit en
    Février 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 99
    Points : 49
    Points
    49
    Par défaut
    Ok, mais en marquant le code ci dessus, g une erreur : type record, objet ou class requis !?

  17. #17
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par James64
    Ok, mais en marquant le code ci dessus, g une erreur : type record, objet ou class requis !?
    Normal.

    Tu dois prendre ta ligne (TBitmap.ScanLine[I]), et récupérer les composantes dedans.
    Pour chaque pixel, tu as un octet Rouge, un octet Vert et un octet Bleu =>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if Round(0.299 * TBitmap.ScanLine[I][3*J] + 0.587 * TBitmap.ScanLine[I][3*J+1] + 0.114 * TBitmap.ScanLine[I][3*J+2]) > seuil then
    Suivant le cas, tu peux avoir un 4ème octet par pixel (canal alpha) à ignorer. Je ne sais plus quel est l'ordre exact sur les octets A, R, G et B, par contre.
    Ceci étant dit, c'est un peu stupide : on ne seuille pas une image RGB avec une simple valeur en niveau de gris, c'est normalement une triple composante indiquant le seuil sur le rouge, le vert et le bleu, sachant que de toutes façons, le résultat devra être monochrome... Est-ce donc bien utile ? A ta place, je convertirai mon image en niveaux de gris à l'aide d'un outil comme PaintShopPro pour mes essais de seuillage.

  18. #18
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 298
    Points : 318
    Points
    318
    Par défaut
    Pour des questions de rapidité et pour ne pas avoir à manipuler des réels il est intéressant de créer une 'lookup table' qui contient un multiple entier pour chaque composante et pour optimiser la conversion RGB -> Gris :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    j: Word;
     
    // Init lookup table
    // 256 est utilisé car il est suffisament précis sans risque d'overflow
    for j := 0 to 255
       TableCompRed[j] := Round(0.299 * 256 * j);
     
    for j := 0 to 255
       TableCompGreen[j] := Round(0.587 * 256 * j);
     
    for j := 0 to 255
       TableCompBlue[j] := Round(0.114 * 256 * j);
     
    // dans la boucle sur les pixels de l'image
    if (TableCompRed[p[i].R] + TableCompGreen[p[i].G] + TableCompBlue[p[i].B]) > 256 * seuil

  19. #19
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par cpdump
    Pour des questions de rapidité et pour ne pas avoir à manipuler des réels il est intéressant de créer une 'lookup table' qui contient un multiple entier pour chaque composante et pour optimiser la conversion RGB -> Gris :
    Tu perds trop de précision sur la somme de tes composantes pondérées, ça peut causer de graves répercussions sur une image donc l'histogramme n'occuperai, par exemple, que 5% du domaine. Il faudrait passer à au moins 32 bits pour ta LUT, $FFFFFFFF correspondant à 255.

    Cependant, vu les vitesses et performances des coprocesseurs mathématiques, il vaut mieux choisir un type réel supporté par le copro (Single si tu veux faire "court", Double si tu as besoin de beaucoup de précision).
    Si tu veux optimiser "lourd" la conversion en niveaux de gris, l'idéal est d'utiliser autant de threads que de processeurs et surtout, le jeu d'instructions MMX (ou mieux, SSE/SSE2) qui permet des opérations SIMD, parfaites pour ce genre d'opérations.

    Vanne gratuite : Et faire une seule boucle "For J:=0 To 255" au lieu de trois... :-D ;-)

  20. #20
    Membre du Club Avatar de James64
    Profil pro
    Inscrit en
    Février 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 99
    Points : 49
    Points
    49
    Par défaut
    Mes essais en 8 bits niveau de gris fonctionnel nickel ! Seulement, je vais peut-etre etre amené à traiter des images 24 bits couleurs vraies RVB. Alors, je cherche une solution... de conversion si possible. (comme le fait naturellement photoshop). Ca serait moins lourd que de modifier toute l'opération de seuillage!

    Merci

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Comment convertir une image bmp en jpeg ?
    Par zidenne dans le forum Langage
    Réponses: 3
    Dernier message: 08/01/2006, 11h37
  2. Comment convertir une image en BMP ?
    Par blaiseac dans le forum Langage
    Réponses: 6
    Dernier message: 30/07/2005, 18h24
  3. Comment convertir une image bmp en png??
    Par Leclair2000 dans le forum Langage
    Réponses: 2
    Dernier message: 03/05/2005, 08h15
  4. [C#] Comment convertir une image bmp en jpg !!!
    Par vandeyy dans le forum Windows Forms
    Réponses: 5
    Dernier message: 13/07/2004, 20h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo