Antecedentes: no tengo nada que hacer recientemente y, a petición de un miembro del foro, quería crear un sitio para descargar emoticones QQ. Originalmente, las cosas eran muy simples, solo escriba un pequeño CRUD, pero como Hahahaha es un programador .Net, por supuesto que tiene que usar .Net para implementarlo. Hoy usaremos .Net para implementar la función de empaquetado del formato de expresión CFC (custom face cab?).
Para lograr esta función, primero debemos entender este formato, primero buscarlo en Google. Encontramos este artículo de la Universidad de Tsinghua: Explicación detallada del formato de archivo FC.
De este artículo aprendimos que el formato de archivo CFC es aproximadamente el siguiente:
Un bloque tiene 15 campos, de la siguiente manera:
longitud de cadena md5, longitud de clave de acceso directo de 4 bytes, longitud de nombre de emoticón de 4 bytes, longitud de nombre de archivo de emoticón de 4 bytes, longitud de archivo de emoticón de 4 bytes, longitud de nombre de archivo de miniatura de 4 bytes, Longitud de archivo en miniatura de 4 bytes, número de fotograma de archivo de emoticones de 4 bytes, imagen de 4 bytes Forma de cadena md5 Tecla de acceso directo Nombre del emoticón Nombre del archivo de emoticones Nombre del archivo en miniatura Contenido del archivo de emoticones Contenido en miniatura Solo conozca el formato Listo, definamos una estructura (struct) paso a paso
1 Estructura#región Estructura
2 estructura pública FaceBlock
3 {
4 unidad pública MD5Longitud //32
5 público uint uintcutLength //4
6 public uint CaraNombreLongitud //4
7 public uint FaceFileNameLength //36 md5 + extensión
8 longitud de archivo de unidad pública;
9 public uint ThumbnailFileNameLength //41 md5 + fijo.bmp
10 uint público ThumbnailFileLength;
11 unidades públicas FrameLength;
12 cadenas públicas MD5;
13 cortes de cadenas públicas;
14 cadenas públicas FaceName;
15 cadenas públicas FaceFileName;
16 cadena pública ThumbnailFileName;
17 bytes públicos [] FaceData;
18 bytes públicos [] ThumbnailData;
19
20 FaceBlock estático público FromImage (archivo de cadena)
veintiuno {
22 devuelve FaceHelper.GetFaceBlockFromImage(archivo);
veintitrés }
veinticuatro
25 bytes[] GetBytes(valor uint)
26 {
27 bytes[] bt = BitConverter.GetBytes(valor);
28 Lista
29 bytes.AddRange(bt);
30 si (bytes.Cuenta < 4)
31 {
32 int l = 4 - bytes.Cuenta;
33 para (int i = 0; i < l; i++)
34 bytes. Agregar ((byte) 0);
35}
36 bytes de retorno.ToArray();
37 }
38
39 bytes públicos[]ToBytes()
40 {
41 Lista
42 Codificación e = Codificación.ASCII;
43 bytes.AddRange(GetBytes(MD5Length));
44 bytes.AddRange(GetBytes(uintcutLength));
45 bytes.AddRange(GetBytes(FaceNameLength));
46 bytes.AddRange(GetBytes(FaceFileNameLength));
47 bytes.AddRange(GetBytes(FileLength));
48 bytes.AddRange(GetBytes(ThumbnailFileNameLength));
49 bytes.AddRange(GetBytes(ThumbnailFileLength));
50 bytes.AddRange(GetBytes(FrameLength));
51
52 bytes.AddRange(e.GetBytes(MD5));
53 bytes.AddRange(e.GetBytes(uintcuts));
54 bytes.AddRange(e.GetBytes(FaceName));
55 bytes.AddRange(e.GetBytes(FaceFileName));
56 bytes.AddRange(e.GetBytes(ThumbnailFileName));
57
58 bytes.AddRange(FaceData);
59 bytes.AddRange(ThumbnailData);
60
61 bytes de retorno.ToArray();
62 }
63}
64 #endregion contiene dos métodos, uno es un método estático para obtener esta estructura del archivo y el otro es convertir esta estructura en una matriz de bytes.
Creemos otra clase y llamémosla: FaceHelper
El código es el siguiente:
clase pública FaceHelper
{
FaceBlock estático interno GetFaceBlockFromImage (archivo de cadena)
{
FaceBlock fb = nuevo FaceBlock();
//Abrir secuencia de archivos
FileStream fs = nuevo FileStream(archivo, FileMode.Open, FileAccess.Read);
//Obtener la imagen
Imagen img = Imagen.FromStream(fs);
//Obtener una miniatura de 20*20
Miniatura de imagen = img.GetThumbnailImage(20, 20, null, IntPtr.Zero);
MemoryStream ms = nuevo MemoryStream();
//Convierte la imagen en miniatura en una matriz de bytes
miniatura.Guardar(ms, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] thumbnailData = ms.ToArray();
ms.Cerrar();
ms.Dispose();
thumbnail.Dispose();
//Obtener una cadena MD5 única
cadena md5 = GetMD5(fs);
//Nombre del archivo, el formato es: md5 + extensión
string fileName = string.Format("{0}{1}", md5, Path.GetExtension(archivo));
//Nombre del archivo en miniatura, formato: md5 + fijo.bmp
string thumbnailName = string.Format("{0}fixed.bmp", md5);
//Establecer una tecla de acceso directo aleatoria
cadena uintcuts = "qq.5inet.net_" + RandomNum(6);
fs.Cerrar();
fs.Dispose();
//Obtener el número total de fotogramas
System.Drawing.Imaging.FrameDimension fd = System.Drawing.Imaging.FrameDimension.Resolution;
int frameCount = img.FrameDimensionsList.Length;
img.Dispose();
fb.MD5 = md5;
fb.MD5Longitud = (uint)md5.Longitud;
fb.uintcuts = uintcuts;
fb.uintcutLength = (uint)uintcuts.Longitud;
fb.FaceName = uintcuts;
fb.FaceNameLength = (uint)uintcuts.Length;
fb.FaceFileName = nombre de archivo;
fb.FaceFileNameLength = (uint)fileName.Longitud;
fb.ThumbnailFileName = nombre de miniatura;
fb.ThumbnailFileNameLength = (uint)thumbnailName.Length;
fb.FaceData = File.ReadAllBytes(archivo);
fb.FileLength = (uint)fb.FaceData.Longitud;
fb.ThumbnailData = miniaturaDatos;
fb.ThumbnailFileLength = (uint)thumbnailData.Length;
fb.FrameLength = (uint)frameCount
devolver fb;
}
Ayudante#región Ayudante
//método aleatorio
cadena estática interna RandomNum(int n) //
{
cadena cadena = "0,1,2,3,4,5,6,7,8,9";
cadena[] VcArray = strchar.Split(',');
string VNum = "";//Dado que la cadena es muy corta, F77pclw,cnetworkG|?,ye,e'b no necesita StringBuilder
int temp = -1; //Registra el último valor aleatorio e intenta evitar generar varios números aleatorios idénticos.
//Utiliza un algoritmo simple para asegurar la diferencia en los números aleatorios generados
Rand aleatorio = nuevo Aleatorio();
para (int i = 1; i < n + 1; i++)
{
si (temperatura! = -1)
{
rand = new Aleatorio(i * temp * unchecked((int)
DateTime.Now.Ticks));
}
//int t = rand.Siguiente(35);
int t = rand.Siguiente(10);
si (temperatura! = -1 && temperatura == t)
{
devolver NúmeroAleatorio(n);
}
temperatura = t;
VNum += VcArray[t];
}
return VNum;//Devuelve el número aleatorio generado
}
//Obtener MD5 del nombre del archivo
cadena estática interna GetMD5 (FileStream fs)
{
MD5CryptoServiceProvider md5 = nuevo MD5CryptoServiceProvider();
byte[] md5byte = md5.ComputeHash(fs);
cadena cadena = cadena.Vacío;
int i, j;
foreach (byte b en md5byte)
{
i = Convertir.ToInt32(b);
j = yo >> 4;
cadena += (Convert.ToString(j, 16));
j = ((yo << 4) & 0x00ff) >> 4;
cadena += (Convert.ToString(j, 16));
}
devolver str.ToUpper();
}
#endregion
//Generar una colección de archivos CFC desde un directorio
vacío público estático
BuildCFCFileFromDirectory (directorio de cadenas)
{
Lista
foreach (archivo de cadena en Directory.GetFiles(directorio))
{
si (!IsImageFile(archivo))
continuar;
bytes.AddRange(FaceBlock.FromImage(archivo).ToBytes());
}
cadena fName = Path.Combine(directorio, Path.GetDirectoryName(directorio) + ".cfc");
FileStream fs = File.Create(fName);
fs.Write(bytes.ToArray(), 0, bytes.Count);
fs.Cerrar();
}
//El método para determinar si es un archivo de imagen es relativamente simple.
bool estático privado IsImageFile (archivo de cadena)
{
Lista
".bmp",
".jpg",
".jpeg",
".gif",
".png",
});
devuelve validExt.Contains(Path.GetExtension(file).ToLower());
}
}
Bien, con el método anterior, podemos llamarlo.
Llamar al método es realmente simple.
FaceHelper.BuildCFCFileFromDirectory(Server.MapPath("~/img/"));
Está bien. Ahora vaya al directorio raíz de su sitio web y vea si hay un archivo img.cfc. Haga doble clic nuevamente. ¿Se han importado todos los archivos en el directorio img a los emoticonos de QQ? ¡Disfruta de la codificación!
Este artículo fue publicado originalmente por: Wuyuan IT Teaching Network.
http://www.cnblogs.com/skyover/archive/2006/10/03/520581.html