Plot
Un jour, au détour d'un darty, j'ai croisé un vieil homme entrain de chercher de l'aide auprès d'une gentille vendeuse parce que ses photos étaient cassées.
La pauvre vendeuse savait vendre des ordinateurs, pas réparer des photos, j'ai donc proposé à l'homme de passer à Atilla, le lendemain soir vers 19h, où je devrais traîner, comme beaucoup de soirs pendant l'hiver.
Le lendemain soir, il a donc pénétré la salle, et c'est là que tout commence.
0xstuff
Les images étaient cassées.
Sous windows vista sur son hp tout pourri, les images n'avaient plus qu'une icône.
Nous avons donc prié vista de nous donner le poids des images, normal pour une image, par conséquent les données étaient toujours présentes.
Pour diagnostiquer, nous avons copié quelques images (seules les JPEG étaient affectées) sur ma debian.
Shotwell a été plus précis que l'afficheur d'images de windows, en nous précisant la source d'erreurs :
l'image ne commence pas par 0xffd8
Un coup de hexdump -n 64 -C image-001.jpeg
nous a montré les premiers 64 octets de l'image sous cette forme :
00000000 00 d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 48 |......JFIF.....H|
00000010 00 48 00 00 ff db 00 43 00 06 04 04 04 05 04 06 |.H.....C........|
00000020 05 05 06 09 06 05 06 09 0b 08 06 06 08 0b 0c 0a |................|
00000030 0a 0b 0a 0a 0c 10 0c 0c 0c 0c 0c 0c 10 0c 0e 0f |................|
00000040
On reconnaît le header avec JFIF
, (soit dit en passant, très pratique pour compter les images dans un gros fichier avec un coup de grep JFIF -c grosfichier.dat
) et les premiers octets : 00 d8 ff e0
.
Or, le format jpeg commence toujours par :
Après avoir vérifié sur d'autres images avec un :
| #!/bin/bash
for i in `ls *.jpeg`;
do
echo $i;
hexdump -n 16 -C $i;
done;
|
Nous (j'ai) supposé que le problème était uniquement le premier octet des images, passé de 0xFF
à 0x00
(plein de 1 -> plein de 0).
Symptôme surprenant, personne sur les Internets ne semble l'avoir rencontré.
Un petit script en python bien sale qui charge les images en mémoire en entier, change le premier octet et les écrit sur le même fichier a pris une petite heure pour les 7000 photos (je crois), éxécuté sur son hp sur une live ubuntu.
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 | #!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import os
import sys
def main():
# lecture du fichier contenant la liste des fichiers, obtenue en faisant un "find . -name *.jpeg"
with open(sys.argv[1],'r') as ofi:
liste_fichiers = ofi.readlines()
ofi.close()
# pour chaque numéro de la liste des images
for index in xrange(len(liste_fichiers)):
# on retrouve le nom de l'image
image = liste_fichiers[index]
# affichage de la progression, histoire qu'on aille faire les courses en attendant
print index,"/",len(liste_fichiers),image
# lecture de l'image
with open(image,'r') as ofi:
data = ofi.read()
ofi.close()
# remplacement du premier octet
data[0] = chr(0xff)
# écriture de l'image (d'où le "w" au lieu du "r")
with open(image,'w') as ofi:
ofi.write(data)
ofi.close()
if __name__ == "__main__":
main()
|
Le vieil homme, ravi a insisté pour me payer, ce que j'ai refusé, bien entendu, alors il m'a invité à manger chez lui ou ce genre de trucs, je lui ai dit que si il voulait vraiment nous (atilla, mais en fait me) remercier, il pouvait ramener un gâteau le lendemain.
Épilogue
Le surlendemain, vers 19h30, PAF, pierre (il a des cheveux) surgit suivi par le monsieur et un gâteau aux amandes \o/ !
(Il a insisté pour me "parler" en privé et en a profité pour me glisser un billet, mais ne le dites à personne ;)
Conclusion
On aurait pu régler ça avec un coup de dd
, ça aurait sûrement été plus vite à éxécuter, mais pas à coder, je n'étais pas trop à l'aise avec dd
à l'époque.