uGBEImageUtils.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. unit uGBEImageUtils;
  2. interface
  3. uses
  4. System.UITypes,
  5. System.SysUtils,
  6. System.UIConsts,
  7. System.Types,
  8. FMX.Effects,
  9. FMX.Graphics;
  10. // https://fr.wikipedia.org/wiki/Algorithme_Diamant-Carr%C3%A9
  11. function GenerateDiamondSquare(size, blurLevel: integer;
  12. color: TAlphaColor = TAlphaColorRec.White; bordure: boolean = false;
  13. colorBordure: TAlphaColor = TAlphaColorRec.Black): TBitmap;
  14. function TileImage(imageOrigine: TBitmap; nbX, nbY: integer): TBitmap;
  15. function CropImage(originBitmap: TBitmap;
  16. Xpos, Ypos, width, height: integer): TBitmap;
  17. function MultiTexturing(imgCarte, imgFond, imgCanalRouge, imgCanalVert,
  18. imgCanalBleu: TBitmap; tailleCrop: integer): TBitmap;
  19. function MultiTexturingZone(img: TBitmap): TBitmap;
  20. function MixerCouleurPixel(cCarte: TAlphaColor; x, y: integer): TAlphaColor;
  21. var
  22. TextureCanalNoir, TextureCanalRouge, TextureCanalVert,
  23. TextureCanalBleu: TBitmap;
  24. BitmapDataCanalNoir, BitmapDataCanalRouge, BitmapDataCanalVert,
  25. BitmapDataCanalBleu: TBitmapData;
  26. implementation // --------------------------------------------------------------
  27. function GenerateDiamondSquare(size, blurLevel: integer;
  28. color: TAlphaColor = TAlphaColorRec.White; bordure: boolean = false;
  29. colorBordure: TAlphaColor = TAlphaColorRec.Black): TBitmap;
  30. var
  31. bmp: TBitmap;
  32. BitmapData: TBitmapData;
  33. i, h, x, y, id, decallage, somme, n, min: integer;
  34. moyenne: single;
  35. rec: TAlphaColorRec;
  36. aByte: Byte;
  37. aR, aG, aB: single;
  38. begin
  39. bmp := TBitmap.Create;
  40. Result := TBitmap.Create;
  41. h := size;
  42. bmp.width := h;
  43. bmp.height := h;
  44. if bordure then
  45. bmp.Clear(colorBordure);
  46. aR := TAlphaColorRec(color).R / 255;
  47. aG := TAlphaColorRec(color).G / 255;
  48. aB := TAlphaColorRec(color).B / 255;
  49. try
  50. if bmp.Map(TMapAccess.ReadWrite, bitmapData) then
  51. begin
  52. if bordure then
  53. begin
  54. bitmapData.SetPixel(1, 1, color);
  55. bitmapData.SetPixel(1, h - 2, color);
  56. bitmapData.SetPixel(h - 2, h - 2, color);
  57. bitmapData.SetPixel(h - 2, 1, color);
  58. h := h - 2;
  59. i := bmp.width - 2;
  60. min := 2;
  61. end
  62. else
  63. begin
  64. bitmapData.SetPixel(0, 0, color);
  65. bitmapData.SetPixel(0, h - 1, color);
  66. bitmapData.SetPixel(h - 1, h - 1, color);
  67. bitmapData.SetPixel(h - 1, 0, color);
  68. i := bmp.width - 1;
  69. min := 1;
  70. end;
  71. while i > min do
  72. begin
  73. id := trunc(i / 2);
  74. // phase diamond
  75. for x := id to h do
  76. begin
  77. for y := id to h do
  78. begin
  79. moyenne := (CorrectColor(bitmapData.GetPixel(x - id, y - id)) +
  80. CorrectColor(bitmapData.GetPixel(x - id, y + id)) +
  81. CorrectColor(bitmapData.GetPixel(x + id, y + id)) +
  82. CorrectColor(bitmapData.GetPixel(x + id, y - id))) / 4;
  83. aByte := Round(moyenne + random(id));
  84. rec.A := $FF;
  85. rec.R := Round(aByte * aR);
  86. rec.G := Round(aByte * aG);
  87. rec.B := Round(aByte * aB);
  88. bitmapData.SetPixel(x, y, TAlphaColor(rec));
  89. end;
  90. end;
  91. decallage := min - 1;
  92. for x := min - 1 to h do
  93. begin
  94. if decallage = min - 1 then
  95. decallage := id
  96. else
  97. decallage := min - 1;
  98. for y := decallage to h do
  99. begin
  100. somme := 0;
  101. n := 0;
  102. if x >= id then
  103. begin
  104. somme := somme + CorrectColor(bitmapData.GetPixel(x - id, y));
  105. n := n + 1;
  106. end;
  107. if x + id < h then
  108. begin
  109. somme := somme + CorrectColor(bitmapData.GetPixel(x + id, y));
  110. n := n + 1;
  111. end;
  112. if y > id then
  113. begin
  114. somme := somme + CorrectColor(bitmapData.GetPixel(x, y - id));
  115. n := n + 1;
  116. end;
  117. if y + id < h then
  118. begin
  119. somme := somme + CorrectColor(bitmapData.GetPixel(x, y + id));
  120. n := n + 1;
  121. end;
  122. aByte := Round(somme / n + random(id));
  123. rec.A := $FF;
  124. rec.R := Round(aByte * aR);
  125. rec.G := Round(aByte * aG);
  126. rec.B := Round(aByte * aB);
  127. bitmapData.SetPixel(x, y, TAlphaColor(rec));
  128. end;
  129. end;
  130. i := id;
  131. end;
  132. end;
  133. finally
  134. bmp.Unmap(bitmapData);
  135. blur(bmp.Canvas, bmp, blurLevel);
  136. result.width := bmp.width;
  137. result.height := bmp.height;
  138. result.CopyFromBitmap(bmp);
  139. freeAndNil(bmp);
  140. end;
  141. end;
  142. function TileImage(imageOrigine: TBitmap; nbX, nbY: integer): TBitmap;
  143. var
  144. x, y: integer;
  145. dX, dY: integer;
  146. tileBmp: TBitmap;
  147. begin
  148. tileBmp := TBitmap.Create;
  149. tileBmp.width := imageOrigine.width * nbX;
  150. tileBmp.height := imageOrigine.height * nbY;
  151. dX := imageOrigine.width;
  152. dY := imageOrigine.height;
  153. tileBmp.Canvas.BeginScene;
  154. y := 0;
  155. while y <= tileBmp.height do
  156. begin
  157. x := 0;
  158. while x <= tileBmp.width do
  159. begin
  160. tileBmp.Canvas.DrawBitmap(imageOrigine, Rectf(0, 0, dX, dY),
  161. Rectf(x, y, x + dX, y + dY), 1);
  162. Inc(x, dX);
  163. end;
  164. Inc(y, dY);
  165. end;
  166. tileBmp.Canvas.EndScene;
  167. Result := TBitmap.Create;
  168. Result.width := tileBmp.width;
  169. Result.height := tileBmp.height;
  170. Result.CopyFromBitmap(tileBmp);
  171. FreeAndNil(TileBmp);
  172. end;
  173. function CropImage(originBitmap: TBitmap;
  174. Xpos, Ypos, width, height: integer): TBitmap;
  175. var
  176. iRect: TRect;
  177. begin
  178. iRect.Left := Xpos;
  179. iRect.Top := Ypos;
  180. iRect.width := width;
  181. iRect.height := height;
  182. Result := TBitmap.Create;
  183. Result.width := width;
  184. Result.height := height;
  185. Result.CopyFromBitmap(originBitmap, iRect, 0, 0);
  186. end;
  187. function MultiTexturing(imgCarte, imgFond, imgCanalRouge, imgCanalVert,
  188. imgCanalBleu: TBitmap; tailleCrop: integer): TBitmap;
  189. var
  190. bmpSortie, imagecrop: TBitmap;
  191. x, y: integer;
  192. iRect: TRect;
  193. begin
  194. x := 0;
  195. y := 0;
  196. TextureCanalNoir := TBitmap.Create(imgFond.width, imgFond.height);
  197. TextureCanalNoir.Assign(imgFond);
  198. TextureCanalNoir.Map(TMapAccess.Read, BitmapDataCanalNoir);
  199. TextureCanalBleu := TBitmap.Create(imgCanalBleu.width, imgCanalBleu.height);
  200. TextureCanalBleu.Assign(imgCanalBleu);
  201. TextureCanalBleu.Map(TMapAccess.Read, BitmapDataCanalBleu);
  202. TextureCanalRouge := TBitmap.Create(imgCanalRouge.width,
  203. imgCanalRouge.height);
  204. TextureCanalRouge.Assign(imgCanalRouge);
  205. TextureCanalRouge.Map(TMapAccess.Read, BitmapDataCanalRouge);
  206. TextureCanalVert := TBitmap.Create(imgCanalVert.width, imgCanalVert.height);
  207. TextureCanalVert.Assign(imgCanalVert);
  208. TextureCanalVert.Map(TMapAccess.Read, BitmapDataCanalVert);
  209. iRect.Left := 0;
  210. iRect.Top := 0;
  211. iRect.width := tailleCrop;
  212. iRect.height := tailleCrop;
  213. bmpSortie := TBitmap.Create(tailleCrop, tailleCrop);
  214. imagecrop := TBitmap.Create(tailleCrop, tailleCrop);
  215. result := TBitmap.Create(imgCarte.width, imgCarte.height);
  216. while y < imgCarte.height do
  217. begin
  218. while x < imgCarte.width do
  219. begin
  220. imagecrop.CopyFromBitmap(CropImage(imgCarte, x, y, tailleCrop,
  221. tailleCrop));
  222. bmpSortie.CopyFromBitmap(MultiTexturingZone(imagecrop));
  223. result.CopyFromBitmap(bmpSortie, iRect, x, y);
  224. x := x + tailleCrop;
  225. end;
  226. y := y + tailleCrop;
  227. x := 0;
  228. end;
  229. TextureCanalNoir.Unmap(BitmapDataCanalNoir);
  230. TextureCanalBleu.Unmap(BitmapDataCanalBleu);
  231. TextureCanalRouge.Unmap(BitmapDataCanalRouge);
  232. TextureCanalVert.Unmap(BitmapDataCanalVert);
  233. end;
  234. function MultiTexturingZone(img: TBitmap): TBitmap;
  235. var
  236. bmp: TBitmap;
  237. BitmapData: TBitmapData;
  238. i, j: integer;
  239. begin
  240. try
  241. bmp := TBitmap.Create(img.width, img.height);
  242. bmp.Assign(img);
  243. if (bmp.Map(TMapAccess.ReadWrite, bitmapData)) then
  244. begin
  245. for i := 0 to bmp.height - 1 do
  246. begin
  247. for j := 0 to bmp.width - 1 do
  248. begin
  249. bitmapData.SetPixel(j, i,
  250. MixerCouleurPixel(CorrectColor(bitmapData.GetPixel(j, i)), j, i));
  251. end;
  252. end;
  253. end;
  254. bmp.Unmap(bitmapData);
  255. Result := TBitmap.Create(bmp.width, bmp.height);
  256. Result.CopyFromBitmap(bmp);
  257. finally
  258. FreeAndNil(bmp);
  259. end;
  260. end;
  261. function MixerCouleurPixel(cCarte: TAlphaColor; x, y: integer): TAlphaColor;
  262. var
  263. rCarte, gCarte, bCarte, rFond, gFond, bFond, rTextureRouge, gTextureRouge,
  264. bTextureRouge, rTextureVert, gTextureVert, bTextureVert, rTextureBleu,
  265. gTextureBleu, bTextureBleu: Byte;
  266. couleurResult: TAlphaColorRec;
  267. resTemp1, resTemp2: single;
  268. begin
  269. rCarte := TAlphaColorRec(cCarte).R;
  270. gCarte := TAlphaColorRec(cCarte).G;
  271. bCarte := TAlphaColorRec(cCarte).B;
  272. rFond := TAlphaColorRec(BitmapDataCanalNoir.GetPixel(x, y)).R;
  273. gFond := TAlphaColorRec(BitmapDataCanalNoir.GetPixel(x, y)).G;
  274. bFond := TAlphaColorRec(BitmapDataCanalNoir.GetPixel(x, y)).B;
  275. rTextureRouge := TAlphaColorRec(BitmapDataCanalRouge.GetPixel(x, y)).R;
  276. gTextureRouge := TAlphaColorRec(BitmapDataCanalRouge.GetPixel(x, y)).G;
  277. bTextureRouge := TAlphaColorRec(BitmapDataCanalRouge.GetPixel(x, y)).B;
  278. rTextureVert := TAlphaColorRec(BitmapDataCanalVert.GetPixel(x, y)).R;
  279. gTextureVert := TAlphaColorRec(BitmapDataCanalVert.GetPixel(x, y)).G;
  280. bTextureVert := TAlphaColorRec(BitmapDataCanalVert.GetPixel(x, y)).B;
  281. rTextureBleu := TAlphaColorRec(BitmapDataCanalBleu.GetPixel(x, y)).R;
  282. gTextureBleu := TAlphaColorRec(BitmapDataCanalBleu.GetPixel(x, y)).G;
  283. bTextureBleu := TAlphaColorRec(BitmapDataCanalBleu.GetPixel(x, y)).B;
  284. couleurResult.R := rFond;
  285. couleurResult.G := gFond;
  286. couleurResult.B := bFond;
  287. couleurResult.A := 255;
  288. if (rCarte > gCarte) and (rCarte > bCarte) then
  289. begin // Couleur dominante rouge => utilisation de la texture correspondante au rouge
  290. resTemp1 := (255 - rCarte) / 255;
  291. resTemp2 := rCarte / 255;
  292. couleurResult.R := Round(resTemp1 * rFond + resTemp2 * rTextureRouge);
  293. couleurResult.G := Round(resTemp1 * gFond + resTemp2 * gTextureRouge);
  294. couleurResult.B := Round(resTemp1 * bFond + resTemp2 * bTextureRouge);
  295. end
  296. else
  297. begin
  298. if (gCarte > rCarte) and (gCarte > bCarte) then
  299. begin // Couleur dominante vert => utilisation de la texture correspondante au vert
  300. resTemp1 := (255 - gCarte) / 255;
  301. resTemp2 := gCarte / 255;
  302. couleurResult.R := Round(resTemp1 * rFond + resTemp2 * rTextureVert);
  303. couleurResult.G := Round(resTemp1 * gFond + resTemp2 * gTextureVert);
  304. couleurResult.B := Round(resTemp1 * bFond + resTemp2 * bTextureVert);
  305. end
  306. else
  307. begin
  308. if (bCarte > rCarte) and (bCarte > gCarte) then
  309. begin // Couleur dominante bleu => utilisation de la texture correspondante au bleu
  310. resTemp1 := (255 - bCarte) / 255;
  311. resTemp2 := bCarte / 255;
  312. couleurResult.R := Round(resTemp1 * rFond + resTemp2 * rTextureBleu);
  313. couleurResult.G := Round(resTemp1 * gFond + resTemp2 * gTextureBleu);
  314. couleurResult.B := Round(resTemp1 * bFond + resTemp2 * bTextureBleu);
  315. end;
  316. end;
  317. end;
  318. Result := CorrectColor(TAlphaColor(couleurResult));
  319. end;
  320. end.