Bonjour,
Je dois encoder une image en Base 64 pour effectuer un transfert vers un webservice en XML.
Comment faire ??
Merci
Bonjour,
Je dois encoder une image en Base 64 pour effectuer un transfert vers un webservice en XML.
Comment faire ??
Merci
Attention le .NET sur PDA peut causer des chutes de cheveux
En utilisant une fonction encode64 qui doit être disponible avec les composants XML ou ça (en le modifiant pour utiliser un stream): http://www.swissdelphicenter.ch/torry/showcode.php?id=1524
En gros, tu enregistres ton image dans un TMemoryStream.
Ensuite, tu récupère le contenu de celui par 3 octets, que tu stocke chaque fois dans un LongWord (4ème octet à 0 bien entendu).
Après, tu fais qutre and binaires pour récupérer les 24 bits par 6 (6 bits = base 64).
Tu n'as plus qu'à stocker ces 6 bits dans un Byte (deux derniers bits à 0) et finalement récupérer le Xème caractère d'une chaîne de 64 caractère contenant les caractères de ta base.
Attention : après avoir récupéré les 3 octets, tu dois les inverser pour obtenir le format Big Endian.
Au niveau du code, ça devrait donner quelque chose comme ça :
Tu noteras qu'avant l'appel à cette fonction, tu dois vérifier que ton stream possède bien un multiple de 3 octets. Si ce n'est pas le cas, tu dois ajouter les 0 manquant au début.
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 function StreamToBase64(Stream : TStream) : string; type TTroisOctets = record // A cause du format Big Endian case integer of 0 : (Int : LongWord); 1 : (Bytes : array[0..3] of Byte); end; const Base64 : string = '01234567789ABCDEFGH...'; // tu dois avoir 64 caractères var TroisOctets : record; SixBits : Byte; begin Stream.Seek(0, soFromBeginning); Result := ''; while Stream.Position < Stream.Size do begin Stream.ReadBuffer(TroisOctets, 3); // Ici on va renverser les quatre octets de TroisOctets TroisOctets.Bytes[3] := TroisOctets.Bytes[0]; TroisOctets.Bytes[0] := TroisOctets.Bytes[1]; TroisOctets.Bytes[1] := TroisOctets.Bytes[2]; TroisOctets.Bytes[2] := TroisOctets.Bytes[0]; TroisOctets.Bytes[0] := 0; // Fin du renversement SixBits := Byte(TroisOctets.Int and 63); // bits 0-5 Result := Result+Base64[SixBits]; SixBits := Byte((TroisOctets.Int and 4032) shr 6); // bits 6-11 Result := Result+Base64[SixBits]; SixBits := Byte((TroisOctets.Int and 258048) shr 12); // bits 12-17 Result := Result+Base64[SixBits]; SixBits := Byte((TroisOctets.Int and 16515072) shr 16); // bits 18-23 Result := Result+Base64[SixBits]; end; end;
sjrd, ancien rédacteur/modérateur Delphi.
Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
Découvrez Mes tutoriels.
Merci à vous deux, je pense que la méthode de sjrd me semble la plus aproprié, je vais donc tester cette méthode la (t'inquietes pas cpdump, j'avais commencé à transformer la fonction de Torry, mais c'était pas gagné ).
juste quelques questions ca :je comprend pas comment ca marche, en plus on peu pas declarer des array dans un record [EDIT] ahh, ben non ca passe si il y a pas de case, GG le compilo pr le message [/EDIT]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 TTroisOctets = record // A cause du format Big Endian case integer of 0 : (Int : LongWord); 1 : (Bytes : array[0..3] of Byte); end;
Bon, ca mis a part, ce que je pige pas c'est comment il trouve la valeur de 'integer' (case integer of...).
Si tu peux m'éclairer, merci.
Attention le .NET sur PDA peut causer des chutes de cheveux
Voila, je me suis permis d'interpréter ton code comme suit :
Comme ca ca compile mais je ne sais pas si je fais une bétise en virant le case.
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 function TMenuPrincipal.StreamToBase64(Stream : TStream) : string; type TTroisOctets = record // A cause du format Big Endian Int : LongWord; Bytes : array[0..3] of Byte; end; var TroisOctets : TTroisOctets; SixBits : Byte; Bytez : array[0..3] of Byte; const Base64 : string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/'; begin Stream.Seek(0, soFromBeginning); Result := ''; while Stream.Position < Stream.Size do begin Stream.ReadBuffer(TroisOctets.Bytes, 3); // Ici on va renverser les quatre octets de TroisOctets TroisOctets.Bytes[3] := TroisOctets.Bytes[0]; TroisOctets.Bytes[0] := TroisOctets.Bytes[1]; TroisOctets.Bytes[1] := TroisOctets.Bytes[2]; TroisOctets.Bytes[2] := TroisOctets.Bytes[0]; TroisOctets.Bytes[0] := 0; // Fin du renversement SixBits := Byte(TroisOctets.Int and 63); // bits 0-5 Result := Result+Base64[SixBits]; SixBits := Byte((TroisOctets.Int and 4032) shr 6); // bits 6-11 Result := Result+Base64[SixBits]; SixBits := Byte((TroisOctets.Int and 258048) shr 12); // bits 12-17 Result := Result+Base64[SixBits]; SixBits := Byte((TroisOctets.Int and 16515072) shr 16); // bits 18-23 Result := Result+Base64[SixBits]; end; end;
Merci, si ca marche je mettrai en résolu, en att je teste.
A dans quelques minutes
Attention le .NET sur PDA peut causer des chutes de cheveux
Erg, ca bloque sur la ligne
La première.
Code : Sélectionner tout - Visualiser dans une fenêtre à part Result := Result+Base64[SixBits];
le message c'est :
SixBits vaut 0 à ce moment laIndex was outside the bounds of the array
Merci,
Attention le .NET sur PDA peut causer des chutes de cheveux
C'est une construction qui permet d'avoir deux suites de champs qui sont enregistrés au même endroit. Donc si tu modifies Int, les Bytes seront modifiés aussi et vice versa. En fait Bytes[0] à la même adresse que IntEnvoyé par Harry
Tu dis qu'on ne peut pas mettre de tableau dans un record, c'est faux ; j'en suis absolument certain.
Par contre il ne faut surtout pas supprimer le case integer of, car dans mon code je me base justement sur let fait que Int et Bytes ont même adresse.
Es-tu certain que le compilo n'accepte pas le code tel que je l'ai écrit ? Si c'est bien le cas peux-tu me dire quel est le message exact du compilo et à quel endroit ?
Pour ce qui est de la valeur de integer, il s'en fout. C'est la construction qui impose ce truc. En fait tu pourrais aussi bien mettre n'importe quel type ordinal (donc pas de chaîne), en adaptant les valeurs possibles. Tu peux même mettre boolean avec True et False !
Voilà j'espère que j'ai été clair sinon n'hésite pas à poser d'autres questions .
sjrd, ancien rédacteur/modérateur Delphi.
Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
Découvrez Mes tutoriels.
J'ai repris ton code d'origine et j'ai juste complété la chaine de 64 caractères et le compilateur s'arrete sur :
Avec le message
Code : Sélectionner tout - Visualiser dans une fenêtre à part 1 : (Bytes : array[0..3] of Byte);
Voila, j'espere que tu pourras m'aider.[Erreur] Menu.pas(1040): E2418 Le type 'Array' nécessite une initialisation - interdite dans un enregistrement variant
Merci,
A ++
[Edit] Remarque : je travaille sous Delphi 2005 en VCL, j'ai essaye ton code sous Delphi 4 et il compile après avoir modifié la declaration de variables comme suit :[/Edit]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 var TroisOctets : TTroisOctets; SixBits : Byte;
Attention le .NET sur PDA peut causer des chutes de cheveux
erreur d'inattention En effet c'est TTroisOctets le type.Envoyé par Harry
Apparemment c'est une évolution du langage sour D2005. C'est vrai que j'ai pas encore utilisé cette syntaxe sour D2005.
Je te propose ceci alors :
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 function StreamToBase64(Stream : TStream) : string; type TTroisOctets = record // A cause du format Big Endian case integer of 0 : (Int : LongWord); 1 : (Byte0, Byte1, Byte2, Byte3 : Byte); end; const Base64 : string = '01234567789ABCDEFGH...'; // tu dois avoir 64 caractères var TroisOctets : TTroisOctets; SixBits : Byte; begin Stream.Seek(0, soFromBeginning); Result := ''; while Stream.Position < Stream.Size do begin Stream.ReadBuffer(TroisOctets, 3); // Ici on va renverser les quatre octets de TroisOctets TroisOctets.Byte3 := TroisOctets.Byte0; TroisOctets.Byte0 := TroisOctets.Byte1; TroisOctets.Byte1 := TroisOctets.Byte2; TroisOctets.Byte2 := TroisOctets.Byte0; TroisOctets.Byte0 := 0; // Fin du renversement SixBits := Byte(TroisOctets.Int and 63); // bits 0-5 Result := Result+Base64[SixBits]; SixBits := Byte((TroisOctets.Int and 4032) shr 6); // bits 6-11 Result := Result+Base64[SixBits]; SixBits := Byte((TroisOctets.Int and 258048) shr 12); // bits 12-17 Result := Result+Base64[SixBits]; SixBits := Byte((TroisOctets.Int and 16515072) shr 16); // bits 18-23 Result := Result+Base64[SixBits]; end; end;
sjrd, ancien rédacteur/modérateur Delphi.
Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
Découvrez Mes tutoriels.
Merci, ca accepte la déclaration de variables come ca
Par contre je suis coincé sur :
Le message rendu par le compilateur est :
Code : Sélectionner tout - Visualiser dans une fenêtre à part Stream.ReadBuffer(TroisOctets, 3);
Merci,[Erreur] Menu.pas(1051): E2250 Aucune version surchargée de 'ReadBuffer' ne peut être appelée avec ces arguments
Et désolé de te faire debugger comme ca , mais l'aide de delphi 2005 est un peu embrouillé du fait du mélange de languages et en plus orienté fortement vers le C#.
Attention le .NET sur PDA peut causer des chutes de cheveux
Aïe. Ca c'est vraiment bizarre
Essaye ceci :
Et si pas ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part Stream.ReadBuffer(@TroisOctets, 3);
Mais j'ai aucune garantie
Code : Sélectionner tout - Visualiser dans une fenêtre à part Stream.ReadBuffer(TroisOctets^, 3);
Au pire, ajoute une variable de type LongWord comme ceci :
end;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 function StreamToBase64(Stream : TStream) : string; ... var LgWord : LongWord; TroisOctets : TTroisOctets; SixBits : Byte; begin ... while Stream.Position < Stream.Size do begin Stream.ReadBuffer(LgWord, 3); TroisOctets.Int := LgWord; ... end; end;
sjrd, ancien rédacteur/modérateur Delphi.
Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
Découvrez Mes tutoriels.
Yess, on y est presque, tes 2 premiers idées ne passent pas, par contre le 'Au pire' lui, ca marche niquel (mais pourquoi j'y ai pas pensé ), enfin ca compile niquel.
Lors de l'execution le code s'arrete sur
(le premier)
Code : Sélectionner tout - Visualiser dans une fenêtre à part Result := Result+Base64[SixBits];
avec comme message d'erreur :
Merci,Index was outside bounds of the array
A++
Attention le .NET sur PDA peut causer des chutes de cheveux
Arf ! Idiot que je suis !
Il faut mettre Base64[SixBits+1]
On va y arriver
sjrd, ancien rédacteur/modérateur Delphi.
Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
Découvrez Mes tutoriels.
Merci
Ca marche presque, juste ca bloque au dernier
Avec le meme message.
Code : Sélectionner tout - Visualiser dans une fenêtre à part Result := Result+Base64[SixBits +1];
Mais c'est peut etre de ma faute! voici le code que j'ai fait pour ajouter le 0 devant pour que le stream soit un multiple de 3 en longeur.
decal est un byte avec 0 dedans.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 decal := 0; streambis := TMemoryStream.Create; if (i mod 3) > 0 then begin streambis.Write(decal,sizeof(decal)); streambis.CopyFrom(Stream, 0); stream := streambis; end;
je sais pas pourquoi mais j'ai l'impression de chercher midi a 14h
Merci
Attention le .NET sur PDA peut causer des chutes de cheveux
Avec le décalage de streams, il fautEnvoyé par Harry
Mais je te conseille plutôt ce code-ci :
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 var Zero : integer; StreamBis : TStream; ... Zero := 0; if Stream.Size mod 3 > 0 then begin StreamBis := TMemoryStream.Create; try StreamBis.Write(Zero, 3 - Stream.Size mod 3); StreamBis.CopyFrom(Stream, 0); Stream.Seek(0, soFromBeginning); Stream.CopyFrom(StreamBis, 0); finally StreamBis.Free; end; end;
sjrd, ancien rédacteur/modérateur Delphi.
Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
Découvrez Mes tutoriels.
Ok, en fait le problème persiste, voici le code dans son état actuel :
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 function TMenuPrincipal.StreamToBase64(Stream : TStream) : string; type TTroisOctets = record // A cause du format Big Endian case integer of 0 : (Int : LongWord); 1 : (Byte0, Byte1, Byte2, Byte3 : Byte); end; const Base64 : string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/'; //64 caractères var TroisOctets : TTroisOctets; SixBits : Byte; LgWord : LongWord; i, Zero : integer; Streambis : TStream; begin Zero := 0; if Stream.Size mod 3 > 0 then begin StreamBis := TMemoryStream.Create; try i := (3 - (Stream.Size mod 3)); StreamBis.Write(Zero, i); StreamBis.CopyFrom(Stream, 0); Stream.Seek(0, soFromBeginning); Stream.CopyFrom(StreamBis, 0); finally StreamBis.Free; end; end; i := stream.Size; Showmessage(IntToStr(i)); Stream.Seek(0, soFromBeginning); Result := ''; while Stream.Position < Stream.Size do begin Stream.ReadBuffer(LgWord, 3); TroisOctets.Int := LgWord; // Ici on va renverser les quatre octets de TroisOctets TroisOctets.Byte3 := TroisOctets.Byte0; TroisOctets.Byte0 := TroisOctets.Byte1; TroisOctets.Byte1 := TroisOctets.Byte2; TroisOctets.Byte2 := TroisOctets.Byte0; TroisOctets.Byte0 := 0; // Fin du renversement SixBits := Byte(TroisOctets.Int and 63); // bits 0-5 Result := Result+Base64[SixBits +1]; SixBits := Byte((TroisOctets.Int and 4032) shr 6); // bits 6-11 Result := Result+Base64[SixBits +1]; SixBits := Byte((TroisOctets.Int and 258048) shr 12); // bits 12-17 Result := Result+Base64[SixBits +1]; SixBits := Byte((TroisOctets.Int and 16515072) shr 16); // bits 18-23 Result := Result+Base64[SixBits +1]; end; end;
A l'execution ca plante sur la dernière ligne :
avec comme message :
Code : Sélectionner tout - Visualiser dans une fenêtre à part Result := Result+Base64[SixBits +1];
Merci pour toutIndex was outside bounds of the array
Attention le .NET sur PDA peut causer des chutes de cheveux
Est ce que tu utilises un composant xml pour gérer tes fichiers xml ? parce les fonctions encode64 sont intégrés dans les compostants xml. Ca serais plus rapide que de perder son temps à chercher un bug dans le code ta fonction.
J'utilise le composant TXMLDocument, mais c'est une photo que je veux encoder en base 64.
Et je n'ai pas trouvé la moindre méthode pour encoder en Base 64 avec ce composant
Si il y en a un bien caché je suis toute ouie
Attention le .NET sur PDA peut causer des chutes de cheveux
Généralement les composants xml ont des fonction encode/decode64 puisque c'est le moyen de stocker les infos binaires. C'est disponible aussi avec les composants Internet type Indy ou ICS.
Sinon regarde ici: http://www.szutils.net/Delphi/Delphi.php
Évalue un peu la valeur de SixBits juste avant d'exécuter cette instruction.Envoyé par Harry
sjrd, ancien rédacteur/modérateur Delphi.
Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
Découvrez Mes tutoriels.
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