배경: 최근에 할 일이 없는데, 포럼 회원의 요청으로 QQ 이모티콘을 다운로드할 수 있는 사이트를 만들고 싶었습니다. 원래는 간단한 CRUD만 작성하면 되지만 하하하하가 .Net 프로그래머이기 때문에 당연히 .Net을 사용하여 이를 구현해야 합니다. 오늘은 .Net을 사용하여 CFC(Custom Face Cab?) 표현 형식의 패키징 기능을 구현해 보겠습니다.
이 기능을 달성하려면 먼저 이 형식을 이해하고 먼저 Google에 검색해야 합니다. 우리는 Tsinghua University에서 FC 파일 형식에 대한 자세한 설명이라는 기사를 찾았습니다.
이 기사에서 우리는 CFC 파일 형식이 대략 다음과 같다는 것을 알게 되었습니다.
블록에는
md5 문자열 길이, 4바이트 단축키 길이, 4바이트 이모티콘 이름 길이, 4바이트 이모티콘 파일 이름 길이, 4바이트 이모티콘 파일 길이, 4바이트 썸네일 파일 이름 길이, 4바이트 미니어처 파일 길이, 4바이트 이모티콘 파일 프레임 번호, 4바이트 이미지 md5 문자열 형태 단축키 이모티콘 이름 이모티콘 파일명 썸네일 파일명 이모티콘 파일 콘텐츠 썸네일 콘텐츠 형식만 알면 완료, 구조(struct)를 정의하자 단계별로
1 구조체#region 구조체
2개의 공개 구조체 FaceBlock
3 {
4 공개 단위 MD5Length //32
5 공개 단위 uintcutLength;
6 공개 단위 FaceNameLength;
7 공개 단위 FaceFileNameLength; //36 md5 + 확장자
8 공개 단위 FileLength;
9 공개 단위 ThumbnailFileNameLength; //41 md5 + 고정.bmp
10 공개 단위 ThumbnailFileLength;
11 공개 단위 FrameLength;
12 공개 문자열 MD5;
공개 문자열 uintcut 13개;
14 공개 문자열 FaceName;
15 공개 문자열 FaceFileName;
16 공개 문자열 ThumbnailFileName;
17 공개 바이트[] FaceData;
18 공개 바이트[] ThumbnailData;
19
20 공개 정적 FaceBlock FromImage(문자열 파일)
스물 하나 {
22 return FaceHelper.GetFaceBlockFromImage(파일);
스물셋 }
스물넷
25바이트[] GetBytes(단위 값)
26 {
27바이트[] bt = BitConverter.GetBytes(값);
28 List
29바이트.AddRange(bt);
30 if (bytes.Count < 4)
31 {
32 int l = 4 - 바이트.카운트;
33 for (int i = 0; i < l; i++)
34바이트.Add((byte)0);
35}
36 반환 bytes.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 반환 bytes.ToArray();
62 }
63}
64 #endregion에는 두 가지 방법이 포함되어 있습니다. 하나는 파일에서 이 구조를 얻는 정적 방법이고, 다른 하나는 이 구조를 바이트 배열로 변환하는 것입니다.
다른 클래스를 만들고 이름을 FaceHelper로 지정해 보겠습니다.
코드는 다음과 같습니다:
공개 클래스 FaceHelper
{
내부 정적 FaceBlock GetFaceBlockFromImage(문자열 파일)
{
FaceBlock fb = new FaceBlock();
//파일 스트림 열기
FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read);
//이미지 가져오기
이미지 img = Image.FromStream(fs);
//20*20 썸네일 가져오기
이미지 썸네일 = img.GetThumbnailImage(20, 20, null, IntPtr.Zero);
MemoryStream ms = new MemoryStream();
//썸네일 이미지를 바이트 배열로 변환
Thumbnail.Save(ms, System.드로잉.Imaging.ImageFormat.Bmp);
byte[] 섬네일데이터 = ms.ToArray();
ms.닫기();
ms.Dispose();
Thumbnail.Dispose();
//고유한 MD5 문자열을 가져옵니다.
문자열 md5 = GetMD5(fs);
//파일명, 형식은 md5 + 확장자
string fileName = string.Format("{0}{1}", md5, Path.GetExtension(파일));
//썸네일 파일명, 형식: md5 +fixed.bmp
string ThumbnailName = string.Format("{0}fixed.bmp", md5);
//임의의 단축키 설정
문자열 uintcuts = "qq.5inet.net_" + RandomNum(6);
fs.닫기();
fs.Dispose();
//총 프레임 수를 가져옵니다.
System.드로잉.Imaging.FrameDimension fd = System.드로잉.Imaging.FrameDimension.Resolution;
int 프레임카운트 = img.FrameDimensionsList.Length;
img.Dispose();
fb.MD5 = md5;
fb.MD5Length = (단위)md5.길이;
fb.uintcuts = uintcuts;
fb.uintcutLength = (uint)uintcuts.Length;
fb.FaceName = uintcuts;
fb.FaceNameLength = (단위)uintcuts.Length;
fb.FaceFileName = 파일이름;
fb.FaceFileNameLength = (단위)fileName.Length;
fb.ThumbnailFileName = 썸네일이름;
fb.ThumbnailFileNameLength = (uint)thumbnailName.Length;
fb.FaceData = File.ReadAllBytes(파일);
fb.FileLength = (단위)fb.FaceData.Length;
fb.ThumbnailData = 썸네일데이터;
fb.ThumbnailFileLength = (uint)thumbnailData.Length;
fb.FrameLength = (단위)frameCount
return fb;
}
도우미#region 도우미
//임의의 방법
내부 정적 문자열 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++)
{
if (임시 != -1)
{
rand = new Random(i * temp * unchecked((int)
DateTime.Now.Ticks));
}
//int t = rand.Next(35);
int t = rand.Next(10);
if (온도 != -1 && 온도 == t)
{
RandomNum(n)을 반환합니다.
}
온도 = t;
VNum += VcArray[t];
}
return VNum;//생성된 난수를 반환합니다.
}
//파일 이름에서 MD5를 가져옵니다.
내부 정적 문자열 GetMD5(FileStream fs)
{
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] md5byte = md5.ComputeHash(fs);
문자열 str = 문자열.Empty;
int i, j;
foreach(md5byte의 바이트 b)
{
i = Convert.ToInt32(b);
j = 나는 >> 4;
str += (Convert.ToString(j, 16));
j = ((i << 4) & 0x00ff) >> 4;
str += (Convert.ToString(j, 16));
}
return str.ToUpper();
}
#endregion
//디렉토리에서 CFC 파일 컬렉션을 생성합니다.
공공 정적 무효
BuildCFCFileFromDirectory(문자열 디렉터리)
{
List
foreach(Directory.GetFiles(디렉토리)의 문자열 파일)
{
if (!IsImage파일(파일))
계속;
bytes.AddRange(FaceBlock.FromImage(file).ToBytes());
}
string fName = Path.Combine(디렉토리, Path.GetDirectoryName(디렉토리) + ".cfc");
FileStream fs = File.Create(fName);
fs.Write(bytes.ToArray(), 0, bytes.Count);
fs.닫기();
}
//이미지 파일인지 판단하는 방법은 비교적 간단합니다.
개인 정적 bool IsImageFile(문자열 파일)
{
List
".bmp",
".jpg",
".jpeg",
".gif",
".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