ImgCreate.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. #include "BeefySysLib/Common.h"
  2. #include "BeefySysLib/util/Array.h"
  3. #include "BeefySysLib/img/PSDReader.h"
  4. #include "BeefySysLib/img/PNGData.h"
  5. #include <direct.h>
  6. USING_NS_BF;
  7. void Resize(ImageData* srcImage, int srcX, int srcY, int srcScale, ImageData* destImage, int destX, int destY, int scale)
  8. {
  9. if (srcScale > scale)
  10. {
  11. struct Color
  12. {
  13. uint8 mElems[4];
  14. };
  15. struct ColorT
  16. {
  17. float mElems[4];
  18. };
  19. ColorT colorT = { 0 };
  20. int sampleScale = srcScale / scale;
  21. float totalDiv = 0;
  22. for (int srcYOfs = 0; srcYOfs < sampleScale; srcYOfs++)
  23. {
  24. for (int srcXOfs = 0; srcXOfs < sampleScale; srcXOfs++)
  25. {
  26. auto color = *(Color*)&srcImage->mBits[(srcX - srcImage->mX + srcXOfs) + (srcY - srcImage->mY + srcYOfs)*srcImage->mWidth];
  27. totalDiv += 1.0f;
  28. float alpha = color.mElems[3];
  29. colorT.mElems[0] += color.mElems[0] * alpha;
  30. colorT.mElems[1] += color.mElems[1] * alpha;
  31. colorT.mElems[2] += color.mElems[2] * alpha;
  32. colorT.mElems[3] += alpha;
  33. }
  34. }
  35. Color outColor;
  36. float alpha = colorT.mElems[3] / totalDiv;
  37. float valScale = 0;
  38. if (alpha > 0)
  39. valScale = 1 / alpha / totalDiv;
  40. outColor.mElems[0] = (int)round(colorT.mElems[0] * valScale);
  41. outColor.mElems[1] = (int)round(colorT.mElems[1] * valScale);
  42. outColor.mElems[2] = (int)round(colorT.mElems[2] * valScale);
  43. outColor.mElems[3] = (int)round(alpha);
  44. destImage->mBits[destX + destY * destImage->mWidth] = *(uint32*)&outColor;
  45. }
  46. else
  47. {
  48. uint32 color = srcImage->mBits[(srcX - srcImage->mX) + (srcY - srcImage->mY)*srcImage->mWidth];
  49. destImage->mBits[destX + destY * destImage->mWidth] = color;
  50. }
  51. }
  52. void ConvImage(const StringImpl& baseName, int wantSize)
  53. {
  54. PNGData srcImage;
  55. bool success = srcImage.LoadFromFile(baseName + "_4.png");
  56. BF_ASSERT(success);
  57. int srcScale = 4;
  58. int destScale = 1 << wantSize;
  59. PNGData destImage;
  60. destImage.CreateNew(srcImage.mWidth * destScale / srcScale, srcImage.mHeight * destScale / srcScale);
  61. for (int destY = 0; destY < destImage.mHeight; destY++)
  62. {
  63. for (int destX = 0; destX < destImage.mWidth; destX++)
  64. {
  65. Resize(&srcImage, destX * srcScale / destScale, destY * srcScale / destScale, srcScale, &destImage, destX, destY, destScale);
  66. }
  67. }
  68. String destName;
  69. if (wantSize == 0)
  70. destName = baseName + ".png";
  71. else
  72. destName = baseName + StrFormat("_%d.png", destScale);
  73. success = destImage.WriteToFile(destName);
  74. BF_ASSERT(success);
  75. }
  76. int main()
  77. {
  78. int baseWidth = 0;
  79. int baseHeight = 0;
  80. bool isThemeDir = false;
  81. PSDReader readers[2][3];
  82. ImageData* imageDatas[2][3] = { NULL };
  83. for (int pass = 0; pass < 2; pass++)
  84. {
  85. for (int size = 0; size < 3; size++)
  86. {
  87. auto& reader = readers[pass][size];
  88. auto& imageData = imageDatas[pass][size];
  89. String fileName;
  90. if (pass == 0)
  91. {
  92. if (size == 0)
  93. fileName = "DarkUI.psd";
  94. else if (size == 1)
  95. fileName = "DarkUI_2.psd";
  96. else
  97. fileName = "DarkUI_4.psd";
  98. if (!FileExists(fileName))
  99. {
  100. String checkFileName = "../../images/" + fileName;
  101. if (FileExists(checkFileName))
  102. {
  103. isThemeDir = true;
  104. fileName = checkFileName;
  105. }
  106. }
  107. }
  108. else
  109. {
  110. if (size == 0)
  111. fileName = "UI.psd";
  112. else if (size == 1)
  113. fileName = "UI_2.psd";
  114. else
  115. fileName = "UI_4.psd";
  116. if (!FileExists(fileName))
  117. {
  118. if (!isThemeDir)
  119. continue;
  120. fileName.RemoveFromEnd(3);
  121. fileName += "png";
  122. if (!FileExists(fileName))
  123. continue;
  124. }
  125. }
  126. if (fileName.EndsWith(".png"))
  127. {
  128. PNGData* pngData = new PNGData();
  129. if (pngData->LoadFromFile(fileName))
  130. {
  131. imageData = pngData;
  132. }
  133. }
  134. else
  135. {
  136. if (!reader.Init(fileName))
  137. {
  138. if (size == 0)
  139. {
  140. printf("Failed to open %s - incorrect working directory?", fileName.c_str());
  141. return 1;
  142. }
  143. imageData = NULL;
  144. continue;
  145. }
  146. if ((size == 0) && (pass == 0))
  147. {
  148. baseWidth = reader.mWidth;
  149. baseHeight = reader.mHeight;
  150. }
  151. std::vector<int> layerIndices;
  152. for (int layerIdx = 0; layerIdx < (int)reader.mPSDLayerInfoVector.size(); layerIdx++)
  153. {
  154. auto layer = reader.mPSDLayerInfoVector[layerIdx];
  155. if (layer->mVisible)
  156. layerIndices.insert(layerIndices.begin(), layerIdx);
  157. }
  158. imageData = reader.ReadImageData();
  159. if (imageData == NULL)
  160. {
  161. ImageData* rawImageData = reader.MergeLayers(NULL, layerIndices, NULL);;
  162. if ((rawImageData->mX == 0) && (rawImageData->mY == 0) &&
  163. (rawImageData->mWidth == reader.mWidth) &&
  164. (rawImageData->mHeight == reader.mHeight))
  165. {
  166. imageData = rawImageData;
  167. }
  168. else
  169. {
  170. imageData = new ImageData();
  171. imageData->CreateNew(reader.mWidth, reader.mHeight);
  172. imageData->CopyFrom(rawImageData, 0, 0);
  173. delete rawImageData;
  174. }
  175. }
  176. // else
  177. // {
  178. // PNGData pngData;
  179. // pngData.mWidth = imageData->mWidth;
  180. // pngData.mHeight = imageData->mHeight;
  181. // pngData.mBits = imageData->mBits;
  182. // pngData.WriteToFile("c:\\temp\\test.png");
  183. // pngData.mBits = NULL;
  184. // }
  185. }
  186. }
  187. }
  188. int numCols = baseWidth / 20;
  189. int numRows = baseHeight / 20;
  190. auto _HasImage = [&](int col, int row, int pass, int size)
  191. {
  192. int scale = 1 << size;
  193. auto srcImage = imageDatas[pass][size];
  194. if (srcImage == NULL)
  195. return false;
  196. int xStart = (col * 20 * scale);
  197. int yStart = (row * 20 * scale);
  198. if ((xStart < srcImage->mX) || (xStart + 20 * scale > srcImage->mX + srcImage->mWidth))
  199. return false;
  200. if ((yStart < srcImage->mY) || (yStart + 20 * scale > srcImage->mY + srcImage->mHeight))
  201. return false;
  202. for (int yOfs = 0; yOfs < 20 * scale; yOfs++)
  203. {
  204. for (int xOfs = 0; xOfs < 20 * scale; xOfs++)
  205. {
  206. int srcX = xStart + xOfs;
  207. int srcY = yStart + yOfs;
  208. auto color = srcImage->mBits[(srcX - srcImage->mX) + (srcY - srcImage->mY)*srcImage->mWidth];
  209. if ((color & 0xFF000000) != 0)
  210. return true;
  211. }
  212. }
  213. return false;
  214. };
  215. auto _HasUniqueThemeImage = [&](int col, int row, int size)
  216. {
  217. if (!_HasImage(col, row, 1, size))
  218. return false;
  219. int scale = 1 << size;
  220. auto srcImage0 = imageDatas[0][size];
  221. if (srcImage0 == NULL)
  222. return false;
  223. auto srcImage1 = imageDatas[1][size];
  224. if (srcImage1 == NULL)
  225. return false;
  226. int xStart = (col * 20 * scale);
  227. int yStart = (row * 20 * scale);
  228. if ((xStart < srcImage1->mX) || (xStart + 20 * scale > srcImage1->mX + srcImage1->mWidth))
  229. return false;
  230. if ((yStart < srcImage1->mY) || (yStart + 20 * scale > srcImage1->mY + srcImage1->mHeight))
  231. return false;
  232. for (int yOfs = 0; yOfs < 20 * scale; yOfs++)
  233. {
  234. for (int xOfs = 0; xOfs < 20 * scale; xOfs++)
  235. {
  236. int srcX = xStart + xOfs;
  237. int srcY = yStart + yOfs;
  238. auto color0 = srcImage0->mBits[(srcX - srcImage0->mX) + (srcY - srcImage0->mY)*srcImage0->mWidth];
  239. auto color1 = srcImage1->mBits[(srcX - srcImage1->mX) + (srcY - srcImage1->mY)*srcImage1->mWidth];
  240. if ((color0 & 0xFF000000) == 0)
  241. color0 = 0;
  242. if ((color1 & 0xFF000000) == 0)
  243. color1 = 0;
  244. if (color0 != color1)
  245. return true;
  246. }
  247. }
  248. return false;
  249. };
  250. if (isThemeDir)
  251. _mkdir("cache");
  252. for (int size = 0; size < 3; size++)
  253. {
  254. int scale = 1 << size;
  255. int outWidth = baseWidth * scale;
  256. int outHeight = baseHeight * scale;
  257. PNGData pngData;
  258. pngData.CreateNew(outWidth, outHeight);
  259. if ((size < 2) && (!isThemeDir))
  260. {
  261. ConvImage("IconError", size);
  262. ConvImage("IconWarning", size);
  263. }
  264. String fileName;
  265. if (isThemeDir)
  266. {
  267. if (size == 0)
  268. fileName = "cache/UI.png";
  269. else if (size == 1)
  270. fileName = "cache/UI_2.png";
  271. else
  272. fileName = "cache/UI_4.png";
  273. }
  274. else
  275. {
  276. if (size == 0)
  277. fileName = "DarkUI.png";
  278. else if (size == 1)
  279. fileName = "DarkUI_2.png";
  280. else
  281. fileName = "DarkUI_4.png";
  282. }
  283. for (int row = 0; row < numRows; row++)
  284. {
  285. for (int col = 0; col < numCols; col++)
  286. {
  287. int srcPass = 0;
  288. int srcSize = size;
  289. if (_HasImage(col, row, 1, size)) // Theme has image of appropriate size
  290. {
  291. srcPass = 1;
  292. srcSize = size;
  293. }
  294. else if (_HasUniqueThemeImage(col, row, 2)) // Use resized theme image
  295. {
  296. srcPass = 1;
  297. srcSize = 2;
  298. }
  299. else if (_HasUniqueThemeImage(col, row, 1)) // Use resized theme image
  300. {
  301. srcPass = 1;
  302. srcSize = 2;
  303. }
  304. else if (_HasUniqueThemeImage(col, row, 0)) // Use resized theme image instead
  305. {
  306. srcPass = 1;
  307. srcSize = 0;
  308. }
  309. else if (_HasImage(col, row, 0, size)) // Use original image
  310. {
  311. srcPass = 0;
  312. srcSize = size;
  313. }
  314. else if (_HasImage(col, row, 0, 2)) // Use resized original image
  315. {
  316. srcPass = 0;
  317. srcSize = 2;
  318. }
  319. else if (_HasImage(col, row, 0, 1)) // Use resized original image
  320. {
  321. srcPass = 0;
  322. srcSize = 1;
  323. }
  324. else // Use resized original image
  325. {
  326. srcPass = 0;
  327. srcSize = 0;
  328. }
  329. int srcScale = 1 << srcSize;
  330. for (int yOfs = 0; yOfs < 20 * scale; yOfs++)
  331. {
  332. for (int xOfs = 0; xOfs < 20 * scale; xOfs++)
  333. {
  334. int destX = (col * 20 * scale) + xOfs;
  335. int destY = (row * 20 * scale) + yOfs;
  336. int srcX = (col * 20 * srcScale) + xOfs * srcScale / scale;
  337. int srcY = (row * 20 * srcScale) + yOfs * srcScale / scale;
  338. auto srcImage = imageDatas[srcPass][srcSize];
  339. if ((srcX >= srcImage->mX) && (srcY >= srcImage->mY) &&
  340. (srcX < srcImage->mX + srcImage->mWidth) &&
  341. (srcY < srcImage->mY + srcImage->mHeight))
  342. {
  343. Resize(srcImage, srcX, srcY, srcScale, &pngData, destX, destY, scale);
  344. }
  345. }
  346. }
  347. }
  348. }
  349. bool success = pngData.WriteToFile(fileName);
  350. BF_ASSERT(success);
  351. }
  352. }