Salut !!
Existe-t-il une méthode ou une commande pour convertir une image 24 bits en 8 bits ?
Merci
Salut !!
Existe-t-il une méthode ou une commande pour convertir une image 24 bits en 8 bits ?
Merci
en niveau de gris?Envoyé par James64
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
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...
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.
Dans le cas D'une Image vers un bitmap c'est un peux plus complex.
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;
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.
Attention n'oubliez pas de détruire les images créer par les fonctions
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;
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.
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 :me génère une "erreur de lecture du flux" lorsque image1 est en 24 bits !!!??
Code : Sélectionner tout - Visualiser dans une fenêtre à part BitMap.LoadFromFile(AppPath+\image1.bmp');
En 8 bits, ca marchait
Secondo : le seuillageavec p : pbytearray; Fonctionnait en 8 bits niveau de gris mais en 24, les valeurs de p vont surement changer ? Ca ne sera plus 255 ?
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;
-pkoi me génère-t-il une erreur de flux?
-qu'est-ce qui change dans le prog du seuillage?
Merci
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 ?
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é.Envoyé par James64
Ton image doit avoir un problème.Envoyé par James64
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.Envoyé par James64
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 faireSinon 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 (p[i].R + p[i].G + p[i].B) / 3 > seuil then ...
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 ...
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.Envoyé par sovitec
Hautement déconseillé, ça...Envoyé par sovitec
Merci, je n'avais plus les valeurs exactes sous la main.Envoyé par sovitec
Merci pour toutes vos précisions. Je vous tiens au courant....
rectificatif: c une image à couleurs vraies RVB 24 bits !
Mon image a bien une erreur !! g essayé avec une autre et ca marche.
Merci pour votre aide
Comment dois-je déclarer p dans ce cas là ?
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 ...
p:pbytearray;Envoyé par James64
(c'est un pointeur sur l'array de donnée qui compose ton image)
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).Envoyé par James64
Ok, mais en marquant le code ci dessus, g une erreur : type record, objet ou class requis !?
Normal.Envoyé par James64
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 =>
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.
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
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.
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
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.Envoyé par cpdump
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 ;-)
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
Partager