Предыстория: Мне в последнее время делать нечего, и по просьбе форумчанина я захотел создать сайт для скачивания смайлов QQ. Первоначально все было очень просто: нужно просто написать небольшой CRUD, но поскольку Хахахаха — .Net-программист, ему, конечно, придется использовать .Net для его реализации. Сегодня мы будем использовать .Net для реализации функции упаковки формата выражений CFC (custom face cab?).
Чтобы реализовать эту функцию, мы должны сначала понять этот формат, сначала загуглить его. Мы нашли эту статью из Университета Цинхуа: Подробное объяснение формата файла FC.
Из этой статьи мы узнали, что формат файла CFC примерно следующий:
Блок имеет 15 полей, а именно:
длина строки md5, длина клавиши быстрого доступа 4 байта, длина имени смайла 4 байта, длина имени файла смайла 4 байта, длина файла смайла 4 байта, длина имени файла миниатюры 4 байта, Длина миниатюрного файла 4 байта, номер кадра файла смайлика 4 байта, строковая форма md5 4 байта, комбинация клавиш, имя смайлика, имя файла смайла, миниатюра имени файла, содержимое файла смайлика, содержимое миниатюры Просто знайте формат Готово, давайте определим структуру (структуру) шаг за шагом
1 Структура #регион
2 общедоступная структура FaceBlock
3 {
4 общедоступный uint MD5Length //32;
5 общественный uint uintcutLength //4;
6 public uint FaceNameLength //4;
7 public uint FaceFileNameLength //36 md5 + расширение;
8 общедоступных uint FileLength;
9 public uint ThumbnailFileNameLength //41 md5 + fix.bmp;
10 общедоступных uint ThumbnailFileLength;
11 общедоступный uint FrameLength;
12 общедоступная строка MD5;
13 общедоступных строковых сокращений;
14 общедоступная строка FaceName;
15 общедоступная строка FaceFileName;
16 общедоступная строка ThumbnailFileName;
17 общедоступный байт[] FaceData;
18 общедоступных байтов [] ThumbnailData;
19
20 общедоступных статических FaceBlock FromImage (строковый файл)
двадцать один {
22 return FaceHelper.GetFaceBlockFromImage(файл);
двадцать три }
двадцать четыре
25 байт[] GetBytes (значение uint)
26 {
27 байт[] bt = BitConverter.GetBytes(значение);
28 байт List
29 байт.AddRange(bt);
30, если (bytes.Count < 4)
31 {
32 int l = 4 — байт.Count;
33 для (int i = 0; i < l; i++)
34 байта.Добавить((байт)0);
35}
36 возвращаемых байт.ToArray();
37 }
38
39 общедоступных байтов[]ToBytes()
40 {
41 List
42 Кодировка e = Encoding.ASCII;
43 байта.AddRange(GetBytes(MD5Length));
44 байта.AddRange(GetBytes(uintcutLength));
45 байт.AddRange(GetBytes(FaceNameLength));
46 байт.AddRange(GetBytes(FaceFileNameLength));
47 байт.AddRange(GetBytes(FileLength));
48 байт.AddRange(GetBytes(ThumbnailFileNameLength));
49 байт.AddRange(GetBytes(ThumbnailFileLength));
50 байт.AddRange(GetBytes(FrameLength));
51
52 байта.AddRange(e.GetBytes(MD5));
53 байта.AddRange(e.GetBytes(uintcuts));
54 байта.AddRange(e.GetBytes(FaceName));
55 байт.AddRange(e.GetBytes(FaceFileName));
56 байт.AddRange(e.GetBytes(ThumbnailFileName));
57
58 байт.AddRange(FaceData);
59 байт.AddRange(ThumbnailData);
60
61 возвращаемый байт.ToArray();
62 }
63}
64 #endregion содержит два метода: один — статический метод для получения этой структуры из файла, а другой — для преобразования этой структуры в массив байтов.
Давайте создадим еще один класс и назовем его: FaceHelper.
Код выглядит следующим образом:
публичный класс FaceHelper
{
внутренний статический FaceBlock GetFaceBlockFromImage (строковый файл)
{
FaceBlock fb = новый FaceBlock();
//Открываем файловый поток
FileStream fs = новый FileStream (файл, FileMode.Open, FileAccess.Read);
//Получаем изображение
Изображение img = Image.FromStream(fs);
//Получаем миниатюру размером 20*20
Миниатюра изображения = img.GetThumbnailImage(20, 20, null, IntPtr.Zero);
MemoryStream мс = новый MemoryStream();
//Преобразуем миниатюру изображения в байтовый массив
Thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] ThumbnailData = ms.ToArray();
мс.Закрыть();
мс.Dispose();
Thumbnail.Dispose();
//Получаем уникальную строку MD5
строка md5 = GetMD5 (фс);
//Имя файла, формат: md5 + расширение
строка fileName = string.Format("{0}{1}", md5, Path.GetExtension(file));
//Имя файла миниатюры, формат: md5 + fix.bmp
string миниатюраName = string.Format("{0}fixed.bmp", md5);
//Установим случайное сочетание клавиш
строка uintcuts = "qq.5inet.net_" + RandomNum(6);
фс.Закрыть();
fs.Dispose();
//Получаем общее количество кадров
System.Drawing.Imaging.FrameDimension fd = System.Drawing.Imaging.FrameDimension.Resolution;
intframeCount = img.FrameDimensionsList.Length;
img.Dispose();
fb.MD5 = md5;
fb.MD5Length = (uint)md5.Length;
fb.uintcuts = uintcuts;
fb.uintcutLength = (uint)uintcuts.Length;
fb.FaceName = uintcuts;
fb.FaceNameLength = (uint)uintcuts.Length;
fb.FaceFileName = имя_файла;
fb.FaceFileNameLength = (uint)fileName.Length;
fb.ThumbnailFileName = имя_миниатюры;
fb.ThumbnailFileNameLength = (uint)thumbnailName.Length;
fb.FaceData = File.ReadAllBytes(файл);
fb.FileLength = (uint)fb.FaceData.Length;
fb.ThumbnailData = миниатюрные данные;
fb.ThumbnailFileLength = (uint)thumbnailData.Length;
fb.FrameLength = (uint)frameCount;
return fb;
}
Helper#Помощник региона
//случайный метод
внутренняя статическая строка RandomNum(int n) //
{
строка strchar = "0,1,2,3,4,5,6,7,8,9";
string[] VcArray = strchar.Split(',');
string VNum = "";//Поскольку строка очень короткая, F77pclw,cnetworkG|?,ye,e'b не нуждается в StringBuilder
int temp = -1; //Запишите последнее случайное значение и постарайтесь избежать генерации нескольких одинаковых случайных чисел.
//Используйте простой алгоритм, чтобы гарантировать разницу в сгенерированных случайных числах
Случайный рандом = новый Случайный();
for (int i = 1; i < n + 1; i++)
{
если (темп!= -1)
{
rand = new Random(i * temp * unchecked((int)
DateTime.Now.Ticks));
}
//int t = rand.Next(35);
int t = rand.Next(10);
if (temp != -1 && temp == t)
{
вернуть RandomNum (n);
}
температура = т;
VNum += VcArray[t];
}
return VNum;//Вернем сгенерированное случайное число
}
//Получаем MD5 по имени файла
внутренняя статическая строка GetMD5 (FileStream fs)
{
MD5CryptoServiceProvider md5 = новый MD5CryptoServiceProvider();
byte[] md5byte = md5.ComputeHash(fs);
строка стр = строка.Пусто;
интервал я, j;
foreach (байт b в md5byte)
{
я = Convert.ToInt32(б);
j = я >> 4;
стр += (Convert.ToString(j, 16));
j = ((i << 4) & 0x00ff) >> 4;
стр += (Convert.ToString(j, 16));
}
Возврат str.ToUpper();
}
#endregion
//Создать коллекцию файлов CFC из каталога
общественная статическая пустота
BuildCFCFileFromDirectory (каталог строки)
{
List
foreach (строковый файл в Directory.GetFiles(каталог))
{
если (!IsImageFile(файл))
продолжить
bytes.AddRange(FaceBlock.FromImage(file).ToBytes());
}
строка fName = Path.Combine(каталог, Path.GetDirectoryName(каталог) + ".cfc");
FileStream fs = File.Create(fName);
fs.Write(bytes.ToArray(), 0, bytes.Count);
фс.Закрыть();
}
//Метод определения того, является ли это файлом изображения, относительно прост.
частный статический bool IsImageFile (строковый файл)
{
List
".bmp",
".jpg",
".jpeg",
".гиф",
".png",
});
return validExt.Contains(Path.GetExtension(file).ToLower());
}
}
Хорошо, с помощью вышеуказанного метода мы можем его вызвать.
Вызвать метод очень просто.
FaceHelper.BuildCFCFileFromDirectory(Server.MapPath("~/img/"));
Ничего страшного. Теперь перейдите в корневой каталог вашего сайта и посмотрите, есть ли там файл img.cfc? Дважды щелкните еще раз. Все ли файлы в каталоге img были импортированы в смайлы QQ? Наслаждайтесь программированием.
Первоначально эта статья была опубликована: Wuyuan IT Teaching Network!
http://www.cnblogs.com/skyover/archive/2006/10/03/520581.html