1
1

corel_thumbnail.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. ** Copyright (C) http://srgb.googlecode.com All rights reserved.
  3. */
  4. #include "corel_thumbnail.h"
  5. #include <regex>
  6. #include <string>
  7. #include <atlimage.h>
  8. #define CASESENSITIVITY (0)
  9. #define WRITEBUFFERSIZE (8192)
  10. using std::string;
  11. bool zip_extract_currentfile(unzFile uf, LPCTSTR save_filename)
  12. {
  13. char szFilePathA[MAX_PATH];
  14. // 对于每个内部文件,可用 unzGetCurrentFileInfo64 来查内部文件名
  15. unz_file_info64 FileInfo;
  16. if (unzGetCurrentFileInfo64(uf, &FileInfo, szFilePathA, sizeof(szFilePathA), NULL, 0, NULL, 0) != UNZ_OK) {
  17. return false;
  18. }
  19. // printf("%s", szFilePathA); // 在压缩文件中的 文件名
  20. // 对于非目录的内部文件,用 unzOpenCurrentFile打开
  21. if (unzOpenCurrentFile(uf) != UNZ_OK) {
  22. return false;
  23. }
  24. HANDLE hFile = CreateFile(save_filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
  25. if (hFile == INVALID_HANDLE_VALUE) {
  26. return false;
  27. }
  28. // 然后 unzReadCurrentFile 读取文件内容,写入到真实文件中。
  29. // unzReadCurrentFile 返回 0 表示文件读取结束然后 unzReadCurrentFile 读取文件内容,写入到真实文件中。
  30. // unzReadCurrentFile 返回 0 表示文件读取结束
  31. char byBuffer[WRITEBUFFERSIZE];
  32. while (true) {
  33. int err = unzReadCurrentFile(uf, byBuffer, WRITEBUFFERSIZE);
  34. if (err < 0) {
  35. return false;
  36. } else if (err == 0) {
  37. break;
  38. } else {
  39. DWORD dwWritten = 0;
  40. if (!WriteFile(hFile, byBuffer, (DWORD)err, &dwWritten, NULL) || dwWritten != (DWORD)err) {
  41. return false;
  42. }
  43. }
  44. }
  45. CloseHandle(hFile);
  46. return true;
  47. }
  48. bool zip_extract_onefile(const char* zip_filename, const char* filename , const char* save_filename)
  49. {
  50. // 解压先使用 zipOpen64 来打开一个 ZIP 文件
  51. unzFile uf = unzOpen64(zip_filename);
  52. // // 需要先使用 unzGetGlobalInfo64 来取得该文件的一些信息,来了解这个压缩包里一共包含了多少个文件,等等。
  53. // unz_global_info64 gi;
  54. //
  55. // if (unzGetGlobalInfo64(uf, &gi) != UNZ_OK) {
  56. // return false;
  57. // }
  58. // 尝试zip文件中找到该文件szFileName。
  59. int err = UNZ_OK;
  60. if (unzLocateFile(uf, filename, CASESENSITIVITY) != UNZ_OK) {
  61. // printf("file %s not found in the zipfile\n", filename);
  62. return false;
  63. }
  64. if (!zip_extract_currentfile(uf, save_filename)) {
  65. return false;
  66. }
  67. unzClose(uf);
  68. return true;
  69. }
  70. // 查阅: http://www.cppblog.com/Streamlet/archive/2013/05/12/127368.html
  71. /* 相关 API
  72. * 压缩相关:
  73. * zipOpen64 zipClose zipOpenNewFileInZip zipCloseFileInZip zipWriteInFileInZip
  74. *
  75. * 解压相关:
  76. * unzOpen64 unzClose unzGetGlobalInfo64 unzGoToNextFile
  77. * unzGetCurrentFileInfo64 unzOpenCurrentFile unzCloseCurrentFile unzReadCurrentFile
  78. *
  79. * 首先是压缩操作。使用 zipOpen64 来打开/创建一个 ZIP 文件,然后开始遍历要被放到压缩包中去的文件。
  80. * 针对每个文件,先调用一次 zipOpenNewFileInZip,然后开始读原始文件数据,使用 zipWriteInFileInZip 来写入到 ZIP 文件中去。
  81. * zipOpenNewFileInZip 的第三个参数是一个 zip_fileinfo 结构,该结构数据可全部置零,其中 dosDate 可用于填入一个时间(LastModificationTime)。
  82. * 它的第二个参数是 ZIP 中的文件名,若要保持目录结构,该参数中可以保留路径,如 foo/bar.txt。
  83. *
  84. * 解压操作稍微复杂一点点。打开一个 ZIP 文件后,需要先使用 unzGetGlobalInfo64 来取得该文件的一些信息,来了解这个压缩包里一共包含了多少个文件,等等。
  85. * 目前我们用得着的就是这个文件数目。然后开始遍历 ZIP 中的文件,初始时自动会定位在第一个文件,以后处理完一个后用 unzGoToNextFile 来跳到下一个文件。
  86. * 对于每个内部文件,可用 unzGetCurrentFileInfo64 来查内部文件名。这个文件名和刚才 zipOpenNewFileInZip 的第二个参数是一样的形式,所以有可能包含路径。
  87. * 也有可能会以路径分隔符(/)结尾,表明这是个目录项(其实压缩操作的时候也可以针对目录写入这样的内部文件,上面没有做)。所以接下来要根据情况创建(多级)目录。
  88. * unzGetCurrentFileInfo64 的第三个参数是 unz_file_info64 结构,其中也有一项包含了 dosDate 信息,可以还原文件时间。
  89. * 对于非目录的内部文件,用 unzOpenCurrentFile,打开,然后 unzReadCurrentFile 读取文件内容,写入到真实文件中。unzReadCurrentFile 返回 0 表示文件读取结束。
  90. *
  91. */
  92. bool cdr_extract_bmp(const char* cdr_filename, const char* bmp_filename)
  93. {
  94. if (! IsFileExist(cdr_filename))
  95. return false ;
  96. bool ret = false;
  97. int version = get_cdrfile_version(cdr_filename);
  98. // printf("\n%d\n", version);
  99. if (version >= 1400 ){
  100. ret = zip_extract_onefile(cdr_filename, "metadata/thumbnails/thumbnail.bmp", bmp_filename);
  101. if (!ret) ret = zip_extract_onefile(cdr_filename, "previews/thumbnail.png", bmp_filename);
  102. }
  103. if (version <= 1300)
  104. ret = cdr_riff_disp2bmp(cdr_filename, bmp_filename);
  105. return ret;
  106. }
  107. bool CorelThumbnail(const char* cdr_filename, const char* png_filename)
  108. {
  109. string file_ext(cdr_filename);
  110. string rs = "(.+)(\\.(?:cdr|CDR|Cdr|CDr|cdR))"; // 正则字符串,exp开始的单词
  111. std::regex expression(rs); // 字符串传递给构造函数,建立正则表达式
  112. bool ret = regex_match(file_ext, expression);
  113. if (!ret) {
  114. // cout << "文件格式不对!\n";
  115. return ret ;
  116. }
  117. FILE* pfile = fopen(cdr_filename, "rb");
  118. if(NULL == pfile){
  119. MessageBoxA(NULL, cdr_filename, "错误File", MB_OK);
  120. return false;
  121. }
  122. char bmp_filename[MAX_PATH] = {0};
  123. if (png_filename == NULL) {
  124. char tmp_filename[MAX_PATH] = {0};
  125. png_filename = tmp_filename;
  126. strcpy(tmp_filename , cdr_filename);
  127. strcpy(strrchr(tmp_filename, '.') , ".png");
  128. }
  129. strcpy(bmp_filename , png_filename);
  130. strcpy(strrchr(bmp_filename, '.') , ".bmp");
  131. // printf("%s\t\%s\n", bmp_filename , png_filename);
  132. ret = cdr_extract_bmp(cdr_filename , bmp_filename);
  133. if (!ret)
  134. return false ;
  135. CImage image; // bmp 转换 png ,需要CImage类,头文件 atlimage.h
  136. image.Load(bmp_filename);
  137. image.Save(png_filename);
  138. if (remove(bmp_filename) != 0)
  139. perror("Error deleting file");
  140. return ret;
  141. }
  142. bool CorelThumbnail_W(const wchar_t* cdr_filename, const wchar_t* png_filename)
  143. {
  144. char fromfile[MAX_PATH] = {0};
  145. char tofile[MAX_PATH] = {0};
  146. WCHARTochar(fromfile, cdr_filename);
  147. WCHARTochar(tofile, png_filename);
  148. bool ret = CorelThumbnail(fromfile, tofile);
  149. return ret;
  150. }