/uppsrc/Draw/Mify.cpp

https://github.com/ultimatepp/mirror · C++ · 214 lines · 200 code · 13 blank · 1 comment · 38 complexity · 523d22068e0ba6e28ead39489b1023cf MD5 · raw file

  1. #include "Draw.h"
  2. namespace Upp {
  3. #ifdef CPU_SIMD
  4. Image Minify(const Image& img, int nx, int ny, bool co)
  5. {
  6. ASSERT(nx > 0 && ny > 0);
  7. Size ssz = img.GetSize();
  8. Size tsz = Size((ssz.cx + nx - 1) / nx, (ssz.cy + ny - 1) / ny);
  9. ImageBuffer ib(tsz);
  10. int scx0 = ssz.cx / nx * nx;
  11. auto do_line = [&](int ty, f32x4 *b, f32x4 *div) {
  12. memset((void *)b, 0, tsz.cx * sizeof(f32x4));
  13. memset((void *)div, 0, tsz.cx * sizeof(f32x4));
  14. f32x4 v1 = f32all(1);
  15. f32x4 vnx = f32all(nx);
  16. int yy = ny * ty;
  17. for(int yi = 0; yi < ny; yi++) {
  18. int y = yy + yi;
  19. if(y < ssz.cy) {
  20. const RGBA *s = img[yy + yi];
  21. const RGBA *e = s + scx0;
  22. const RGBA *e2 = s + ssz.cx;
  23. f32x4 *t = b;
  24. f32x4 *d = div;
  25. while(s < e) {
  26. f32x4 px = 0;
  27. for(int n = nx; n--;)
  28. px += LoadRGBAF(s++);
  29. *t += px;
  30. *d += vnx;
  31. t++;
  32. d++;
  33. }
  34. if(s < e2) {
  35. f32x4 px = 0;
  36. f32x4 dv = 0;
  37. while(s < e2) {
  38. px += LoadRGBAF(s++);
  39. dv += v1;
  40. }
  41. *t += px;
  42. *d += dv;
  43. t++;
  44. d++;
  45. }
  46. ASSERT(t == b + tsz.cx);
  47. }
  48. }
  49. f32x4 *s = b;
  50. f32x4 *d = div;
  51. RGBA *t = ~ib + ty * tsz.cx;
  52. RGBA *e = t + tsz.cx;
  53. while(t < e)
  54. StoreRGBAF(t++, *s++ / *d++);
  55. };
  56. if(co) {
  57. CoWork cw;
  58. cw * [&] {
  59. Buffer<f32x4> div(tsz.cx);
  60. Buffer<f32x4> b(tsz.cx);
  61. for(;;) {
  62. int y = cw.Next();
  63. if(y >= tsz.cy)
  64. break;
  65. do_line(y, b, div);
  66. }
  67. };
  68. }
  69. else {
  70. Buffer<f32x4> div(tsz.cx);
  71. Buffer<f32x4> b(tsz.cx);
  72. for(int y = 0; y < tsz.cy; y++)
  73. do_line(y, b, div);
  74. }
  75. return ib;
  76. }
  77. #else
  78. Image Minify(const Image& img, int nx, int ny, bool co)
  79. {
  80. ASSERT(nx > 0 && ny > 0);
  81. Size ssz = img.GetSize();
  82. Size tsz = Size((ssz.cx + nx - 1) / nx, (ssz.cy + ny - 1) / ny);
  83. ImageBuffer ib(tsz);
  84. int scx0 = ssz.cx / nx * nx;
  85. auto do_line = [&](int ty, RGBAV *b, int *div) {
  86. int yy = ny * ty;
  87. for(int i = 0; i < tsz.cx; i++)
  88. b[i].Clear();
  89. memset(div, 0, tsz.cx * sizeof(int));
  90. for(int yi = 0; yi < ny; yi++) {
  91. int y = yy + yi;
  92. if(y < ssz.cy) {
  93. const RGBA *s = img[yy + yi];
  94. const RGBA *e = s + scx0;
  95. const RGBA *e2 = s + ssz.cx;
  96. RGBAV *t = b;
  97. int *dv = div;
  98. while(s < e) {
  99. for(int n = nx; n--;) {
  100. t->Put(*s++);
  101. (*dv)++;
  102. }
  103. t++;
  104. dv++;
  105. }
  106. while(s < e2) {
  107. t->Put(*s++);
  108. (*dv)++;
  109. }
  110. }
  111. }
  112. const RGBAV *s = b;
  113. const int *dv = div;
  114. RGBA *it = ~ib + ty * tsz.cx;
  115. for(int x = 0; x < tsz.cx; x++)
  116. *it++ = (s++)->Get(*dv++);
  117. };
  118. if(co) {
  119. CoWork cw;
  120. cw * [&] {
  121. Buffer<int> div(tsz.cx);
  122. Buffer<RGBAV> b(tsz.cx);
  123. for(;;) {
  124. int y = cw.Next();
  125. if(y >= tsz.cy)
  126. break;
  127. do_line(y, b, div);
  128. }
  129. };
  130. }
  131. else {
  132. Buffer<int> div(tsz.cx);
  133. Buffer<RGBAV> b(tsz.cx);
  134. for(int y = 0; y < tsz.cy; y++)
  135. do_line(y, b, div);
  136. }
  137. return ib;
  138. }
  139. #endif
  140. struct MinifyImageMaker : public ImageMaker {
  141. Image image;
  142. int nx;
  143. int ny;
  144. bool co;
  145. virtual String Key() const;
  146. virtual Image Make() const;
  147. };
  148. String MinifyImageMaker::Key() const
  149. {
  150. String key;
  151. RawCat(key, image.GetSerialId());
  152. RawCat(key, nx);
  153. RawCat(key, ny);
  154. // we are not adding co as that is just a hint for actual image making
  155. return key;
  156. }
  157. Image MinifyImageMaker::Make() const
  158. {
  159. return Minify(image, nx, ny, co);
  160. }
  161. Image MinifyCached(const Image& img, int nx, int ny, bool co)
  162. {
  163. MinifyImageMaker m;
  164. m.image = img;
  165. m.nx = nx;
  166. m.ny = ny;
  167. m.co = co;
  168. return MakeImage(m);
  169. }
  170. Image Magnify(const Image& img, int nx, int ny)
  171. {
  172. if(nx == 1 && ny == 1)
  173. return img;
  174. if(nx == 0 || ny == 0)
  175. return Image();
  176. Size sz = img.GetSize();
  177. bool xdown = nx < 0;
  178. nx = abs(nx);
  179. int ncx = xdown ? sz.cx / nx : sz.cx * nx;
  180. ImageBuffer b(ncx, sz.cy * ny);
  181. const RGBA *s = ~img;
  182. const RGBA *e = s + img.GetLength();
  183. RGBA *t = ~b;
  184. while(s < e) {
  185. RGBA *q = t;
  186. const RGBA *le = s + sz.cx;
  187. while(s < le) {
  188. Fill(q, *s, nx);
  189. q += nx;
  190. s++;
  191. }
  192. for(int n = ny - 1; n--;) {
  193. memcpy(q, t, ncx * sizeof(RGBA));
  194. q += ncx;
  195. }
  196. t = q;
  197. }
  198. b.SetResolution(img.GetResolution());
  199. return b;
  200. }
  201. };