Bonjour,
y a t il un moyen (simple si possible !) de savoir si un fichier Jpg, jpeg, gif ou png est une image valide ?
merci
A+
Charly
Bonjour,
y a t il un moyen (simple si possible !) de savoir si un fichier Jpg, jpeg, gif ou png est une image valide ?
merci
A+
Charly
Mon site : http://lapaille.byethost24.com/index.htm
Pour compléter : Exemple d'images gif non valides :
Images Non Valides.zip
A+
Charly
Mon site : http://lapaille.byethost24.com/index.htm
Bonsoir,
pour les gif et les png je n'en sais rien, je ne vais parler que des jpg et des bmp.
Il se trouve que j'ai récemment fait tourner sur un vieux disque un outil de récupération de fichiers supprimés, et l'outil m'en a trouvé un wagon, mais certains dans un drôle d'état, qu'on en juge :
Dans ce montage réduit aux 2/3, la grande image est une copie d'écran d'un fichier jpg ouvert dans The Gimp sous Linux, on voit tout en bas un message d'erreur affiché pendant quelques secondes ; en haut à droite le même fichier ouvert sous XP sans message d'erreur dans mon vieux PaintShopPro (niveau de zoom réduit) : on retrouve les barres de couleur présentes dans The Gimp à droite au-dessus de la zone grise.
Quant à l'incrustation du visage en bas à gauche, il s'agit d'un .bmp et c'est dans cet état qu'il s'affiche, aussi bien sous Linux que sous XP, sans aucun message d'erreur.
Et tes trois images gif font surgir à chaque fois un message d'erreur comme quoi le format n'est pas reconnaissable, mais c'est normal, ce n'est pas du gif, c'est du html :
Une fois le fichier renommé en .html, on gagne ça :
Qu'est-ce que tu veux faire, exactement ?
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 Jipété,
merci pour ta réponse. En fait je fais un download d'images contenues dans une page Web. Parmi les images téléchargées, certaines s'affichent bien dans un TImage, et d'autres sont invalides (elles ne s'affichent pas non plus dans le gestionnaire de fichiers de Windows). Je voudrais donc les éliminer juste après le téléchargement.
A+
Charly
Mon site : http://lapaille.byethost24.com/index.htm
Bonjour,
Pourquoi ne pas analyser les premiers caractères du fichier ? À ma souvenance les 7 premiers devrait suffire pour détecter le type d'image
cewiki te fournira la plupart des nombres magiques
MVP Embarcadero
Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
SGBD : Firebird 2.5, 3, SQLite
générateurs États : FastReport, Rave, QuickReport
OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd
Oui merci Serge et Jipété,
je vais tester l'entête des fichiers. je teste et posterai le code si c'est satisfaisant
A+
Charly
Mon site : http://lapaille.byethost24.com/index.htm
Étant entendu que ce n'est pas parce que le magic number est correct que le reste l'est…
C'est d'ailleurs pour ça que j'ai démarré bille en tête avec mes fichiers dont l'image est moisie alors que le magic number est correct.
C'est un peu comme si tu mettais de l'eau dans le réservoir de ta voiture : l'aiguille (le magic number) t'indiquera qu'il est rempli,
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
D'accord mais c'est toi même qui a fait remarquer que les prétendus GIF étaient des XML (pointant certainement sur des Gifs)
cela éliminerait donc ceux-ci
MVP Embarcadero
Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
SGBD : Firebird 2.5, 3, SQLite
générateurs États : FastReport, Rave, QuickReport
OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd
Des html !
(ça m'est arrivé au moins un million de fois, tu fais "clic droit / enregistrer sous..." et tu te retrouves avec le code source de la page au lieu de l'objet convoité : les webmasters se défendent, )
Au cas où ça ne serait pas très clair, je précise que ce qu'on voit après ma phrase Une fois le fichier renommé en .html, on gagne ça : est une copie d'écran de ce qui s'est affiché dans mon navigateur quand je lui ai gentiment demandé de m'ouvrir le fichier blabla.gif.html.
D'ailleurs, si je l'ouvre dans un bloc-notes, j'y trouve ça (juste le début, car il y a 278 lignes) :D'accord pour ça.
Code html : 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 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Orange</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <!-- / Inclusions Styles Orange --> <link rel="stylesheet" href="C/autosearch.css" type="text/css"> <link rel="stylesheet" href="C/completion.css" type="text/css"> <!-- patch IE completion --> <style type="text/css" media="all"> .keWebNoResultAutoCompleteCompletionBox { _left: 0px; }
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 bricolé ceci qui est suffisant pour moi :
Est ce que je pourrai lire directement une chaine String[8] plutôt qu'un Array[1..8] of Char, pour éviter une conversion ?
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 Function TF_Princ.IsTypeImage(Const Fichier : String) : Boolean ; // Vrai si fichier est une image de type Gif, jpeg, png ou Bmp // d'après l'entête du fichier (2 premiers octets) Var Chaine : String ; Position : Integer ; F : file ; NumRead : Integer ; Buf : array[1..8] of Char; ChLue : String ; i : Integer ; Begin Result := False ; If Not FileExists(Fichier) then exit; // Chaine contenant les entêtes des fichiers image // #1 séparateur - #255#216#255 jpeg ou jpg - #66#77 (BM) Bmp // #137#80#78#71#13#10#26#10 PNG - #71#73#70#56 (GIF8 7 ou 9) GIF Chaine := #1#255#216#255#1#66#77#1#137#80#78#71#13#10#26#10#1#71#73#70#56#1 ; // Lecture des 8 premiers octets du fichier AssignFile(F, Fichier); Reset(F, 1); BlockRead(F, Buf, SizeOf(Buf), NumRead); CloseFile(F) ; ChLue := '' ; For i := 1 To 2 Do ChLue := ChLue + Buf[i] ; ChLue := #1+ChLue ; // ShowMessage(ChLue) ; Position := Pos(ChLue, Chaine) ; If Position = 0 Then Exit ; Result := True ; End ;
On peut aussi aller plus loin en donnant le type de fichier trouvé et aussi reconnaitre sur plus de 2 caractères pour les fichiers qui ne sont pas des bmp.
Ce serait peut être aussi plus clair en hexa qu'en décimal par exemple : #$FF au lieu de #255 ?
A+
Charly
Mon site : http://lapaille.byethost24.com/index.htm
Bonjour,
je me suis pris au jeu et j'ai fait ceci:le code est très simple
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
74
75
76
77 function ReadHeader(aStream: TStream): string; const PNG_SIGNATURE : AnsiString = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A; //PNG JPEG_JFIF_SIGNATURE: AnsiString = #$FF#$D8#$FF#$E0; //JPEG_JFIF_FORMAT JPEG_EXIF_SIGNATURE: AnsiString = #$FF#$D8#$FF#$E1; //JPEG_EXIF_FORMAT METAFILE_SIGNATURE : AnsiString = #$D7#$CD#$C6#$9A; //'Windows MetaFile' EMETAFILE_SIGNATURE: AnsiString = #$45#$4D#$46; //'Enhanced MetaFile' BMP_SIGNATURE : AnsiString = #$42#$4D; //'Bitmap'; GIF87a_SIGNATURE : AnsiString = #$47#$49#$46#$38#$37#$61; //'GIF87a' GIF89a_SIGNATURE : AnsiString = #$47#$49#$46#$38#$39#$61; //'GIF89a' TIFF_II_SIGNATURE : AnsiString = #$49#$49#$2A#$0; //'TIFF II' TIFF_MM_SIGNATURE : AnsiString = #$4D#$4D#$2A#$0; //'TIFF MM' var Signatures : record case byte of 0: (Raw: array[0..43] of AnsiChar); 1: (Bitmap: array[0..1] of AnsiChar); 2: (PNG: array[0..7] of AnsiChar); 3: (JPG: array[0..3] of AnsiChar; Unused1: array[0..1] of Byte; Marker: array[0..3] of AnsiChar); 4: (Metafile: array[0..3] of AnsiChar; Unused2: array[0..36] of Byte; EMetafile: array[0..2] of AnsiChar); 5: (Gif: array[0..5] of AnsiChar); 6: (Tiff: array[0..3] of AnsiChar); end; StreamPos : Int64; begin StreamPos := aStream.Position; aStream.ReadBuffer(Signatures, SizeOf(Signatures)); aStream.Position := StreamPos; if CompareMem(@BMP_SIGNATURE[1], @Signatures.Bitmap[0], SizeOf(Signatures.Bitmap)) then Result := 'Bitmap Image' else if CompareMem(@PNG_SIGNATURE[1], @Signatures.PNG[0], SizeOf(Signatures.PNG)) then Result := 'PNG Image' else if (CompareMem(@JPEG_JFIF_SIGNATURE[1], @Signatures.JPG[0], SizeOf(Signatures.JPG))) or (CompareMem(@JPEG_EXIF_SIGNATURE[1], @Signatures.JPG[0], SizeOf(Signatures.JPG))) then Result := Format('JPG/%s Image', [Signatures.Marker]) else if (CompareMem(@GIF89a_SIGNATURE[1], @Signatures.Gif[0], SizeOf(Signatures.Gif))) or (CompareMem(@GIF87a_SIGNATURE[1], @Signatures.Gif[0], SizeOf(Signatures.Gif))) then Result := 'GIF Image' else if (CompareMem(@TIFF_II_SIGNATURE[1], @Signatures.Tiff[0], SizeOf(Signatures.Tiff))) or (CompareMem(@TIFF_MM_SIGNATURE[1], @Signatures.Tiff[0], SizeOf(Signatures.Tiff))) then Result := 'TIFF Image' else if CompareMem(@METAFILE_SIGNATURE[1], @Signatures.Metafile[0], SizeOf(Signatures.Metafile)) then Result := 'MetaFile Image' else if CompareMem(@EMETAFILE_SIGNATURE[1], @Signatures.EMetafile[0], SizeOf(Signatures.EMetafile)) then Result := 'Enhanced MetaFile Image' else Result := 'Unknown or Invalid File'; end; function TestImgFile(aFileName: TFileName): string; var aStream : TMemoryStream; begin aStream := TMemoryStream.Create; try aStream.LoadFromFile(aFileName); Result := ReadHeader(aStream); finally aStream.Free; end; end; procedure TForm4.Button1Click(Sender: TObject); begin if Opd1.Execute then Caption := TestImgFile(Opd1.FileName); end;
il renvoie une chaine de caractère juste pour savoir si la détection se fait correctement mais on peut le modifier à souhait ...
Cordialement,
@+
Yop !
mais que tu n'as pas dû tester dans tous les cas de figure, car quand je lis ça :
je me dis que tu te prépares des lendemains qui déchantent, avec les .jpg.
Je te laisse regarder le commentaire au milieu de cette fonction, ligne 12 :
et admirer ce montage de la vue de 5 fichiers différents ouverts dans un afficheur hexa :
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 function ReadJPGIdentifier(Filename : string): string; var idstr: string[4]; i: integer; f: file; aChar: Char; amt : Integer; {bytes returned by blockread} begin idstr:=''; aChar:=#0; amt:=0; // happy compilo AssignFile(f, filename); Reset(f, 1); {a JPEG file MAY return the id 'JFIF<null>' starting at 06 from beginning of file} for i := 0 to 5 do BlockRead(f, aChar, 1, amt); for i := 6 to 9 do begin BlockRead(f, aChar, 1, amt); idstr := idstr + aChar; end; CloseFile(f); Result := idstr; end;
Cette seconde ligne est bizarre car, comme on le voit sur mon image, le premier fichier est EXIF avec FF D8 FF E0.
Le FF E1 est sur la ligne suivante.
Ici ça n'aura pas d'importance, mais dans d'autres cas de figure,
Lecture.
EDIT : j'ai mis les données de Wikipedia un peu en forme, ça donne ça :
Ensuite j'ai fait une recherche de FF D8 FF sur la page et ça n'a trouvé que ces 4 lignes, conclusion il suffirait pour tes besoins de tester les 3 premiers octets du fichier pour savoir si c'est jpg (tous formats confondus) ou pas.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 FF D8 FF DB ÿØÿÛ FF D8 FF E0 00 10 4A 46 49 46 00 ÿØÿà..JFIF. FF D8 FF EE ÿØÿî FF D8 FF E1 ?? ?? 45 78 69 66 00 ÿØÿá..Exif.
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
re,
tout ceci n'a effectivement pas grande importance le fichier est quand même détecté correctement
le fichier JPEG commence soit par:
#$FF#$D8#$FF#$E0;
soit par:
#$FF#$D8#$FF#$E1;
le reste est optionnel dans la détection ...
as tu déjà essayé le code avec tes images ?
je peux pas m'étendre plus je dois me sauver mais je serai de retour dans l'aprèm
Cordialement,
@+
ps: pour se passer de controle et ne pas avoir de message d'erreur lors d'un chargement d'image invalide
je vous conseil d'utiliser l'unité Execute.GDIPBitmap de Paul Toth
avec quelques petites modification c'est top
Merci Cirec,
cette fonction est très complète et bien au delà de ce qu'il me faut ici !!
Pour les Jpeg, les 4 premiers octets suffisent effectivement avec les 2 variantes E0 ou E1
Par contre cela ne répond pas à ma question : est t il possible de lire directement un string pour éviter une conversion ? est ce possible avec un File of ?? ou un Textfile
(ceci pour être plus rapide ...)
A+
Charly
Mon site : http://lapaille.byethost24.com/index.htm
re,
non non
sont des entêtes interne au format JPEG
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 FF D8 FF DB ÿØÿÛ et FF D8 FF EE ÿØÿî
Tiré du Wiki : "JPEG raw or in the JFIF or Exif file format "
toutes les images contenants ces signatures ont pour entête :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 FF D8 FF E0 00 10 4A 46 49 46 00 ÿØÿà..JFIF ou FF D8 FF E1 ?? ?? 45 78 69 66 00 ÿØÿá..Exif
@Charly910:
de quelle conversion parles-tu ?
tu peux directement faire ceci:
pare contre je ne suis pas convaincu par ton code:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 ShowMessage(Buf) ; // ou ChLue := Buf;
tu lis un Buffer de 8 caractères et tu n'en retiens que 2 !! :
ça ne va pas fonctionner correctement.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 ... var ... Buf : array[1..8] of Char; ... For i := 1 To 2 Do ChLue := ChLue + Buf[i] ; ...
[EDIT]
pour répondre à ta question tu peux le faire directement avec un string:
Cordialement,
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 Function TForm4.IsTypeImage(Const Fichier : String) : Boolean ; // Vrai si fichier est une image de type Gif, jpeg, png ou Bmp // d'après l'entête du fichier (2 premiers octets) Var Chaine : String ; Position : Integer ; F : file ; NumRead : Integer ; Buf : string; // <------ Modifié ----- ChLue : String ; i : Integer ; Begin Result := False ; If Not FileExists(Fichier) then exit; // Chaine contenant les entêtes des fichiers image // #1 séparateur - #255#216#255 jpeg ou jpg - #66#77 (BM) Bmp // #137#80#78#71#13#10#26#10 PNG - #71#73#70#56 (GIF8 7 ou 9) GIF Chaine := #1#255#216#255#1#66#77#1#137#80#78#71#13#10#26#10#1#71#73#70#56#1 ; // Lecture des 8 premiers octets du fichier SetLength(Buf, 8); // <------ Ajouté ----- AssignFile(F, Fichier); Reset(F, 1); BlockRead(F, Buf[1], Length(Buf), NumRead); // <------ Modifié ----- CloseFile(F) ; ChLue := '' ; For i := 1 To 2 Do ChLue := ChLue + Buf[i] ; ChLue := #1+ChLue ; // ShowMessage(ChLue) ; Position := Pos(ChLue, Chaine) ; If Position = 0 Then Exit ; Result := True ; End ;
@+
...
et pour coller le plus possible à ton code j'ai fait un mix des deux
comme ça tous les octets utiles à la l'identification d'un fichier image sont testés
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 function TF_Princ.IsTypeImage(Const Fichier : String): Boolean; // Vrai si fichier est une image de type Gif, jpeg, png ou Bmp, Tif, wmf, emf // d'après l'entête du fichier (44 premiers octets d'un bloc) const PNG_SIGNATURE : AnsiString = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A; //PNG JPEG_JFIF_SIGNATURE: AnsiString = #$FF#$D8#$FF#$E0; //JPEG_JFIF_FORMAT JPEG_EXIF_SIGNATURE: AnsiString = #$FF#$D8#$FF#$E1; //JPEG_EXIF_FORMAT METAFILE_SIGNATURE : AnsiString = #$D7#$CD#$C6#$9A; //'Windows MetaFile' EMETAFILE_SIGNATURE: AnsiString = #$45#$4D#$46; //'Enhanced MetaFile' BMP_SIGNATURE : AnsiString = #$42#$4D; //'Bitmap'; GIF87a_SIGNATURE : AnsiString = #$47#$49#$46#$38#$37#$61; //'GIF87a' GIF89a_SIGNATURE : AnsiString = #$47#$49#$46#$38#$39#$61; //'GIF89a' TIFF_II_SIGNATURE : AnsiString = #$49#$49#$2A#$0; //'TIFF II' TIFF_MM_SIGNATURE : AnsiString = #$4D#$4D#$2A#$0; //'TIFF MM' var Signatures : record case byte of 0: (Raw: array[0..43] of AnsiChar); 1: (Bitmap: array[0..1] of AnsiChar); 2: (PNG: array[0..7] of AnsiChar); 3: (JPG: array[0..3] of AnsiChar; Unused1: array[0..1] of Byte; Marker: array[0..3] of AnsiChar); 4: (Metafile: array[0..3] of AnsiChar; Unused2: array[0..36] of Byte; EMetafile: array[0..2] of AnsiChar); 5: (Gif: array[0..5] of AnsiChar); 6: (Tiff: array[0..3] of AnsiChar); end; Chaine : AnsiString ; Position : Integer ; F : file ; NumRead : Integer ; begin Result := False ; if not FileExists(Fichier) then exit; // Chaine contenant les entêtes des fichiers image Chaine := #$01+PNG_SIGNATURE+#$01+JPEG_JFIF_SIGNATURE+#$01+JPEG_EXIF_SIGNATURE+#$01+ METAFILE_SIGNATURE+#$01+EMETAFILE_SIGNATURE+#$01+BMP_SIGNATURE+#$01+GIF87a_SIGNATURE+#$01+ GIF89a_SIGNATURE+#$01+TIFF_II_SIGNATURE+#$01+TIFF_MM_SIGNATURE+#$01; // Lecture des 44 premiers octets du fichier AssignFile(F, Fichier); Reset(F, 1); BlockRead(F, PByte(@Signatures)^, SizeOf(Signatures), NumRead); CloseFile(F) ; Position := Pos(Signatures.JPG, Chaine) + Pos(Signatures.PNG, Chaine) + Pos(Signatures.Bitmap, Chaine) + Pos(Signatures.Metafile, Chaine) + Pos(Signatures.EMetafile, Chaine) + Pos(Signatures.Gif, Chaine) + Pos(Signatures.Tiff, Chaine); Result := Position > 0; end;
ne tester que les 2 premiers me semble trop hasardeux
Merci et bravo Cirec,
j'avais mis 8 octets, car j'avais l'intention de de faire des tests sur chaque type de fichier (2 octets pour Bmp, 4 pour Jpeg, 8 pour Png, ...)
Mais je n'en avis pas réellement besoin et je n'ai testé que les 2 premiers en me disant que c'était suffisant..
Je vais prendre ton dernier code qui me parait correspondre exactement à ce que je veux.
Merci encore
A+
Charly
Mon site : http://lapaille.byethost24.com/index.htm
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