Est-il possible que le TRawImage code les pixels sur 4 octets alors qu'ils sont codés sur 3 octets dans le fichier ?
Il faudrait s'en assurer avec son BytesPerPixel.
Est-il possible que le TRawImage code les pixels sur 4 octets alors qu'ils sont codés sur 3 octets dans le fichier ?
Il faudrait s'en assurer avec son BytesPerPixel.
Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
. Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !
Damned !
BytesPerPixel je n'ai pas, mais j'ai
D'où on déduira que BytesPerPixel vaut 4 si on considère la seconde ligne.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 Depth=24 BitsPerPixel=32
Quand je disais que c'est une cochonnerie pas fiable, ce TRawImageDescription !
Parce que quand je demande le PixelFormat du fichier en lisant son header, ça remonte bien 24, donc 3 bytes per pixel.
T'as mis le doigt là où ça fait mal, et c'est juste ingérable puisque quand on regarde le fichier à l'éditeur hexa on voit bien que c'est du 24, pas du 32.
Quand je reviens, je creuserai les streams...
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
Src c'est un TBitmap le RawImage.Description.BitsPerPixel il est en 24bits ou en 32bits ?. Pour le "image1.Picture.Bitmap" par défaut si je me souviens bien le bitsperpixel est à 32bits et donc quand tu charges un BMP 32bits si le canal alpha est à 0 ou 255 il sera normal que le Depth soit à 24.
La taille d'un pixel dans les données est représenté par le bitsperpixel le Depth correspond au nombre de bits "utilisés" ces 2 valeurs ont on toujours été source de confusions. Ensuite si je me souviens bien lorsque tu charges un BMP 24 bits dans un TBitmap qui a été initialiser en 32bits le BitsPerPixels reste en 32 bits et ne change pas.
Donc si tu as
Ta procédure devrais from scratch ressembler à ceciDepth=24
BitsPerPixel=32
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 for h := 0 to src.Height-1 do begin pbS := pByte(src.RawImage.GetLineStart(h)); if src.RawImage.Description.BitsPerPixel = 24 then begin for ws := 0 to (src.Width*3)-1 do memo1.Lines.Add(IntToStr(ws) +' '+ IntToStr(pbS[ws])); p := 0; // ok pour skipper les bytes de padding while (((src.Width*3)+p) mod 4 <> 0) do begin mss.ReadByte; inc(p); end; end else if src.RawImage.Description.BitsPerPixel = 32 then begin for ws := 0 to (src.Width*4)-1 do memo1.Lines.Add(IntToStr(ws) +' '+ IntToStr(pbS[ws])); //--> Dans exemple ca devrait être ici que ca se passe end; end;
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Oui, je suis parti de ça, j'ai juste rajouté un ShowMessage pour savoir où je passais (par le else 32 comme tu l'indiques) et, navré de te décevoir, mais le bestiau résiste et se défend comme un beau diable :
On peut constater (avec stupéfaction !) que le 183 est toujours là, à sa place, vaillant, même si on ne sait pas d'où il sort, quant aux deux autres pavés orange, je ne sais pas quoi en dire dans la mesure où tout étant décalé après le 1er pixel, est-ce qu'il s'agit de bytes de pixels ou de bytes de padding ?
(padding qui, soit dit en passant, est normalement de 3 bytes par ligne, voir l'image précédente)
On ne le saura jamais, je vais voir ce que m'apportent les streams.
Tant pis pour les pointeurs de scanline et ce genre de choses, mais à l'impossible nul n'est tenu.
Et comme je pense qu'il doit y avoir moyen de refaire la même chose avec les streams, alors au boulot !
PS : quelqu'un veut jouer avec le fichier ? : 3x2x24_vh1.bmp.zip
3x2x24_vh1 pour 3 pixels de large x 2 lignes en 24 bpp et une VersionHeader à 1.
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
Bon, voilà le cœur du truc, torché en 10 minutes (à comparer aux 3 semaines du RawImage...) :
vous noterez 3 lignes en commentaire pour bien les repérer, il faut les activer ! Sinon, les grandes largeurs impaires (397 ici) échouent lamentablement, et je ne sais pas pourquoi : ça le faisait déjà avec RawImage et associés…
Il me reste un fichier cassé à l'origine, et qui le reste :
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
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 mss := TMemoryStream.Create; src.SaveToStream(mss); mss.Position := GetOffsetToDatas(src); dst.BeginUpdate(); for h := src.Height-1 downto 0 do begin // parcours inversé pour les streams pbD := pByte(dst.RawImage.GetLineStart(h)); wd := 0; for ws := 0 to (src.Width*3)-1 do begin aByte := mss.ReadByte; //memo1.Lines.Add(IntToStr(ws)+' '+IntToStr(aByte)); pbD[wd] := aByte; if ((ws + 1) mod 3 = 0) then begin // = traitement du 3e byte de la source terminé // R et B inversés pour jouer --> en fait elles sont naturellement inversées SI pf32bit tmpbyte := pbD[wd-2]; pbD[wd-2] := pbD[wd]; pbD[wd] := tmpbyte; // 4e byte bidouille obligatoire sinon les grandes largeurs impaires sont en vrac // if (src.Width < 32) // tout comme les toutes petites // or (not Odd(src.Width)) then begin // largeur > 32, test si paire (= not impair) inc(wd); pbD[wd] := 255; // end; end; inc( wd); end; p := 0; // ok pour skipper les bytes de padding while (((src.Width*3) + p) mod 4 <> 0) do begin mss.ReadByte; inc(p); end; end; dst.EndUpdate(); // mss.Position:=0; mss.SaveToFile('/root/Desktop/mss.bmp'); mss.Free; image2.Picture.Bitmap.Assign(dst);
mais le plus curieux, c'est que l'enregistrement du bitmap dst génère un fichier correct, regardez sa miniature créée par Linux sur le Bureau.
Je verrai ça demain à tête reposée, après avoir fait le ménage dans le projet de test, qui est une joyeuse pagaille, vous vous en doutez.
Ce soir j'en ai un peu ras la casquette,
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
J'ai fait un petit test avec lazarus 2.0 sous Windows il semblerai que certain petits problèmes ont été corrigés. Mais c'est pas à 100% juste.
J'ai testé avec des BMP 24bits et 32bits
Avec le code suivant
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
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 procedure TForm1.Button1Click(Sender : TObject); begin if OPD.Execute then begin Image1.Picture.LoadFromFile(OPD.FileName); label1.caption := 'Depth : '+ Image1.Picture.Bitmap.RawImage.Description.Depth.ToString; label2.caption := 'BPP : '+ Image1.Picture.Bitmap.RawImage.Description.BitsPerPixel.ToString; end; end; procedure TForm1.Button2Click(Sender : TObject); var h,w : Longword; Dst, Src : PByte; bmpDst : TBitmap; begin bmpDst := TBitmap.Create; if Image1.Picture.Bitmap.RawImage.Description.BitsPerPixel = 24 then bmpDst.PixelFormat := pf24bit else bmpDst.PixelFormat := pf32bit; bmpDst.SetSize(Image1.Picture.bitmap.Width, Image1.Picture.bitmap.Height); for h := 0 to Image1.Picture.bitmap.Height-1 do begin Src := pByte(Image1.Picture.bitmap.RawImage.GetLineStart(h)); Dst := pByte(BmpDst.RawImage.GetLineStart(h)); if Image1.Picture.Bitmap.RawImage.Description.BitsPerPixel = 24 then begin for w := 0 to (Image1.Picture.bitmap.Width*3)-1 do begin // memo1.Lines.Add(IntToStr(w) +' '+ IntToStr(Src[w])); Dst[w] := Src[w]; end; end else if Image1.Picture.Bitmap.RawImage.Description.BitsPerPixel = 32 then begin for w := 0 to (Image1.Picture.Bitmap.Width*4)-1 do begin // memo1.Lines.Add(IntToStr(w) +' '+ IntToStr(Src[w])); Dst[w] := Src[w]; end; end; end; Image2.Picture.Bitmap.Assign(BmpDst); BmpDst.Free; end;
Resultat
et avec FondRGB 32bits XBGR
Comme on peut le voir le Depth et le BPP sont à 24 bits alors que le fichier BMP est bien un 32 bits. Vu qu'il n'y a pas de pixel transparent, Lazarus afin d'optimiser la taille prise en mémoire il le traite comme un 24 bits
[EDIT] Ton erreur viens à mon avis du PixelFormat de ton bitmap de destination qui est erroné
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Bonne nouvelle après plusieurs chargement de différent fichiers BMP provenant de ma "test-suite" il semblerai bien que le support du fichier BMP est été amélioré dans cette version 2.0
Certains fichiers BMP résistent encore et d'autres retournent toujours des valeurs erronées pour le Depth et BPP mais c'est déja bien mieux que les précédentes versions
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Comment se fait-il que je n'ai rien trouvé dans les liens donnés par Gilles concernant les informations de version ?
Tu devrais faire un test sous Linux,
Qu'est-ce que tu appelles bitmap de destination ? Le dst ou le Image2.Picture.Bitmap utilisé pour l'affichage ?
Dans l'attente de ta réponse, regarde ça, juste pour rire (le dst.PixelFormat est à 32) :
Ah, petit bug sans incidence : l'un des deux fichiers .bmp dans le zip, le 196x128x24.bmp,
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 image2.Picture.Bitmap.PixelFormat:=pf24bit; image2.Picture.Bitmap.LoadFromBitmapHandles(dst.Handle, dst.Handle, nil); memo1.Lines.Add(IntToStr(BitsPerPixel(image2.Picture.Bitmap.PixelFormat)) + ' bpp');// 24 image2.Picture.Bitmap.PixelFormat:=pf24bit; image2.Picture.Bitmap := dst; // affecte le pf du timage memo1.Lines.Add(IntToStr(BitsPerPixel(image2.Picture.Bitmap.PixelFormat)) + ' bpp');// 32
doit être renommé 192x128x24.bmp pour être en phase avec la réalité de son contenu. Désolé,
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
Bonjour,
j'ai passé la matinée sur ce $£µ*§@#&! de fichier, voilà mes conclusions : pour faire court et simple, le bug n'est pas dans le fichier, il est dans (ma vieille version de) Lazarus.
Faut voir maintenant si ça a changé avec la 2.0...
Je redonne le fichier : 32bitsKC.bmp.zip
Démonstration :
à coups d'éditeur hexa (voir + bas la grande image) on sait qu'à l'adresse 22 se trouve "size in bytes of the image, including padding".
Décortiquons :
@22..25 --> 90 d0 03 00 --> 3d090hex --> 250000déc, c'est la taille de l'image en bytes
@12..15 --> FA --> 250 (pixels) pour la largeur
@16..19 --> FA --> 250 (lignes) pour la hauteur
Taille de l'image / nombre de lignes = taille d'une ligne :
250000 / 250 = 1000 bytes
si on a 4 bytes par pixel ça nous donne 250 pixels par ligne, ça tombe bien, ça correspond au contenu de l'adresse 12..15 ;
si on a 3 bytes par pixel ça nous donne 333 pixels par ligne, ce qui ne correspond à rien et c'est ce qu'on voit d'affiché ("largeur" = largeur de la zone blanche quand la couleur commence -- là j'ai enlevé le stretch des TImage pour avoir un affichage 1/1 rogné) :
41 pixels de 4 bytes ça nous fait 164 bytes et c'est joli.
Et 164 bytes répartis dans des pixels de 3 bytes, ça nous fait 164 / 3 = 55 (arrondi) pixels, suivis par des pixels en vrac, ce qu'on voit sur l'image du bas.
La bonne question c'est : pourquoi Lazarus ne respecte-t-il pas le biBitCount qui est à 32 (20 à @1C) soit 4 bytes par pixel pour ce fichier ?
Voilà ce qu'en disait le grand gourou il y a deux ans :
Sauf qu'on ne trouve rien de particulier dans le fichier, il a la même structure que d'autres 32 bits qui s'ouvrent sans problème, c'est tout.
Et surtout, il s'ouvre bien avec Gimp, ImageJ, ImageMagick, LibreOffice et le visionneur par défaut sous Linux, ainsi qu'avec XnView, en insertion d'objet dans Wordpad et dans un message OutlookExpress sous XP.
Il n'y a qu'avec Lazarus que ça coince.
Un peu la même histoire qu'ici, où l'OP commence par incriminer Gimp quand au final c'est son logiciel périmé qui est en cause.
Ce qui est ennuyeux (et hallucinant), c'est qu'ouvrir ce fichier avec Gimp et le récrire ensuite génère un fichier VersionHeader 4 avec les datas en plus qui vont bien, mais il s'ouvre toujours aussi mal avec Lazarus, alors que d'autres fichiers avec la même structure et la même version du header s'ouvrent très bien.
Récrit sans les informations de couleur (= header v1) donne le même résultat foireux.
Donc la seule chose qui ne change pas dans toutes ces manips, ce sont les dimensions du fichier.
Y aurait-il des tests bizarres à l'ouverture qui font que 250 ET 250 ET 1000 génèrent un défaut ? Nul ne le saura jamais, à moins d'aller voir au fin fond des routines qui font le boulot...
Lecture intéressante à propos du format bmp.
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
Salut
Parce que c'est juste de petits changements (genre changement de type) mais qui font la différence
Je parlais bien de Dst par contre utilises plutôt image2.Picture.Bitmap.assign(Dst) que image2.Picture.Bitmap := Dst;Et oui il faut verifier que "Image2" est également le même nombre de bits. Car si ta copie est correcte du coup l'affichage lui ne le sera pas
Sinon l'exemple que j'ai mis hier il fonctionne ou pas ?
Avec l'exemple que je t'ai donné hier (toujours avec Lazarus 2.0 et sous Win tout est correcte
Je testerai d'ici demain sous Linux pour comparer
Pour ma part si je me souviens bien je n'utilise pas cette donnée dans ma solution. Car si tu tombe sur un fichier mal encodé tu l'a dans baba.
Je l'ai dis hier, c'est pour optimiser l'utilisation en mémoire. Avec certains BMP 32Bits Vu qu'il n'y a aucun pixel transparent Lazarus le charge et le stock comme une image 24bits. Je sais c'est déconcertant et moi aussi je n'aime pas cette façon de faire.
Ces erreurs dans la description viennent du fait que la méthode de chargement du format BMP comportent quelques erreurs et notamment dans la gestion et le calcul des "BittFields" et j'avais découvert (dans une nos discussions) un bout de code qui fautif qui pouvait provoquer ce changement de bits (A cause d'un calcul avec la valeur Alpha)
C'est pourquoi, Le RawImage ne reflette pas toujours les spécifications des fichiers chargés essentiellement avec le format BMP 32bits ou les spécifications ne sont pas prises correctement en compte dans le code de chargement.
C'est pour cela que dans ma solution pour stocker les bitmap j'utilise exclusivement une structure 32bits, mais je conserve les informations originales qui se trouvent dans les headers des fichiers. (ex je charge un BMP 16bits je retrouve cette donnée dans mes infos mais l'image elle, est stockée en 32bits (je convertit les couleurs) Et lorsque je veux manipuler les pixels, je n'ai pas à me soucier du nombre de BitsPerpPixel et lors de l'export je peux me référer aux infos de base pour réencoder le fichier avec le nombre bits d'origine.
Plus simple et pas de prise de tête.
A+
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Je t'ai répondu là à 17 h 44 que c'était la cata...
Ah !
Je t'attends de pied ferme, je ne bouge pas (sauf que demain aprème ch'suis pas dispo, mais bon, ça fait un mois que je suis là-dessus, je ne suis plus à qq heures près...)
Déjà que je l'ai dans le baba même quand le fichier est bien encodé...
Je remets ce qu'on dirait que tu as zappé :
Je pense plutôt à des vieux bugs, parce qu'optimiser la mémoire, euh, ça se saurait, non ?Envoyé par Jipété
+++
Les dernières nouvelles et après je plie, j'en ai trop marre.
'tention c'est du lourd, mahousse costaud...
J'ai bien dit que je voulais travailler au niveau des bytes, et j'avais l'impression en fin de matinée que je tenais le bon bout, puisque mis à part le fichier 32bitsKC, l'outil réagit correctement pour ouvrir 24 et 32 bits et les afficher par l'intermédiaire du bitmap 32 bits dans un TImage (image2) configuré en 32 bits.
Bien.
Pour vérifier que j'ai accès aux bytes, je décide de recopier ceux de l'image2 dans une image3 qui n'attend que ça, sauf que ça ne se passe pas du tout comme prévu !
Incroyable : j'avais prévu d'inverser les couleurs mais avec les streams, ça ne veut rien savoir, et si je choisis un fichier à largeur exotique (397), bonjour le retour des rayures :
Donc je décide un retour aux pointeurs de bytes, là les couleurs s'inversent bien mais les rayures c'est pire :
Je suis anéanti.
Je n'aurais jamais imaginé que ça puisse être aussi compliqué de recopier des bytes d'un TImage à l'autre alors qu'ils sont tous les deux à la même taille et au même pixelformat.
Bon, j'ai autre chose à faire...
Ah, le code :
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
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 procedure TForm1.trkTranspChange(Sender: TObject); var w,h: integer; // pb avec les largeurs exotiques... pbS,pbD: pByte; // voir comment est la source en pf tmpbyte: byte; // --> 32 32 tt le temps :koi: aByte: byte; mss: TMemoryStream; function GetOffsetToDatas(b: TBitmap): integer; var bs: TBytesStream; begin bs := TBytesStream.Create; b.SaveToStream(bs); bs.Position:=10; GetOffsetToDatas := bs.ReadDWord; bs.Free; end; begin image3.Picture.Bitmap.PixelFormat:=image2.Picture.Bitmap.PixelFormat; image3.Picture.Bitmap.Width :=image2.Picture.Bitmap.Width; image3.Picture.Bitmap.Height:=image2.Picture.Bitmap.Height; memo1.Lines.Add('i2-'+IntToStr(BitsPerPixel(image2.Picture.Bitmap.PixelFormat)) + ' bpp'); memo1.Lines.Add('i3-'+IntToStr(BitsPerPixel(image3.Picture.Bitmap.PixelFormat)) + ' bpp'); image3.Picture.Bitmap.BeginUpdate(); for h := 0 to image1.Picture.Bitmap.Height-1 do begin pbS := pByte(image2.Picture.Bitmap.RawImage.GetLineStart(h)); pbD := pByte(image3.Picture.Bitmap.RawImage.GetLineStart(h)); for w := 0 to (image2.Picture.Bitmap.Width*4)-1 do begin pbD[w] := pbS[w]; if ((w + 1) mod 4 = 0) then begin // = tous les 4 bytes // inverser R et B pour jouer, dans la destination tmpbyte := pbD[w-3]; pbD[w-3] := pbD[w-1]; pbD[w-1] := tmpbyte; // transparence pbD[w] := trkTransp.Position; end; end; end; image3.Picture.Bitmap.EndUpdate(); // PASSER PAR LES STREAMS ? NAN ! Les couleurs ne sont pas inversées { mss := TMemoryStream.Create; image2.Picture.Bitmap.SaveToStream(mss); // taille du stream s'adapte automagiquement mss.Position := GetOffsetToDatas(image2.Picture.Bitmap); image3.Picture.Bitmap.BeginUpdate(); for h := image2.Picture.Bitmap.Height-1 downto 0 do begin // parcours inversé pour les streams pbD := pByte(image3.Picture.Bitmap.RawImage.GetLineStart(h)); for w := 0 to (image2.Picture.Bitmap.Width*4)-1 do begin aByte := mss.ReadByte; //memo1.Lines.Add(IntToStr(w)+' '+IntToStr(aByte)); pbD[w] := aByte; if ((w + 1) mod 4 = 0) then begin // = tous les 4 bytes // inverser R et B pour jouer, dans la destination { tmpbyte := pbD[w-1]; pbD[w-1] := pbD[w-3]; pbD[w-3] := tmpbyte; } // une manière ou l'autre = pas d'inversion, alors qu'avec les pBytes oui. tmpbyte := pbD[w-3]; pbD[w-3] := pbD[w-1]; pbD[w-1] := tmpbyte; // transparence pbD[w] := trkTransp.Position; end; end; end; image3.Picture.Bitmap.EndUpdate(); mss.Free; } end;
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
Résultat des manips de la fin d'aprème (c'est l'enfer)
Contexte :
1 fichier de 37 px de large et 1 ligne de haut en 32 bits (le marron qu'on voit à droite, c'est... le bras de Léna, après le damier, si si !) ;
3 TImage avec Stretch à True (sinon on ne voit rien) ;
tout est en pf32bit.
De haut en bas,
- image1, utilisée comme témoin après chargement du fichier ;
- image2, chargée à travers la "boîte noire" et affiché avec un soupçon de flou : lié au strech ? Je ne sais pas ;
- image3, la catastrophe suite à recopie par streams (avec les pBytes c'est pareil), des bytes de l'image2 ;
- The Gimp a ouvert et zoomé sur un fichier généré très simplement par image2.SaveToFile('chemin/image2.bmp');.
(j'ai légèrement globalement réduit tout ça, histoire de tout avoir sous les yeux)
Si quelqu'un peut m'expliquer pourquoi la jolie image de la ligne 2 génère un truc aussi moche à travers une instruction de haut niveau sur laquelle je n'ai aucun contrôle, ça serait cool.
Encore deux heures de perdues en essais infructueux et autres prises de tête.
Le code ?
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
16
17
18
19 // PASSER PAR LES STREAMS mss := TMemoryStream.Create; msd := TMemoryStream.Create; image2.Picture.Bitmap.SaveToStream(mss); // taille du stream s'adapte automagiquement image2.Picture.Bitmap.SaveToStream(msd); // taille du stream s'adapte automagiquement mss.Position := GetOffsetToDatas(image2.Picture.Bitmap); msd.Position := GetOffsetToDatas(image2.Picture.Bitmap); for x := 0 to (image2.Picture.Bitmap.Height * image2.Picture.Bitmap.Width * 4)-1 do begin msd.WriteByte(mss.ReadByte); if ((x + 1) mod 4 = 0) then begin // = tous les 4 bytes // transparence msd.Position := msd.Position-1; // reculer de 1 car ReadByte a fait avancer automatiq. msd.WriteByte(byte(trkTransp.Position)); end; end; msd.Position := 0; image3.Picture.Bitmap.LoadFromStream(msd, msd.Size); mss.Free;
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
Salut Jipete,
je vais te faire sourire (un peu, enfin j'espère). Hier soir j'ai fais quelques test en repartant du dernier bout de code que j'ai mis. Ne manipulant jamais les bitmaps sous Linux hors-mis l'utilisation d'un TImage pour afficher une image, j'ai vite déchanté.
Je comprend mieux ta frustration et pourquoi tu pleures. Déja que sous Windows manipuler des bitmap est bien galère, mais sous Linux, l'utilisation d'un TBitmap couplé à un TImage, comment dire ? tout simplement ingérable. Ou est donc passé le "Write once, compil everywhere". Le manque de synchronisme entre Windows et Linux est une vrai catastrophe avec les TBitmap/TImage.
En effet l'exemple que j'avais produit qui fonctionne très bien sous Windows ben sous Linux non. Ce qui est du surnaturel pour un exemple aussi basique, on dirait avoir des codes sources totalement différents
Avant de donner quelques explications et surtout dire ce qui NE FONCTIONNE PAS voici quelques screenshot. En piece jointe un petit zip JipeteBMP.zip contenant l'application et les fichiers BMP avec lesquels j'ai réalisé mes petites expériences (on se croirait vraiment dans le laboratoire de minus et cortex )
L'application test : On charge un fichier dans un TImage on en fait une copie en recopiant les pixels un à un dans un TBitmap temporaire, puis on ré-affiche cette copie dans un second TImage. Rien de bien méchant (A LA BASE)
Allons-y et commençons par les descriptions des tests !!! (Regardez bien la différence des valeurs de Depth et BitsPerPixels des TImage entre les 2 OS)
A gauche Linux, à droite Windows
Je lance l'application
J'ouvre le premier fichier 3x2x24_vh1.bmp
Ici tout fonctionne, normalement. Sauf que comparer à Windows, lors de la copie il faut inverser les composantes de couleur Rouge et Bleu. (Il m'a donc fallut blinder le code de {$IFDEF LINUX}...{$ELSE}
J'ouvre le deuxième fichier 32bitsKC.bmp
Ici du début à la fin c'est clair que cela ne fonctionne pas. Dans ce cas ici je penche qu'il y a un soucis dans la procedure de chargement du fichier BMP ?, Bizarre car ce fichier s'affiche correctement sous Windows, non ce n'est par là
Troisième fichier FondRVB32_xbgr.bmp
Pas de soucis, niveau affichage et pour la copie. Sauf que regardez le Depth de l'image 1 après chargement il est à 24 au lieu de 32. Ensuite comparer le BitperPixels de l'image 1 après le chargement et celui après l'assignation de l'Image 2
Hum, hum
Enfin le dernier et quatrième fichier rgb32bfdef.bmp
Ici comment dire ça saute aux yeux, l'affichage dans l'image 2 est foireuse, pourquoi ??? mystère et boule de gomme ? A mon avis encore une erreur interne. Lorsque l'on compare le Depth de l'image 2 avant et après assignation cette valeur passe de 24 à 32 mais à l'affichage il s'emblerai que celle-ci reste à 24. Le problème c'est ou se trouve cette erreur interne. Dans le code source du TImage ou dans la procedure d'affichage ?
Pour les 2 autres fichiers présent dans l'archive je vous laisse tester (ces 2 fichiers sont des bmp 32bits parfaitement encodé pour info)
Conclusion
La manipulation des TBitmap couplé au TImage est une misère sans nom sous Linux. Il y a sérieusement des incohérences dans la gestion du tampon et des informations contenue dans le RawImage sous Linux.
Je comprend mieux pourquoi tu t'arraches les cheveux à essayer de comprendre.
Pour la défense les tests sous Linux ont été réalisé avec la version 1.8.4 (la 2.0 n'étant pas encore disponible dans mes dépots et la flemme de faire une installation manuelle) et sous windows la version 2.0
Je retesterai sous Linux dès que la version 2.0 de Lazarus sera disponible dans mes dépots pour voir si ce problème à été corrigé.
A mon humble avis, si tu veux manipuler des bitmaps (sous Linux) je te conseillerai vivement comme Gilles te l'a suggéré d'apprendre à utiliser BGRABitmap (en attendant que je puisse fournir les codes de ma solution, sur laquelle je me suis remis à plancher cette semaine )
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Salut Jér' !
Tu tombes bien, j'allais plier (suis absent c't'aprème)
Merci pour ton long post, je le regarderai ce soir.
Voilà ce que j'ai vécu hier soir :
J'avais commencé doucement par ça, confiant :
et là je me suis dit "ouh la la..."
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 with image3.Picture.Bitmap do begin PixelFormat := pf32bit; showmessage(inttostr(BitsPerPixel(PixelFormat)));// 32 LoadFromStream(msd, msd.Size); // un stream qui contient la photocopie d'un bitmap, header+datas showmessage(inttostr(BitsPerPixel(PixelFormat)));// 24 !???! end;
J'ai continué avec tout ce fourbi :
Quand j'enregistre msd sur le Bureau, ça génère une image parfaite (miniature, examen à l'éditeur hexa = ras)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 with bmp do begin PixelFormat := pf32bit; showmessage(inttostr(BitsPerPixel(PixelFormat)));// 32 Width := image2.Picture.Bitmap.Width; showmessage(inttostr(BitsPerPixel(PixelFormat)));// 32 Height := image2.Picture.Bitmap.Height; showmessage(inttostr(BitsPerPixel(PixelFormat)));// 32 LoadFromStream(msd, msd.Size); showmessage(inttostr(BitsPerPixel(PixelFormat)));// 24 bim ! end;
Donc
Alors ce matin je me suis dit que j'allais feinter comme ça :
Mais pas mieux...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 with bmp do begin PixelFormat := pf32bit; showmessage(inttostr(BitsPerPixel(PixelFormat)));// 32 Width := image2.Picture.Bitmap.Width; showmessage(inttostr(BitsPerPixel(PixelFormat)));// 32 Height := image2.Picture.Bitmap.Height; showmessage(inttostr(BitsPerPixel(PixelFormat)));// 32 msd.SaveToFile('/chemin/msd.bmp');// vu à l'éditeur hexa le fichier est bien en pf32 LoadFromFile('/chemin/msd.bmp'); showmessage(inttostr(BitsPerPixel(PixelFormat)));// 24 re-bim ! J'en peux plus... end;
Tu parles de bgra : tu crois que c'est possible, ce que je voudrais ? Intervenir au niveau des pixels ?
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Vit' vit' avant que je file.
ça me démangeait trop, j'ai testé : partant d'une bête image jpeg trouvée sur le web, je l'ai ouverte avec The Gimp et l'ai redimensionnée à 250 x 250 x 32 bpp.
Elle a donc exactement la même taille que le fichier 32bitsKC.bmp et que croyez-vous qu'il arrivât lors de son affichage avec le bazar Lazarus ?
Des traits verticaux...
J'm'marre... jaune...
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
Salut,
En effet il y a clairement un problème sous Linux dans le chargement de certains fichiers BMP. Je te rassure hier j'ai également testé avec des PNG (avec transparence) chargement correct dans l'image1 mais à la copie dans le Image2 paf Il est clair que le tampon des données (Le RawImage) n'est pas (ré)initialiser correctement. Je pense qu'il y a un oublis dans la procedure Assign du TBitmap.
Une solution que je n'ai pas testé serait peut-être de passer par un TLazIntfImage pour contourné le problème.
[EDIT] Pour s'en assurer au lieu d'utiliser un TImage pour afficher la copie du bitmap il faudrait tester avec Canvas.StretchDraw ou Draw directement dans un TPanel par exemple
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Yop !
Il faudrait que je le confirme, mais il me semble qu'il bascule systématiquement les sources pf32 en pf24 (ou alors c'est moi qui ne sais pas l'utiliser, mais comme je n'ai jamais trouvé un tuto simple, clair, précis et complet, et qu'il n'y a pas d'aide, ben voilà, quoi...)
Avec ça :
Donc résultat :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 procedure TForm1.PanelPaint(Sender: TObject); begin with Sender as TPANEL do Canvas.StretchDraw(ClientRect, aBmp); end;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 mss.LoadFromFile(opd.FileName); mss.Position:=0; aBmp.LoadFromStream(mss, mss.Size); mss.Position:=0; // en vrac dans le panel si fichier de 250 de large mss.SaveToFile('/chemin/mss.bmp'); mss.Position:=0; // miniature ok
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
Le problème vient donc de "StretchDraw", il y'a surement une erreur d'utilisation de l'Api GTK ou une mauvaise conversions des données.
Tu peux essayer de tester également avec Draw pour voir si le problème persiste aussi avec ?
Faudrait tester avec QT également pour confirmer et affiner la position ou se trouve le bug. Donc voila l'appel est lancé si quelqu'un est sous Linux et utilise Lazarus avec l'environnement QT, il est le bienvenue
Ces fonctions d'affichage sont tellement de bas niveau que c'est une vrai galère à déboguer pour trouver ou est ce que ça cloche. Si j'arrive à trouver je pourrais soumettre un rapport de bug dans ce sens. Mais je testerai avant avec la 2.0 dès qu'elle sera dispo dans mes dépôts.
- "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
- "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
- "La simplicité est la sophistication suprême" - Léonard De Vinci
- "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei
Mes projets sur Github - Blog - Site DVP
Confirmé (lire le commentaire en bas du code) :
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
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 function load(f: String): TBitmap; var Pict: TPicture; lii: TLazIntfImage; function GetOffsetToDatas(b: TBitmap): integer; var bs: TBytesStream; begin bs := TBytesStream.Create; b.SaveToStream(bs); bs.Position:=10; Result := bs.ReadDWord; bs.Free; end; begin Pict := TPicture.Create; Pict.LoadFromFile(f); RESULT := TBitmap.Create; RESULT.PixelFormat:=pf32bit; lii := TLazIntfImage.Create(0,0); try if GetOffsetToDatas(Pict.bitmap) = 54 then begin lii.DataDescription := GetDescriptionFromDevice(0); lii.LoadFromFile(f); end else // 70, 122 pour bgra, 138 pour xbgr, n/a pour jpg et d'autres encore lii.LoadFromBitmap(Pict.bitmap.Handle, Pict.bitmap.Handle, Pict.bitmap.Width, Pict.bitmap.Height); RESULT.LoadFromIntfImage(lii); // renvoie un bitmap "bien" rempli mais en pf24 si pf32 en entrée finally lii.Free; end; Pict.Free; end;
Comme ça ? :
Tout autant cassé, sauf que l'image n'est pas stretchée.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 procedure TForm1.PanelPaint(Sender: TObject); begin with Sender as TPANEL do // Canvas.StretchDraw(ClientRect, aBmp); Canvas.Draw(0,0, aBmp); end;
Ah, j'ai mis un petit zip avec 2 projets et qq bmp dans l'autre fil d'aujourd'hui, tout en bas.
Pourquoi veux-tu descendre aussi bas ? Ce n'est plus notre problème de simples utilisateurs : quand on constate que la voiture tire à gauche, on l'emmène chez le garagiste, à lui de la passer au banc et de régler le parallélisme.
Ça ne va pas prendre des mois, cette affaire ?
Si je devais réinstaller ma machine, je me retrouverais en... 1.2.4 !
Heureusement que je zappe les dépôts pour passer par l'install des .deb à la mano.
Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peut–être qu'il peut être sûr, etc.
Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
Mes 2 cts,
--
jp
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager