Reduce.c 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483
  1. #include "Imaging.h"
  2. #include <math.h>
  3. #define ROUND_UP(f) ((int)((f) >= 0.0 ? (f) + 0.5F : (f)-0.5F))
  4. UINT32
  5. division_UINT32(int divider, int result_bits) {
  6. UINT32 max_dividend = (1 << result_bits) * divider;
  7. float max_int = (1 << 30) * 4.0;
  8. return (UINT32)(max_int / max_dividend);
  9. }
  10. void
  11. ImagingReduceNxN(Imaging imOut, Imaging imIn, int box[4], int xscale, int yscale) {
  12. /* The most general implementation for any xscale and yscale
  13. */
  14. int x, y, xx, yy;
  15. UINT32 multiplier = division_UINT32(yscale * xscale, 8);
  16. UINT32 amend = yscale * xscale / 2;
  17. if (imIn->image8) {
  18. for (y = 0; y < box[3] / yscale; y++) {
  19. int yy_from = box[1] + y * yscale;
  20. for (x = 0; x < box[2] / xscale; x++) {
  21. int xx_from = box[0] + x * xscale;
  22. UINT32 ss = amend;
  23. for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
  24. UINT8 *line0 = (UINT8 *)imIn->image8[yy];
  25. UINT8 *line1 = (UINT8 *)imIn->image8[yy + 1];
  26. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  27. ss += line0[xx + 0] + line0[xx + 1] + line1[xx + 0] +
  28. line1[xx + 1];
  29. }
  30. if (xscale & 0x01) {
  31. ss += line0[xx + 0] + line1[xx + 0];
  32. }
  33. }
  34. if (yscale & 0x01) {
  35. UINT8 *line = (UINT8 *)imIn->image8[yy];
  36. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  37. ss += line[xx + 0] + line[xx + 1];
  38. }
  39. if (xscale & 0x01) {
  40. ss += line[xx + 0];
  41. }
  42. }
  43. imOut->image8[y][x] = (ss * multiplier) >> 24;
  44. }
  45. }
  46. } else {
  47. for (y = 0; y < box[3] / yscale; y++) {
  48. int yy_from = box[1] + y * yscale;
  49. if (imIn->bands == 2) {
  50. for (x = 0; x < box[2] / xscale; x++) {
  51. int xx_from = box[0] + x * xscale;
  52. UINT32 v;
  53. UINT32 ss0 = amend, ss3 = amend;
  54. for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
  55. UINT8 *line0 = (UINT8 *)imIn->image[yy];
  56. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  57. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  58. ss0 += line0[xx * 4 + 0] + line0[xx * 4 + 4] +
  59. line1[xx * 4 + 0] + line1[xx * 4 + 4];
  60. ss3 += line0[xx * 4 + 3] + line0[xx * 4 + 7] +
  61. line1[xx * 4 + 3] + line1[xx * 4 + 7];
  62. }
  63. if (xscale & 0x01) {
  64. ss0 += line0[xx * 4 + 0] + line1[xx * 4 + 0];
  65. ss3 += line0[xx * 4 + 3] + line1[xx * 4 + 3];
  66. }
  67. }
  68. if (yscale & 0x01) {
  69. UINT8 *line = (UINT8 *)imIn->image[yy];
  70. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  71. ss0 += line[xx * 4 + 0] + line[xx * 4 + 4];
  72. ss3 += line[xx * 4 + 3] + line[xx * 4 + 7];
  73. }
  74. if (xscale & 0x01) {
  75. ss0 += line[xx * 4 + 0];
  76. ss3 += line[xx * 4 + 3];
  77. }
  78. }
  79. v = MAKE_UINT32(
  80. (ss0 * multiplier) >> 24, 0, 0, (ss3 * multiplier) >> 24);
  81. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  82. }
  83. } else if (imIn->bands == 3) {
  84. for (x = 0; x < box[2] / xscale; x++) {
  85. int xx_from = box[0] + x * xscale;
  86. UINT32 v;
  87. UINT32 ss0 = amend, ss1 = amend, ss2 = amend;
  88. for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
  89. UINT8 *line0 = (UINT8 *)imIn->image[yy];
  90. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  91. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  92. ss0 += line0[xx * 4 + 0] + line0[xx * 4 + 4] +
  93. line1[xx * 4 + 0] + line1[xx * 4 + 4];
  94. ss1 += line0[xx * 4 + 1] + line0[xx * 4 + 5] +
  95. line1[xx * 4 + 1] + line1[xx * 4 + 5];
  96. ss2 += line0[xx * 4 + 2] + line0[xx * 4 + 6] +
  97. line1[xx * 4 + 2] + line1[xx * 4 + 6];
  98. }
  99. if (xscale & 0x01) {
  100. ss0 += line0[xx * 4 + 0] + line1[xx * 4 + 0];
  101. ss1 += line0[xx * 4 + 1] + line1[xx * 4 + 1];
  102. ss2 += line0[xx * 4 + 2] + line1[xx * 4 + 2];
  103. }
  104. }
  105. if (yscale & 0x01) {
  106. UINT8 *line = (UINT8 *)imIn->image[yy];
  107. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  108. ss0 += line[xx * 4 + 0] + line[xx * 4 + 4];
  109. ss1 += line[xx * 4 + 1] + line[xx * 4 + 5];
  110. ss2 += line[xx * 4 + 2] + line[xx * 4 + 6];
  111. }
  112. if (xscale & 0x01) {
  113. ss0 += line[xx * 4 + 0];
  114. ss1 += line[xx * 4 + 1];
  115. ss2 += line[xx * 4 + 2];
  116. }
  117. }
  118. v = MAKE_UINT32(
  119. (ss0 * multiplier) >> 24,
  120. (ss1 * multiplier) >> 24,
  121. (ss2 * multiplier) >> 24,
  122. 0);
  123. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  124. }
  125. } else { // bands == 4
  126. for (x = 0; x < box[2] / xscale; x++) {
  127. int xx_from = box[0] + x * xscale;
  128. UINT32 v;
  129. UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
  130. for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
  131. UINT8 *line0 = (UINT8 *)imIn->image[yy];
  132. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  133. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  134. ss0 += line0[xx * 4 + 0] + line0[xx * 4 + 4] +
  135. line1[xx * 4 + 0] + line1[xx * 4 + 4];
  136. ss1 += line0[xx * 4 + 1] + line0[xx * 4 + 5] +
  137. line1[xx * 4 + 1] + line1[xx * 4 + 5];
  138. ss2 += line0[xx * 4 + 2] + line0[xx * 4 + 6] +
  139. line1[xx * 4 + 2] + line1[xx * 4 + 6];
  140. ss3 += line0[xx * 4 + 3] + line0[xx * 4 + 7] +
  141. line1[xx * 4 + 3] + line1[xx * 4 + 7];
  142. }
  143. if (xscale & 0x01) {
  144. ss0 += line0[xx * 4 + 0] + line1[xx * 4 + 0];
  145. ss1 += line0[xx * 4 + 1] + line1[xx * 4 + 1];
  146. ss2 += line0[xx * 4 + 2] + line1[xx * 4 + 2];
  147. ss3 += line0[xx * 4 + 3] + line1[xx * 4 + 3];
  148. }
  149. }
  150. if (yscale & 0x01) {
  151. UINT8 *line = (UINT8 *)imIn->image[yy];
  152. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  153. ss0 += line[xx * 4 + 0] + line[xx * 4 + 4];
  154. ss1 += line[xx * 4 + 1] + line[xx * 4 + 5];
  155. ss2 += line[xx * 4 + 2] + line[xx * 4 + 6];
  156. ss3 += line[xx * 4 + 3] + line[xx * 4 + 7];
  157. }
  158. if (xscale & 0x01) {
  159. ss0 += line[xx * 4 + 0];
  160. ss1 += line[xx * 4 + 1];
  161. ss2 += line[xx * 4 + 2];
  162. ss3 += line[xx * 4 + 3];
  163. }
  164. }
  165. v = MAKE_UINT32(
  166. (ss0 * multiplier) >> 24,
  167. (ss1 * multiplier) >> 24,
  168. (ss2 * multiplier) >> 24,
  169. (ss3 * multiplier) >> 24);
  170. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  171. }
  172. }
  173. }
  174. }
  175. }
  176. void
  177. ImagingReduce1xN(Imaging imOut, Imaging imIn, int box[4], int yscale) {
  178. /* Optimized implementation for xscale = 1.
  179. */
  180. int x, y, yy;
  181. int xscale = 1;
  182. UINT32 multiplier = division_UINT32(yscale * xscale, 8);
  183. UINT32 amend = yscale * xscale / 2;
  184. if (imIn->image8) {
  185. for (y = 0; y < box[3] / yscale; y++) {
  186. int yy_from = box[1] + y * yscale;
  187. for (x = 0; x < box[2] / xscale; x++) {
  188. int xx = box[0] + x * xscale;
  189. UINT32 ss = amend;
  190. for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
  191. UINT8 *line0 = (UINT8 *)imIn->image8[yy];
  192. UINT8 *line1 = (UINT8 *)imIn->image8[yy + 1];
  193. ss += line0[xx + 0] + line1[xx + 0];
  194. }
  195. if (yscale & 0x01) {
  196. UINT8 *line = (UINT8 *)imIn->image8[yy];
  197. ss += line[xx + 0];
  198. }
  199. imOut->image8[y][x] = (ss * multiplier) >> 24;
  200. }
  201. }
  202. } else {
  203. for (y = 0; y < box[3] / yscale; y++) {
  204. int yy_from = box[1] + y * yscale;
  205. if (imIn->bands == 2) {
  206. for (x = 0; x < box[2] / xscale; x++) {
  207. int xx = box[0] + x * xscale;
  208. UINT32 v;
  209. UINT32 ss0 = amend, ss3 = amend;
  210. for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
  211. UINT8 *line0 = (UINT8 *)imIn->image[yy];
  212. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  213. ss0 += line0[xx * 4 + 0] + line1[xx * 4 + 0];
  214. ss3 += line0[xx * 4 + 3] + line1[xx * 4 + 3];
  215. }
  216. if (yscale & 0x01) {
  217. UINT8 *line = (UINT8 *)imIn->image[yy];
  218. ss0 += line[xx * 4 + 0];
  219. ss3 += line[xx * 4 + 3];
  220. }
  221. v = MAKE_UINT32(
  222. (ss0 * multiplier) >> 24, 0, 0, (ss3 * multiplier) >> 24);
  223. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  224. }
  225. } else if (imIn->bands == 3) {
  226. for (x = 0; x < box[2] / xscale; x++) {
  227. int xx = box[0] + x * xscale;
  228. UINT32 v;
  229. UINT32 ss0 = amend, ss1 = amend, ss2 = amend;
  230. for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
  231. UINT8 *line0 = (UINT8 *)imIn->image[yy];
  232. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  233. ss0 += line0[xx * 4 + 0] + line1[xx * 4 + 0];
  234. ss1 += line0[xx * 4 + 1] + line1[xx * 4 + 1];
  235. ss2 += line0[xx * 4 + 2] + line1[xx * 4 + 2];
  236. }
  237. if (yscale & 0x01) {
  238. UINT8 *line = (UINT8 *)imIn->image[yy];
  239. ss0 += line[xx * 4 + 0];
  240. ss1 += line[xx * 4 + 1];
  241. ss2 += line[xx * 4 + 2];
  242. }
  243. v = MAKE_UINT32(
  244. (ss0 * multiplier) >> 24,
  245. (ss1 * multiplier) >> 24,
  246. (ss2 * multiplier) >> 24,
  247. 0);
  248. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  249. }
  250. } else { // bands == 4
  251. for (x = 0; x < box[2] / xscale; x++) {
  252. int xx = box[0] + x * xscale;
  253. UINT32 v;
  254. UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
  255. for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
  256. UINT8 *line0 = (UINT8 *)imIn->image[yy];
  257. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  258. ss0 += line0[xx * 4 + 0] + line1[xx * 4 + 0];
  259. ss1 += line0[xx * 4 + 1] + line1[xx * 4 + 1];
  260. ss2 += line0[xx * 4 + 2] + line1[xx * 4 + 2];
  261. ss3 += line0[xx * 4 + 3] + line1[xx * 4 + 3];
  262. }
  263. if (yscale & 0x01) {
  264. UINT8 *line = (UINT8 *)imIn->image[yy];
  265. ss0 += line[xx * 4 + 0];
  266. ss1 += line[xx * 4 + 1];
  267. ss2 += line[xx * 4 + 2];
  268. ss3 += line[xx * 4 + 3];
  269. }
  270. v = MAKE_UINT32(
  271. (ss0 * multiplier) >> 24,
  272. (ss1 * multiplier) >> 24,
  273. (ss2 * multiplier) >> 24,
  274. (ss3 * multiplier) >> 24);
  275. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  276. }
  277. }
  278. }
  279. }
  280. }
  281. void
  282. ImagingReduceNx1(Imaging imOut, Imaging imIn, int box[4], int xscale) {
  283. /* Optimized implementation for yscale = 1.
  284. */
  285. int x, y, xx;
  286. int yscale = 1;
  287. UINT32 multiplier = division_UINT32(yscale * xscale, 8);
  288. UINT32 amend = yscale * xscale / 2;
  289. if (imIn->image8) {
  290. for (y = 0; y < box[3] / yscale; y++) {
  291. int yy = box[1] + y * yscale;
  292. UINT8 *line = (UINT8 *)imIn->image8[yy];
  293. for (x = 0; x < box[2] / xscale; x++) {
  294. int xx_from = box[0] + x * xscale;
  295. UINT32 ss = amend;
  296. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  297. ss += line[xx + 0] + line[xx + 1];
  298. }
  299. if (xscale & 0x01) {
  300. ss += line[xx + 0];
  301. }
  302. imOut->image8[y][x] = (ss * multiplier) >> 24;
  303. }
  304. }
  305. } else {
  306. for (y = 0; y < box[3] / yscale; y++) {
  307. int yy = box[1] + y * yscale;
  308. UINT8 *line = (UINT8 *)imIn->image[yy];
  309. if (imIn->bands == 2) {
  310. for (x = 0; x < box[2] / xscale; x++) {
  311. int xx_from = box[0] + x * xscale;
  312. UINT32 v;
  313. UINT32 ss0 = amend, ss3 = amend;
  314. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  315. ss0 += line[xx * 4 + 0] + line[xx * 4 + 4];
  316. ss3 += line[xx * 4 + 3] + line[xx * 4 + 7];
  317. }
  318. if (xscale & 0x01) {
  319. ss0 += line[xx * 4 + 0];
  320. ss3 += line[xx * 4 + 3];
  321. }
  322. v = MAKE_UINT32(
  323. (ss0 * multiplier) >> 24, 0, 0, (ss3 * multiplier) >> 24);
  324. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  325. }
  326. } else if (imIn->bands == 3) {
  327. for (x = 0; x < box[2] / xscale; x++) {
  328. int xx_from = box[0] + x * xscale;
  329. UINT32 v;
  330. UINT32 ss0 = amend, ss1 = amend, ss2 = amend;
  331. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  332. ss0 += line[xx * 4 + 0] + line[xx * 4 + 4];
  333. ss1 += line[xx * 4 + 1] + line[xx * 4 + 5];
  334. ss2 += line[xx * 4 + 2] + line[xx * 4 + 6];
  335. }
  336. if (xscale & 0x01) {
  337. ss0 += line[xx * 4 + 0];
  338. ss1 += line[xx * 4 + 1];
  339. ss2 += line[xx * 4 + 2];
  340. }
  341. v = MAKE_UINT32(
  342. (ss0 * multiplier) >> 24,
  343. (ss1 * multiplier) >> 24,
  344. (ss2 * multiplier) >> 24,
  345. 0);
  346. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  347. }
  348. } else { // bands == 4
  349. for (x = 0; x < box[2] / xscale; x++) {
  350. int xx_from = box[0] + x * xscale;
  351. UINT32 v;
  352. UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
  353. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  354. ss0 += line[xx * 4 + 0] + line[xx * 4 + 4];
  355. ss1 += line[xx * 4 + 1] + line[xx * 4 + 5];
  356. ss2 += line[xx * 4 + 2] + line[xx * 4 + 6];
  357. ss3 += line[xx * 4 + 3] + line[xx * 4 + 7];
  358. }
  359. if (xscale & 0x01) {
  360. ss0 += line[xx * 4 + 0];
  361. ss1 += line[xx * 4 + 1];
  362. ss2 += line[xx * 4 + 2];
  363. ss3 += line[xx * 4 + 3];
  364. }
  365. v = MAKE_UINT32(
  366. (ss0 * multiplier) >> 24,
  367. (ss1 * multiplier) >> 24,
  368. (ss2 * multiplier) >> 24,
  369. (ss3 * multiplier) >> 24);
  370. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  371. }
  372. }
  373. }
  374. }
  375. }
  376. void
  377. ImagingReduce1x2(Imaging imOut, Imaging imIn, int box[4]) {
  378. /* Optimized implementation for xscale = 1 and yscale = 2.
  379. */
  380. int xscale = 1, yscale = 2;
  381. int x, y;
  382. UINT32 ss0, ss1, ss2, ss3;
  383. UINT32 amend = yscale * xscale / 2;
  384. if (imIn->image8) {
  385. for (y = 0; y < box[3] / yscale; y++) {
  386. int yy = box[1] + y * yscale;
  387. UINT8 *line0 = (UINT8 *)imIn->image8[yy + 0];
  388. UINT8 *line1 = (UINT8 *)imIn->image8[yy + 1];
  389. for (x = 0; x < box[2] / xscale; x++) {
  390. int xx = box[0] + x * xscale;
  391. ss0 = line0[xx + 0] + line1[xx + 0];
  392. imOut->image8[y][x] = (ss0 + amend) >> 1;
  393. }
  394. }
  395. } else {
  396. for (y = 0; y < box[3] / yscale; y++) {
  397. int yy = box[1] + y * yscale;
  398. UINT8 *line0 = (UINT8 *)imIn->image[yy + 0];
  399. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  400. if (imIn->bands == 2) {
  401. for (x = 0; x < box[2] / xscale; x++) {
  402. int xx = box[0] + x * xscale;
  403. UINT32 v;
  404. ss0 = line0[xx * 4 + 0] + line1[xx * 4 + 0];
  405. ss3 = line0[xx * 4 + 3] + line1[xx * 4 + 3];
  406. v = MAKE_UINT32((ss0 + amend) >> 1, 0, 0, (ss3 + amend) >> 1);
  407. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  408. }
  409. } else if (imIn->bands == 3) {
  410. for (x = 0; x < box[2] / xscale; x++) {
  411. int xx = box[0] + x * xscale;
  412. UINT32 v;
  413. ss0 = line0[xx * 4 + 0] + line1[xx * 4 + 0];
  414. ss1 = line0[xx * 4 + 1] + line1[xx * 4 + 1];
  415. ss2 = line0[xx * 4 + 2] + line1[xx * 4 + 2];
  416. v = MAKE_UINT32(
  417. (ss0 + amend) >> 1, (ss1 + amend) >> 1, (ss2 + amend) >> 1, 0);
  418. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  419. }
  420. } else { // bands == 4
  421. for (x = 0; x < box[2] / xscale; x++) {
  422. int xx = box[0] + x * xscale;
  423. UINT32 v;
  424. ss0 = line0[xx * 4 + 0] + line1[xx * 4 + 0];
  425. ss1 = line0[xx * 4 + 1] + line1[xx * 4 + 1];
  426. ss2 = line0[xx * 4 + 2] + line1[xx * 4 + 2];
  427. ss3 = line0[xx * 4 + 3] + line1[xx * 4 + 3];
  428. v = MAKE_UINT32(
  429. (ss0 + amend) >> 1,
  430. (ss1 + amend) >> 1,
  431. (ss2 + amend) >> 1,
  432. (ss3 + amend) >> 1);
  433. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  434. }
  435. }
  436. }
  437. }
  438. }
  439. void
  440. ImagingReduce2x1(Imaging imOut, Imaging imIn, int box[4]) {
  441. /* Optimized implementation for xscale = 2 and yscale = 1.
  442. */
  443. int xscale = 2, yscale = 1;
  444. int x, y;
  445. UINT32 ss0, ss1, ss2, ss3;
  446. UINT32 amend = yscale * xscale / 2;
  447. if (imIn->image8) {
  448. for (y = 0; y < box[3] / yscale; y++) {
  449. int yy = box[1] + y * yscale;
  450. UINT8 *line0 = (UINT8 *)imIn->image8[yy + 0];
  451. for (x = 0; x < box[2] / xscale; x++) {
  452. int xx = box[0] + x * xscale;
  453. ss0 = line0[xx + 0] + line0[xx + 1];
  454. imOut->image8[y][x] = (ss0 + amend) >> 1;
  455. }
  456. }
  457. } else {
  458. for (y = 0; y < box[3] / yscale; y++) {
  459. int yy = box[1] + y * yscale;
  460. UINT8 *line0 = (UINT8 *)imIn->image[yy + 0];
  461. if (imIn->bands == 2) {
  462. for (x = 0; x < box[2] / xscale; x++) {
  463. int xx = box[0] + x * xscale;
  464. UINT32 v;
  465. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4];
  466. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7];
  467. v = MAKE_UINT32((ss0 + amend) >> 1, 0, 0, (ss3 + amend) >> 1);
  468. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  469. }
  470. } else if (imIn->bands == 3) {
  471. for (x = 0; x < box[2] / xscale; x++) {
  472. int xx = box[0] + x * xscale;
  473. UINT32 v;
  474. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4];
  475. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5];
  476. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6];
  477. v = MAKE_UINT32(
  478. (ss0 + amend) >> 1, (ss1 + amend) >> 1, (ss2 + amend) >> 1, 0);
  479. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  480. }
  481. } else { // bands == 4
  482. for (x = 0; x < box[2] / xscale; x++) {
  483. int xx = box[0] + x * xscale;
  484. UINT32 v;
  485. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4];
  486. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5];
  487. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6];
  488. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7];
  489. v = MAKE_UINT32(
  490. (ss0 + amend) >> 1,
  491. (ss1 + amend) >> 1,
  492. (ss2 + amend) >> 1,
  493. (ss3 + amend) >> 1);
  494. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  495. }
  496. }
  497. }
  498. }
  499. }
  500. void
  501. ImagingReduce2x2(Imaging imOut, Imaging imIn, int box[4]) {
  502. /* Optimized implementation for xscale = 2 and yscale = 2.
  503. */
  504. int xscale = 2, yscale = 2;
  505. int x, y;
  506. UINT32 ss0, ss1, ss2, ss3;
  507. UINT32 amend = yscale * xscale / 2;
  508. if (imIn->image8) {
  509. for (y = 0; y < box[3] / yscale; y++) {
  510. int yy = box[1] + y * yscale;
  511. UINT8 *line0 = (UINT8 *)imIn->image8[yy + 0];
  512. UINT8 *line1 = (UINT8 *)imIn->image8[yy + 1];
  513. for (x = 0; x < box[2] / xscale; x++) {
  514. int xx = box[0] + x * xscale;
  515. ss0 = line0[xx + 0] + line0[xx + 1] + line1[xx + 0] + line1[xx + 1];
  516. imOut->image8[y][x] = (ss0 + amend) >> 2;
  517. }
  518. }
  519. } else {
  520. for (y = 0; y < box[3] / yscale; y++) {
  521. int yy = box[1] + y * yscale;
  522. UINT8 *line0 = (UINT8 *)imIn->image[yy + 0];
  523. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  524. if (imIn->bands == 2) {
  525. for (x = 0; x < box[2] / xscale; x++) {
  526. int xx = box[0] + x * xscale;
  527. UINT32 v;
  528. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line1[xx * 4 + 0] +
  529. line1[xx * 4 + 4];
  530. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7] + line1[xx * 4 + 3] +
  531. line1[xx * 4 + 7];
  532. v = MAKE_UINT32((ss0 + amend) >> 2, 0, 0, (ss3 + amend) >> 2);
  533. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  534. }
  535. } else if (imIn->bands == 3) {
  536. for (x = 0; x < box[2] / xscale; x++) {
  537. int xx = box[0] + x * xscale;
  538. UINT32 v;
  539. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line1[xx * 4 + 0] +
  540. line1[xx * 4 + 4];
  541. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5] + line1[xx * 4 + 1] +
  542. line1[xx * 4 + 5];
  543. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6] + line1[xx * 4 + 2] +
  544. line1[xx * 4 + 6];
  545. v = MAKE_UINT32(
  546. (ss0 + amend) >> 2, (ss1 + amend) >> 2, (ss2 + amend) >> 2, 0);
  547. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  548. }
  549. } else { // bands == 4
  550. for (x = 0; x < box[2] / xscale; x++) {
  551. int xx = box[0] + x * xscale;
  552. UINT32 v;
  553. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line1[xx * 4 + 0] +
  554. line1[xx * 4 + 4];
  555. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5] + line1[xx * 4 + 1] +
  556. line1[xx * 4 + 5];
  557. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6] + line1[xx * 4 + 2] +
  558. line1[xx * 4 + 6];
  559. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7] + line1[xx * 4 + 3] +
  560. line1[xx * 4 + 7];
  561. v = MAKE_UINT32(
  562. (ss0 + amend) >> 2,
  563. (ss1 + amend) >> 2,
  564. (ss2 + amend) >> 2,
  565. (ss3 + amend) >> 2);
  566. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  567. }
  568. }
  569. }
  570. }
  571. }
  572. void
  573. ImagingReduce1x3(Imaging imOut, Imaging imIn, int box[4]) {
  574. /* Optimized implementation for xscale = 1 and yscale = 3.
  575. */
  576. int xscale = 1, yscale = 3;
  577. int x, y;
  578. UINT32 ss0, ss1, ss2, ss3;
  579. UINT32 multiplier = division_UINT32(yscale * xscale, 8);
  580. UINT32 amend = yscale * xscale / 2;
  581. if (imIn->image8) {
  582. for (y = 0; y < box[3] / yscale; y++) {
  583. int yy = box[1] + y * yscale;
  584. UINT8 *line0 = (UINT8 *)imIn->image8[yy + 0];
  585. UINT8 *line1 = (UINT8 *)imIn->image8[yy + 1];
  586. UINT8 *line2 = (UINT8 *)imIn->image8[yy + 2];
  587. for (x = 0; x < box[2] / xscale; x++) {
  588. int xx = box[0] + x * xscale;
  589. ss0 = line0[xx + 0] + line1[xx + 0] + line2[xx + 0];
  590. imOut->image8[y][x] = ((ss0 + amend) * multiplier) >> 24;
  591. }
  592. }
  593. } else {
  594. for (y = 0; y < box[3] / yscale; y++) {
  595. int yy = box[1] + y * yscale;
  596. UINT8 *line0 = (UINT8 *)imIn->image[yy + 0];
  597. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  598. UINT8 *line2 = (UINT8 *)imIn->image[yy + 2];
  599. if (imIn->bands == 2) {
  600. for (x = 0; x < box[2] / xscale; x++) {
  601. int xx = box[0] + x * xscale;
  602. UINT32 v;
  603. ss0 = line0[xx * 4 + 0] + line1[xx * 4 + 0] + line2[xx * 4 + 0];
  604. ss3 = line0[xx * 4 + 3] + line1[xx * 4 + 3] + line2[xx * 4 + 3];
  605. v = MAKE_UINT32(
  606. ((ss0 + amend) * multiplier) >> 24,
  607. 0,
  608. 0,
  609. ((ss3 + amend) * multiplier) >> 24);
  610. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  611. }
  612. } else if (imIn->bands == 3) {
  613. for (x = 0; x < box[2] / xscale; x++) {
  614. int xx = box[0] + x * xscale;
  615. UINT32 v;
  616. ss0 = line0[xx * 4 + 0] + line1[xx * 4 + 0] + line2[xx * 4 + 0];
  617. ss1 = line0[xx * 4 + 1] + line1[xx * 4 + 1] + line2[xx * 4 + 1];
  618. ss2 = line0[xx * 4 + 2] + line1[xx * 4 + 2] + line2[xx * 4 + 2];
  619. v = MAKE_UINT32(
  620. ((ss0 + amend) * multiplier) >> 24,
  621. ((ss1 + amend) * multiplier) >> 24,
  622. ((ss2 + amend) * multiplier) >> 24,
  623. 0);
  624. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  625. }
  626. } else { // bands == 4
  627. for (x = 0; x < box[2] / xscale; x++) {
  628. int xx = box[0] + x * xscale;
  629. UINT32 v;
  630. ss0 = line0[xx * 4 + 0] + line1[xx * 4 + 0] + line2[xx * 4 + 0];
  631. ss1 = line0[xx * 4 + 1] + line1[xx * 4 + 1] + line2[xx * 4 + 1];
  632. ss2 = line0[xx * 4 + 2] + line1[xx * 4 + 2] + line2[xx * 4 + 2];
  633. ss3 = line0[xx * 4 + 3] + line1[xx * 4 + 3] + line2[xx * 4 + 3];
  634. v = MAKE_UINT32(
  635. ((ss0 + amend) * multiplier) >> 24,
  636. ((ss1 + amend) * multiplier) >> 24,
  637. ((ss2 + amend) * multiplier) >> 24,
  638. ((ss3 + amend) * multiplier) >> 24);
  639. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  640. }
  641. }
  642. }
  643. }
  644. }
  645. void
  646. ImagingReduce3x1(Imaging imOut, Imaging imIn, int box[4]) {
  647. /* Optimized implementation for xscale = 3 and yscale = 1.
  648. */
  649. int xscale = 3, yscale = 1;
  650. int x, y;
  651. UINT32 ss0, ss1, ss2, ss3;
  652. UINT32 multiplier = division_UINT32(yscale * xscale, 8);
  653. UINT32 amend = yscale * xscale / 2;
  654. if (imIn->image8) {
  655. for (y = 0; y < box[3] / yscale; y++) {
  656. int yy = box[1] + y * yscale;
  657. UINT8 *line0 = (UINT8 *)imIn->image8[yy + 0];
  658. for (x = 0; x < box[2] / xscale; x++) {
  659. int xx = box[0] + x * xscale;
  660. ss0 = line0[xx + 0] + line0[xx + 1] + line0[xx + 2];
  661. imOut->image8[y][x] = ((ss0 + amend) * multiplier) >> 24;
  662. }
  663. }
  664. } else {
  665. for (y = 0; y < box[3] / yscale; y++) {
  666. int yy = box[1] + y * yscale;
  667. UINT8 *line0 = (UINT8 *)imIn->image[yy + 0];
  668. if (imIn->bands == 2) {
  669. for (x = 0; x < box[2] / xscale; x++) {
  670. int xx = box[0] + x * xscale;
  671. UINT32 v;
  672. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8];
  673. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7] + line0[xx * 4 + 11];
  674. v = MAKE_UINT32(
  675. ((ss0 + amend) * multiplier) >> 24,
  676. 0,
  677. 0,
  678. ((ss3 + amend) * multiplier) >> 24);
  679. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  680. }
  681. } else if (imIn->bands == 3) {
  682. for (x = 0; x < box[2] / xscale; x++) {
  683. int xx = box[0] + x * xscale;
  684. UINT32 v;
  685. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8];
  686. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5] + line0[xx * 4 + 9];
  687. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6] + line0[xx * 4 + 10];
  688. v = MAKE_UINT32(
  689. ((ss0 + amend) * multiplier) >> 24,
  690. ((ss1 + amend) * multiplier) >> 24,
  691. ((ss2 + amend) * multiplier) >> 24,
  692. 0);
  693. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  694. }
  695. } else { // bands == 4
  696. for (x = 0; x < box[2] / xscale; x++) {
  697. int xx = box[0] + x * xscale;
  698. UINT32 v;
  699. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8];
  700. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5] + line0[xx * 4 + 9];
  701. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6] + line0[xx * 4 + 10];
  702. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7] + line0[xx * 4 + 11];
  703. v = MAKE_UINT32(
  704. ((ss0 + amend) * multiplier) >> 24,
  705. ((ss1 + amend) * multiplier) >> 24,
  706. ((ss2 + amend) * multiplier) >> 24,
  707. ((ss3 + amend) * multiplier) >> 24);
  708. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  709. }
  710. }
  711. }
  712. }
  713. }
  714. void
  715. ImagingReduce3x3(Imaging imOut, Imaging imIn, int box[4]) {
  716. /* Optimized implementation for xscale = 3 and yscale = 3.
  717. */
  718. int xscale = 3, yscale = 3;
  719. int x, y;
  720. UINT32 ss0, ss1, ss2, ss3;
  721. UINT32 multiplier = division_UINT32(yscale * xscale, 8);
  722. UINT32 amend = yscale * xscale / 2;
  723. if (imIn->image8) {
  724. for (y = 0; y < box[3] / yscale; y++) {
  725. int yy = box[1] + y * yscale;
  726. UINT8 *line0 = (UINT8 *)imIn->image8[yy + 0];
  727. UINT8 *line1 = (UINT8 *)imIn->image8[yy + 1];
  728. UINT8 *line2 = (UINT8 *)imIn->image8[yy + 2];
  729. for (x = 0; x < box[2] / xscale; x++) {
  730. int xx = box[0] + x * xscale;
  731. ss0 = line0[xx + 0] + line0[xx + 1] + line0[xx + 2] + line1[xx + 0] +
  732. line1[xx + 1] + line1[xx + 2] + line2[xx + 0] + line2[xx + 1] +
  733. line2[xx + 2];
  734. imOut->image8[y][x] = ((ss0 + amend) * multiplier) >> 24;
  735. }
  736. }
  737. } else {
  738. for (y = 0; y < box[3] / yscale; y++) {
  739. int yy = box[1] + y * yscale;
  740. UINT8 *line0 = (UINT8 *)imIn->image[yy + 0];
  741. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  742. UINT8 *line2 = (UINT8 *)imIn->image[yy + 2];
  743. if (imIn->bands == 2) {
  744. for (x = 0; x < box[2] / xscale; x++) {
  745. int xx = box[0] + x * xscale;
  746. UINT32 v;
  747. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8] +
  748. line1[xx * 4 + 0] + line1[xx * 4 + 4] + line1[xx * 4 + 8] +
  749. line2[xx * 4 + 0] + line2[xx * 4 + 4] + line2[xx * 4 + 8];
  750. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7] + line0[xx * 4 + 11] +
  751. line1[xx * 4 + 3] + line1[xx * 4 + 7] + line1[xx * 4 + 11] +
  752. line2[xx * 4 + 3] + line2[xx * 4 + 7] + line2[xx * 4 + 11];
  753. v = MAKE_UINT32(
  754. ((ss0 + amend) * multiplier) >> 24,
  755. 0,
  756. 0,
  757. ((ss3 + amend) * multiplier) >> 24);
  758. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  759. }
  760. } else if (imIn->bands == 3) {
  761. for (x = 0; x < box[2] / xscale; x++) {
  762. int xx = box[0] + x * xscale;
  763. UINT32 v;
  764. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8] +
  765. line1[xx * 4 + 0] + line1[xx * 4 + 4] + line1[xx * 4 + 8] +
  766. line2[xx * 4 + 0] + line2[xx * 4 + 4] + line2[xx * 4 + 8];
  767. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5] + line0[xx * 4 + 9] +
  768. line1[xx * 4 + 1] + line1[xx * 4 + 5] + line1[xx * 4 + 9] +
  769. line2[xx * 4 + 1] + line2[xx * 4 + 5] + line2[xx * 4 + 9];
  770. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6] + line0[xx * 4 + 10] +
  771. line1[xx * 4 + 2] + line1[xx * 4 + 6] + line1[xx * 4 + 10] +
  772. line2[xx * 4 + 2] + line2[xx * 4 + 6] + line2[xx * 4 + 10];
  773. v = MAKE_UINT32(
  774. ((ss0 + amend) * multiplier) >> 24,
  775. ((ss1 + amend) * multiplier) >> 24,
  776. ((ss2 + amend) * multiplier) >> 24,
  777. 0);
  778. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  779. }
  780. } else { // bands == 4
  781. for (x = 0; x < box[2] / xscale; x++) {
  782. int xx = box[0] + x * xscale;
  783. UINT32 v;
  784. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8] +
  785. line1[xx * 4 + 0] + line1[xx * 4 + 4] + line1[xx * 4 + 8] +
  786. line2[xx * 4 + 0] + line2[xx * 4 + 4] + line2[xx * 4 + 8];
  787. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5] + line0[xx * 4 + 9] +
  788. line1[xx * 4 + 1] + line1[xx * 4 + 5] + line1[xx * 4 + 9] +
  789. line2[xx * 4 + 1] + line2[xx * 4 + 5] + line2[xx * 4 + 9];
  790. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6] + line0[xx * 4 + 10] +
  791. line1[xx * 4 + 2] + line1[xx * 4 + 6] + line1[xx * 4 + 10] +
  792. line2[xx * 4 + 2] + line2[xx * 4 + 6] + line2[xx * 4 + 10];
  793. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7] + line0[xx * 4 + 11] +
  794. line1[xx * 4 + 3] + line1[xx * 4 + 7] + line1[xx * 4 + 11] +
  795. line2[xx * 4 + 3] + line2[xx * 4 + 7] + line2[xx * 4 + 11];
  796. v = MAKE_UINT32(
  797. ((ss0 + amend) * multiplier) >> 24,
  798. ((ss1 + amend) * multiplier) >> 24,
  799. ((ss2 + amend) * multiplier) >> 24,
  800. ((ss3 + amend) * multiplier) >> 24);
  801. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  802. }
  803. }
  804. }
  805. }
  806. }
  807. void
  808. ImagingReduce4x4(Imaging imOut, Imaging imIn, int box[4]) {
  809. /* Optimized implementation for xscale = 4 and yscale = 4.
  810. */
  811. int xscale = 4, yscale = 4;
  812. int x, y;
  813. UINT32 ss0, ss1, ss2, ss3;
  814. UINT32 amend = yscale * xscale / 2;
  815. if (imIn->image8) {
  816. for (y = 0; y < box[3] / yscale; y++) {
  817. int yy = box[1] + y * yscale;
  818. UINT8 *line0 = (UINT8 *)imIn->image8[yy + 0];
  819. UINT8 *line1 = (UINT8 *)imIn->image8[yy + 1];
  820. UINT8 *line2 = (UINT8 *)imIn->image8[yy + 2];
  821. UINT8 *line3 = (UINT8 *)imIn->image8[yy + 3];
  822. for (x = 0; x < box[2] / xscale; x++) {
  823. int xx = box[0] + x * xscale;
  824. ss0 = line0[xx + 0] + line0[xx + 1] + line0[xx + 2] + line0[xx + 3] +
  825. line1[xx + 0] + line1[xx + 1] + line1[xx + 2] + line1[xx + 3] +
  826. line2[xx + 0] + line2[xx + 1] + line2[xx + 2] + line2[xx + 3] +
  827. line3[xx + 0] + line3[xx + 1] + line3[xx + 2] + line3[xx + 3];
  828. imOut->image8[y][x] = (ss0 + amend) >> 4;
  829. }
  830. }
  831. } else {
  832. for (y = 0; y < box[3] / yscale; y++) {
  833. int yy = box[1] + y * yscale;
  834. UINT8 *line0 = (UINT8 *)imIn->image[yy + 0];
  835. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  836. UINT8 *line2 = (UINT8 *)imIn->image[yy + 2];
  837. UINT8 *line3 = (UINT8 *)imIn->image[yy + 3];
  838. if (imIn->bands == 2) {
  839. for (x = 0; x < box[2] / xscale; x++) {
  840. int xx = box[0] + x * xscale;
  841. UINT32 v;
  842. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8] +
  843. line0[xx * 4 + 12] + line1[xx * 4 + 0] + line1[xx * 4 + 4] +
  844. line1[xx * 4 + 8] + line1[xx * 4 + 12] + line2[xx * 4 + 0] +
  845. line2[xx * 4 + 4] + line2[xx * 4 + 8] + line2[xx * 4 + 12] +
  846. line3[xx * 4 + 0] + line3[xx * 4 + 4] + line3[xx * 4 + 8] +
  847. line3[xx * 4 + 12];
  848. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7] + line0[xx * 4 + 11] +
  849. line0[xx * 4 + 15] + line1[xx * 4 + 3] + line1[xx * 4 + 7] +
  850. line1[xx * 4 + 11] + line1[xx * 4 + 15] + line2[xx * 4 + 3] +
  851. line2[xx * 4 + 7] + line2[xx * 4 + 11] + line2[xx * 4 + 15] +
  852. line3[xx * 4 + 3] + line3[xx * 4 + 7] + line3[xx * 4 + 11] +
  853. line3[xx * 4 + 15];
  854. v = MAKE_UINT32((ss0 + amend) >> 4, 0, 0, (ss3 + amend) >> 4);
  855. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  856. }
  857. } else if (imIn->bands == 3) {
  858. for (x = 0; x < box[2] / xscale; x++) {
  859. int xx = box[0] + x * xscale;
  860. UINT32 v;
  861. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8] +
  862. line0[xx * 4 + 12] + line1[xx * 4 + 0] + line1[xx * 4 + 4] +
  863. line1[xx * 4 + 8] + line1[xx * 4 + 12] + line2[xx * 4 + 0] +
  864. line2[xx * 4 + 4] + line2[xx * 4 + 8] + line2[xx * 4 + 12] +
  865. line3[xx * 4 + 0] + line3[xx * 4 + 4] + line3[xx * 4 + 8] +
  866. line3[xx * 4 + 12];
  867. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5] + line0[xx * 4 + 9] +
  868. line0[xx * 4 + 13] + line1[xx * 4 + 1] + line1[xx * 4 + 5] +
  869. line1[xx * 4 + 9] + line1[xx * 4 + 13] + line2[xx * 4 + 1] +
  870. line2[xx * 4 + 5] + line2[xx * 4 + 9] + line2[xx * 4 + 13] +
  871. line3[xx * 4 + 1] + line3[xx * 4 + 5] + line3[xx * 4 + 9] +
  872. line3[xx * 4 + 13];
  873. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6] + line0[xx * 4 + 10] +
  874. line0[xx * 4 + 14] + line1[xx * 4 + 2] + line1[xx * 4 + 6] +
  875. line1[xx * 4 + 10] + line1[xx * 4 + 14] + line2[xx * 4 + 2] +
  876. line2[xx * 4 + 6] + line2[xx * 4 + 10] + line2[xx * 4 + 14] +
  877. line3[xx * 4 + 2] + line3[xx * 4 + 6] + line3[xx * 4 + 10] +
  878. line3[xx * 4 + 14];
  879. v = MAKE_UINT32(
  880. (ss0 + amend) >> 4, (ss1 + amend) >> 4, (ss2 + amend) >> 4, 0);
  881. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  882. }
  883. } else { // bands == 4
  884. for (x = 0; x < box[2] / xscale; x++) {
  885. int xx = box[0] + x * xscale;
  886. UINT32 v;
  887. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8] +
  888. line0[xx * 4 + 12] + line1[xx * 4 + 0] + line1[xx * 4 + 4] +
  889. line1[xx * 4 + 8] + line1[xx * 4 + 12] + line2[xx * 4 + 0] +
  890. line2[xx * 4 + 4] + line2[xx * 4 + 8] + line2[xx * 4 + 12] +
  891. line3[xx * 4 + 0] + line3[xx * 4 + 4] + line3[xx * 4 + 8] +
  892. line3[xx * 4 + 12];
  893. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5] + line0[xx * 4 + 9] +
  894. line0[xx * 4 + 13] + line1[xx * 4 + 1] + line1[xx * 4 + 5] +
  895. line1[xx * 4 + 9] + line1[xx * 4 + 13] + line2[xx * 4 + 1] +
  896. line2[xx * 4 + 5] + line2[xx * 4 + 9] + line2[xx * 4 + 13] +
  897. line3[xx * 4 + 1] + line3[xx * 4 + 5] + line3[xx * 4 + 9] +
  898. line3[xx * 4 + 13];
  899. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6] + line0[xx * 4 + 10] +
  900. line0[xx * 4 + 14] + line1[xx * 4 + 2] + line1[xx * 4 + 6] +
  901. line1[xx * 4 + 10] + line1[xx * 4 + 14] + line2[xx * 4 + 2] +
  902. line2[xx * 4 + 6] + line2[xx * 4 + 10] + line2[xx * 4 + 14] +
  903. line3[xx * 4 + 2] + line3[xx * 4 + 6] + line3[xx * 4 + 10] +
  904. line3[xx * 4 + 14];
  905. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7] + line0[xx * 4 + 11] +
  906. line0[xx * 4 + 15] + line1[xx * 4 + 3] + line1[xx * 4 + 7] +
  907. line1[xx * 4 + 11] + line1[xx * 4 + 15] + line2[xx * 4 + 3] +
  908. line2[xx * 4 + 7] + line2[xx * 4 + 11] + line2[xx * 4 + 15] +
  909. line3[xx * 4 + 3] + line3[xx * 4 + 7] + line3[xx * 4 + 11] +
  910. line3[xx * 4 + 15];
  911. v = MAKE_UINT32(
  912. (ss0 + amend) >> 4,
  913. (ss1 + amend) >> 4,
  914. (ss2 + amend) >> 4,
  915. (ss3 + amend) >> 4);
  916. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  917. }
  918. }
  919. }
  920. }
  921. }
  922. void
  923. ImagingReduce5x5(Imaging imOut, Imaging imIn, int box[4]) {
  924. /* Fast special case for xscale = 5 and yscale = 5.
  925. */
  926. int xscale = 5, yscale = 5;
  927. int x, y;
  928. UINT32 ss0, ss1, ss2, ss3;
  929. UINT32 multiplier = division_UINT32(yscale * xscale, 8);
  930. UINT32 amend = yscale * xscale / 2;
  931. if (imIn->image8) {
  932. for (y = 0; y < box[3] / yscale; y++) {
  933. int yy = box[1] + y * yscale;
  934. UINT8 *line0 = (UINT8 *)imIn->image8[yy + 0];
  935. UINT8 *line1 = (UINT8 *)imIn->image8[yy + 1];
  936. UINT8 *line2 = (UINT8 *)imIn->image8[yy + 2];
  937. UINT8 *line3 = (UINT8 *)imIn->image8[yy + 3];
  938. UINT8 *line4 = (UINT8 *)imIn->image8[yy + 4];
  939. for (x = 0; x < box[2] / xscale; x++) {
  940. int xx = box[0] + x * xscale;
  941. ss0 = line0[xx + 0] + line0[xx + 1] + line0[xx + 2] + line0[xx + 3] +
  942. line0[xx + 4] + line1[xx + 0] + line1[xx + 1] + line1[xx + 2] +
  943. line1[xx + 3] + line1[xx + 4] + line2[xx + 0] + line2[xx + 1] +
  944. line2[xx + 2] + line2[xx + 3] + line2[xx + 4] + line3[xx + 0] +
  945. line3[xx + 1] + line3[xx + 2] + line3[xx + 3] + line3[xx + 4] +
  946. line4[xx + 0] + line4[xx + 1] + line4[xx + 2] + line4[xx + 3] +
  947. line4[xx + 4];
  948. imOut->image8[y][x] = ((ss0 + amend) * multiplier) >> 24;
  949. }
  950. }
  951. } else {
  952. for (y = 0; y < box[3] / yscale; y++) {
  953. int yy = box[1] + y * yscale;
  954. UINT8 *line0 = (UINT8 *)imIn->image[yy + 0];
  955. UINT8 *line1 = (UINT8 *)imIn->image[yy + 1];
  956. UINT8 *line2 = (UINT8 *)imIn->image[yy + 2];
  957. UINT8 *line3 = (UINT8 *)imIn->image[yy + 3];
  958. UINT8 *line4 = (UINT8 *)imIn->image[yy + 4];
  959. if (imIn->bands == 2) {
  960. for (x = 0; x < box[2] / xscale; x++) {
  961. int xx = box[0] + x * xscale;
  962. UINT32 v;
  963. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8] +
  964. line0[xx * 4 + 12] + line0[xx * 4 + 16] + line1[xx * 4 + 0] +
  965. line1[xx * 4 + 4] + line1[xx * 4 + 8] + line1[xx * 4 + 12] +
  966. line1[xx * 4 + 16] + line2[xx * 4 + 0] + line2[xx * 4 + 4] +
  967. line2[xx * 4 + 8] + line2[xx * 4 + 12] + line2[xx * 4 + 16] +
  968. line3[xx * 4 + 0] + line3[xx * 4 + 4] + line3[xx * 4 + 8] +
  969. line3[xx * 4 + 12] + line3[xx * 4 + 16] + line4[xx * 4 + 0] +
  970. line4[xx * 4 + 4] + line4[xx * 4 + 8] + line4[xx * 4 + 12] +
  971. line4[xx * 4 + 16];
  972. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7] + line0[xx * 4 + 11] +
  973. line0[xx * 4 + 15] + line0[xx * 4 + 19] + line1[xx * 4 + 3] +
  974. line1[xx * 4 + 7] + line1[xx * 4 + 11] + line1[xx * 4 + 15] +
  975. line1[xx * 4 + 19] + line2[xx * 4 + 3] + line2[xx * 4 + 7] +
  976. line2[xx * 4 + 11] + line2[xx * 4 + 15] + line2[xx * 4 + 19] +
  977. line3[xx * 4 + 3] + line3[xx * 4 + 7] + line3[xx * 4 + 11] +
  978. line3[xx * 4 + 15] + line3[xx * 4 + 19] + line4[xx * 4 + 3] +
  979. line4[xx * 4 + 7] + line4[xx * 4 + 11] + line4[xx * 4 + 15] +
  980. line4[xx * 4 + 19];
  981. v = MAKE_UINT32(
  982. ((ss0 + amend) * multiplier) >> 24,
  983. 0,
  984. 0,
  985. ((ss3 + amend) * multiplier) >> 24);
  986. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  987. }
  988. } else if (imIn->bands == 3) {
  989. for (x = 0; x < box[2] / xscale; x++) {
  990. int xx = box[0] + x * xscale;
  991. UINT32 v;
  992. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8] +
  993. line0[xx * 4 + 12] + line0[xx * 4 + 16] + line1[xx * 4 + 0] +
  994. line1[xx * 4 + 4] + line1[xx * 4 + 8] + line1[xx * 4 + 12] +
  995. line1[xx * 4 + 16] + line2[xx * 4 + 0] + line2[xx * 4 + 4] +
  996. line2[xx * 4 + 8] + line2[xx * 4 + 12] + line2[xx * 4 + 16] +
  997. line3[xx * 4 + 0] + line3[xx * 4 + 4] + line3[xx * 4 + 8] +
  998. line3[xx * 4 + 12] + line3[xx * 4 + 16] + line4[xx * 4 + 0] +
  999. line4[xx * 4 + 4] + line4[xx * 4 + 8] + line4[xx * 4 + 12] +
  1000. line4[xx * 4 + 16];
  1001. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5] + line0[xx * 4 + 9] +
  1002. line0[xx * 4 + 13] + line0[xx * 4 + 17] + line1[xx * 4 + 1] +
  1003. line1[xx * 4 + 5] + line1[xx * 4 + 9] + line1[xx * 4 + 13] +
  1004. line1[xx * 4 + 17] + line2[xx * 4 + 1] + line2[xx * 4 + 5] +
  1005. line2[xx * 4 + 9] + line2[xx * 4 + 13] + line2[xx * 4 + 17] +
  1006. line3[xx * 4 + 1] + line3[xx * 4 + 5] + line3[xx * 4 + 9] +
  1007. line3[xx * 4 + 13] + line3[xx * 4 + 17] + line4[xx * 4 + 1] +
  1008. line4[xx * 4 + 5] + line4[xx * 4 + 9] + line4[xx * 4 + 13] +
  1009. line4[xx * 4 + 17];
  1010. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6] + line0[xx * 4 + 10] +
  1011. line0[xx * 4 + 14] + line0[xx * 4 + 18] + line1[xx * 4 + 2] +
  1012. line1[xx * 4 + 6] + line1[xx * 4 + 10] + line1[xx * 4 + 14] +
  1013. line1[xx * 4 + 18] + line2[xx * 4 + 2] + line2[xx * 4 + 6] +
  1014. line2[xx * 4 + 10] + line2[xx * 4 + 14] + line2[xx * 4 + 18] +
  1015. line3[xx * 4 + 2] + line3[xx * 4 + 6] + line3[xx * 4 + 10] +
  1016. line3[xx * 4 + 14] + line3[xx * 4 + 18] + line4[xx * 4 + 2] +
  1017. line4[xx * 4 + 6] + line4[xx * 4 + 10] + line4[xx * 4 + 14] +
  1018. line4[xx * 4 + 18];
  1019. v = MAKE_UINT32(
  1020. ((ss0 + amend) * multiplier) >> 24,
  1021. ((ss1 + amend) * multiplier) >> 24,
  1022. ((ss2 + amend) * multiplier) >> 24,
  1023. 0);
  1024. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  1025. }
  1026. } else { // bands == 4
  1027. for (x = 0; x < box[2] / xscale; x++) {
  1028. int xx = box[0] + x * xscale;
  1029. UINT32 v;
  1030. ss0 = line0[xx * 4 + 0] + line0[xx * 4 + 4] + line0[xx * 4 + 8] +
  1031. line0[xx * 4 + 12] + line0[xx * 4 + 16] + line1[xx * 4 + 0] +
  1032. line1[xx * 4 + 4] + line1[xx * 4 + 8] + line1[xx * 4 + 12] +
  1033. line1[xx * 4 + 16] + line2[xx * 4 + 0] + line2[xx * 4 + 4] +
  1034. line2[xx * 4 + 8] + line2[xx * 4 + 12] + line2[xx * 4 + 16] +
  1035. line3[xx * 4 + 0] + line3[xx * 4 + 4] + line3[xx * 4 + 8] +
  1036. line3[xx * 4 + 12] + line3[xx * 4 + 16] + line4[xx * 4 + 0] +
  1037. line4[xx * 4 + 4] + line4[xx * 4 + 8] + line4[xx * 4 + 12] +
  1038. line4[xx * 4 + 16];
  1039. ss1 = line0[xx * 4 + 1] + line0[xx * 4 + 5] + line0[xx * 4 + 9] +
  1040. line0[xx * 4 + 13] + line0[xx * 4 + 17] + line1[xx * 4 + 1] +
  1041. line1[xx * 4 + 5] + line1[xx * 4 + 9] + line1[xx * 4 + 13] +
  1042. line1[xx * 4 + 17] + line2[xx * 4 + 1] + line2[xx * 4 + 5] +
  1043. line2[xx * 4 + 9] + line2[xx * 4 + 13] + line2[xx * 4 + 17] +
  1044. line3[xx * 4 + 1] + line3[xx * 4 + 5] + line3[xx * 4 + 9] +
  1045. line3[xx * 4 + 13] + line3[xx * 4 + 17] + line4[xx * 4 + 1] +
  1046. line4[xx * 4 + 5] + line4[xx * 4 + 9] + line4[xx * 4 + 13] +
  1047. line4[xx * 4 + 17];
  1048. ss2 = line0[xx * 4 + 2] + line0[xx * 4 + 6] + line0[xx * 4 + 10] +
  1049. line0[xx * 4 + 14] + line0[xx * 4 + 18] + line1[xx * 4 + 2] +
  1050. line1[xx * 4 + 6] + line1[xx * 4 + 10] + line1[xx * 4 + 14] +
  1051. line1[xx * 4 + 18] + line2[xx * 4 + 2] + line2[xx * 4 + 6] +
  1052. line2[xx * 4 + 10] + line2[xx * 4 + 14] + line2[xx * 4 + 18] +
  1053. line3[xx * 4 + 2] + line3[xx * 4 + 6] + line3[xx * 4 + 10] +
  1054. line3[xx * 4 + 14] + line3[xx * 4 + 18] + line4[xx * 4 + 2] +
  1055. line4[xx * 4 + 6] + line4[xx * 4 + 10] + line4[xx * 4 + 14] +
  1056. line4[xx * 4 + 18];
  1057. ss3 = line0[xx * 4 + 3] + line0[xx * 4 + 7] + line0[xx * 4 + 11] +
  1058. line0[xx * 4 + 15] + line0[xx * 4 + 19] + line1[xx * 4 + 3] +
  1059. line1[xx * 4 + 7] + line1[xx * 4 + 11] + line1[xx * 4 + 15] +
  1060. line1[xx * 4 + 19] + line2[xx * 4 + 3] + line2[xx * 4 + 7] +
  1061. line2[xx * 4 + 11] + line2[xx * 4 + 15] + line2[xx * 4 + 19] +
  1062. line3[xx * 4 + 3] + line3[xx * 4 + 7] + line3[xx * 4 + 11] +
  1063. line3[xx * 4 + 15] + line3[xx * 4 + 19] + line4[xx * 4 + 3] +
  1064. line4[xx * 4 + 7] + line4[xx * 4 + 11] + line4[xx * 4 + 15] +
  1065. line4[xx * 4 + 19];
  1066. v = MAKE_UINT32(
  1067. ((ss0 + amend) * multiplier) >> 24,
  1068. ((ss1 + amend) * multiplier) >> 24,
  1069. ((ss2 + amend) * multiplier) >> 24,
  1070. ((ss3 + amend) * multiplier) >> 24);
  1071. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  1072. }
  1073. }
  1074. }
  1075. }
  1076. }
  1077. void
  1078. ImagingReduceCorners(Imaging imOut, Imaging imIn, int box[4], int xscale, int yscale) {
  1079. /* Fill the last row and the last column for any xscale and yscale.
  1080. */
  1081. int x, y, xx, yy;
  1082. if (imIn->image8) {
  1083. if (box[2] % xscale) {
  1084. int scale = (box[2] % xscale) * yscale;
  1085. UINT32 multiplier = division_UINT32(scale, 8);
  1086. UINT32 amend = scale / 2;
  1087. for (y = 0; y < box[3] / yscale; y++) {
  1088. int yy_from = box[1] + y * yscale;
  1089. UINT32 ss = amend;
  1090. x = box[2] / xscale;
  1091. for (yy = yy_from; yy < yy_from + yscale; yy++) {
  1092. UINT8 *line = (UINT8 *)imIn->image8[yy];
  1093. for (xx = box[0] + x * xscale; xx < box[0] + box[2]; xx++) {
  1094. ss += line[xx + 0];
  1095. }
  1096. }
  1097. imOut->image8[y][x] = (ss * multiplier) >> 24;
  1098. }
  1099. }
  1100. if (box[3] % yscale) {
  1101. int scale = xscale * (box[3] % yscale);
  1102. UINT32 multiplier = division_UINT32(scale, 8);
  1103. UINT32 amend = scale / 2;
  1104. y = box[3] / yscale;
  1105. for (x = 0; x < box[2] / xscale; x++) {
  1106. int xx_from = box[0] + x * xscale;
  1107. UINT32 ss = amend;
  1108. for (yy = box[1] + y * yscale; yy < box[1] + box[3]; yy++) {
  1109. UINT8 *line = (UINT8 *)imIn->image8[yy];
  1110. for (xx = xx_from; xx < xx_from + xscale; xx++) {
  1111. ss += line[xx + 0];
  1112. }
  1113. }
  1114. imOut->image8[y][x] = (ss * multiplier) >> 24;
  1115. }
  1116. }
  1117. if (box[2] % xscale && box[3] % yscale) {
  1118. int scale = (box[2] % xscale) * (box[3] % yscale);
  1119. UINT32 multiplier = division_UINT32(scale, 8);
  1120. UINT32 amend = scale / 2;
  1121. UINT32 ss = amend;
  1122. x = box[2] / xscale;
  1123. y = box[3] / yscale;
  1124. for (yy = box[1] + y * yscale; yy < box[1] + box[3]; yy++) {
  1125. UINT8 *line = (UINT8 *)imIn->image8[yy];
  1126. for (xx = box[0] + x * xscale; xx < box[0] + box[2]; xx++) {
  1127. ss += line[xx + 0];
  1128. }
  1129. }
  1130. imOut->image8[y][x] = (ss * multiplier) >> 24;
  1131. }
  1132. } else {
  1133. if (box[2] % xscale) {
  1134. int scale = (box[2] % xscale) * yscale;
  1135. UINT32 multiplier = division_UINT32(scale, 8);
  1136. UINT32 amend = scale / 2;
  1137. for (y = 0; y < box[3] / yscale; y++) {
  1138. int yy_from = box[1] + y * yscale;
  1139. UINT32 v;
  1140. UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
  1141. x = box[2] / xscale;
  1142. for (yy = yy_from; yy < yy_from + yscale; yy++) {
  1143. UINT8 *line = (UINT8 *)imIn->image[yy];
  1144. for (xx = box[0] + x * xscale; xx < box[0] + box[2]; xx++) {
  1145. ss0 += line[xx * 4 + 0];
  1146. ss1 += line[xx * 4 + 1];
  1147. ss2 += line[xx * 4 + 2];
  1148. ss3 += line[xx * 4 + 3];
  1149. }
  1150. }
  1151. v = MAKE_UINT32(
  1152. (ss0 * multiplier) >> 24,
  1153. (ss1 * multiplier) >> 24,
  1154. (ss2 * multiplier) >> 24,
  1155. (ss3 * multiplier) >> 24);
  1156. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  1157. }
  1158. }
  1159. if (box[3] % yscale) {
  1160. int scale = xscale * (box[3] % yscale);
  1161. UINT32 multiplier = division_UINT32(scale, 8);
  1162. UINT32 amend = scale / 2;
  1163. y = box[3] / yscale;
  1164. for (x = 0; x < box[2] / xscale; x++) {
  1165. int xx_from = box[0] + x * xscale;
  1166. UINT32 v;
  1167. UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
  1168. for (yy = box[1] + y * yscale; yy < box[1] + box[3]; yy++) {
  1169. UINT8 *line = (UINT8 *)imIn->image[yy];
  1170. for (xx = xx_from; xx < xx_from + xscale; xx++) {
  1171. ss0 += line[xx * 4 + 0];
  1172. ss1 += line[xx * 4 + 1];
  1173. ss2 += line[xx * 4 + 2];
  1174. ss3 += line[xx * 4 + 3];
  1175. }
  1176. }
  1177. v = MAKE_UINT32(
  1178. (ss0 * multiplier) >> 24,
  1179. (ss1 * multiplier) >> 24,
  1180. (ss2 * multiplier) >> 24,
  1181. (ss3 * multiplier) >> 24);
  1182. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  1183. }
  1184. }
  1185. if (box[2] % xscale && box[3] % yscale) {
  1186. int scale = (box[2] % xscale) * (box[3] % yscale);
  1187. UINT32 multiplier = division_UINT32(scale, 8);
  1188. UINT32 amend = scale / 2;
  1189. UINT32 v;
  1190. UINT32 ss0 = amend, ss1 = amend, ss2 = amend, ss3 = amend;
  1191. x = box[2] / xscale;
  1192. y = box[3] / yscale;
  1193. for (yy = box[1] + y * yscale; yy < box[1] + box[3]; yy++) {
  1194. UINT8 *line = (UINT8 *)imIn->image[yy];
  1195. for (xx = box[0] + x * xscale; xx < box[0] + box[2]; xx++) {
  1196. ss0 += line[xx * 4 + 0];
  1197. ss1 += line[xx * 4 + 1];
  1198. ss2 += line[xx * 4 + 2];
  1199. ss3 += line[xx * 4 + 3];
  1200. }
  1201. }
  1202. v = MAKE_UINT32(
  1203. (ss0 * multiplier) >> 24,
  1204. (ss1 * multiplier) >> 24,
  1205. (ss2 * multiplier) >> 24,
  1206. (ss3 * multiplier) >> 24);
  1207. memcpy(imOut->image[y] + x * sizeof(v), &v, sizeof(v));
  1208. }
  1209. }
  1210. }
  1211. void
  1212. ImagingReduceNxN_32bpc(
  1213. Imaging imOut, Imaging imIn, int box[4], int xscale, int yscale) {
  1214. /* The most general implementation for any xscale and yscale
  1215. */
  1216. int x, y, xx, yy;
  1217. double multiplier = 1.0 / (yscale * xscale);
  1218. switch (imIn->type) {
  1219. case IMAGING_TYPE_INT32:
  1220. for (y = 0; y < box[3] / yscale; y++) {
  1221. int yy_from = box[1] + y * yscale;
  1222. for (x = 0; x < box[2] / xscale; x++) {
  1223. int xx_from = box[0] + x * xscale;
  1224. double ss = 0;
  1225. for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
  1226. INT32 *line0 = (INT32 *)imIn->image32[yy];
  1227. INT32 *line1 = (INT32 *)imIn->image32[yy + 1];
  1228. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  1229. ss += line0[xx + 0] + line0[xx + 1] + line1[xx + 0] +
  1230. line1[xx + 1];
  1231. }
  1232. if (xscale & 0x01) {
  1233. ss += line0[xx + 0] + line1[xx + 0];
  1234. }
  1235. }
  1236. if (yscale & 0x01) {
  1237. INT32 *line = (INT32 *)imIn->image32[yy];
  1238. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  1239. ss += line[xx + 0] + line[xx + 1];
  1240. }
  1241. if (xscale & 0x01) {
  1242. ss += line[xx + 0];
  1243. }
  1244. }
  1245. IMAGING_PIXEL_I(imOut, x, y) = ROUND_UP(ss * multiplier);
  1246. }
  1247. }
  1248. break;
  1249. case IMAGING_TYPE_FLOAT32:
  1250. for (y = 0; y < box[3] / yscale; y++) {
  1251. int yy_from = box[1] + y * yscale;
  1252. for (x = 0; x < box[2] / xscale; x++) {
  1253. int xx_from = box[0] + x * xscale;
  1254. double ss = 0;
  1255. for (yy = yy_from; yy < yy_from + yscale - 1; yy += 2) {
  1256. FLOAT32 *line0 = (FLOAT32 *)imIn->image32[yy];
  1257. FLOAT32 *line1 = (FLOAT32 *)imIn->image32[yy + 1];
  1258. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  1259. ss += line0[xx + 0] + line0[xx + 1] + line1[xx + 0] +
  1260. line1[xx + 1];
  1261. }
  1262. if (xscale & 0x01) {
  1263. ss += line0[xx + 0] + line1[xx + 0];
  1264. }
  1265. }
  1266. if (yscale & 0x01) {
  1267. FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
  1268. for (xx = xx_from; xx < xx_from + xscale - 1; xx += 2) {
  1269. ss += line[xx + 0] + line[xx + 1];
  1270. }
  1271. if (xscale & 0x01) {
  1272. ss += line[xx + 0];
  1273. }
  1274. }
  1275. IMAGING_PIXEL_F(imOut, x, y) = ss * multiplier;
  1276. }
  1277. }
  1278. break;
  1279. }
  1280. }
  1281. void
  1282. ImagingReduceCorners_32bpc(
  1283. Imaging imOut, Imaging imIn, int box[4], int xscale, int yscale) {
  1284. /* Fill the last row and the last column for any xscale and yscale.
  1285. */
  1286. int x, y, xx, yy;
  1287. switch (imIn->type) {
  1288. case IMAGING_TYPE_INT32:
  1289. if (box[2] % xscale) {
  1290. double multiplier = 1.0 / ((box[2] % xscale) * yscale);
  1291. for (y = 0; y < box[3] / yscale; y++) {
  1292. int yy_from = box[1] + y * yscale;
  1293. double ss = 0;
  1294. x = box[2] / xscale;
  1295. for (yy = yy_from; yy < yy_from + yscale; yy++) {
  1296. INT32 *line = (INT32 *)imIn->image32[yy];
  1297. for (xx = box[0] + x * xscale; xx < box[0] + box[2]; xx++) {
  1298. ss += line[xx + 0];
  1299. }
  1300. }
  1301. IMAGING_PIXEL_I(imOut, x, y) = ROUND_UP(ss * multiplier);
  1302. }
  1303. }
  1304. if (box[3] % yscale) {
  1305. double multiplier = 1.0 / (xscale * (box[3] % yscale));
  1306. y = box[3] / yscale;
  1307. for (x = 0; x < box[2] / xscale; x++) {
  1308. int xx_from = box[0] + x * xscale;
  1309. double ss = 0;
  1310. for (yy = box[1] + y * yscale; yy < box[1] + box[3]; yy++) {
  1311. INT32 *line = (INT32 *)imIn->image32[yy];
  1312. for (xx = xx_from; xx < xx_from + xscale; xx++) {
  1313. ss += line[xx + 0];
  1314. }
  1315. }
  1316. IMAGING_PIXEL_I(imOut, x, y) = ROUND_UP(ss * multiplier);
  1317. }
  1318. }
  1319. if (box[2] % xscale && box[3] % yscale) {
  1320. double multiplier = 1.0 / ((box[2] % xscale) * (box[3] % yscale));
  1321. double ss = 0;
  1322. x = box[2] / xscale;
  1323. y = box[3] / yscale;
  1324. for (yy = box[1] + y * yscale; yy < box[1] + box[3]; yy++) {
  1325. INT32 *line = (INT32 *)imIn->image32[yy];
  1326. for (xx = box[0] + x * xscale; xx < box[0] + box[2]; xx++) {
  1327. ss += line[xx + 0];
  1328. }
  1329. }
  1330. IMAGING_PIXEL_I(imOut, x, y) = ROUND_UP(ss * multiplier);
  1331. }
  1332. break;
  1333. case IMAGING_TYPE_FLOAT32:
  1334. if (box[2] % xscale) {
  1335. double multiplier = 1.0 / ((box[2] % xscale) * yscale);
  1336. for (y = 0; y < box[3] / yscale; y++) {
  1337. int yy_from = box[1] + y * yscale;
  1338. double ss = 0;
  1339. x = box[2] / xscale;
  1340. for (yy = yy_from; yy < yy_from + yscale; yy++) {
  1341. FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
  1342. for (xx = box[0] + x * xscale; xx < box[0] + box[2]; xx++) {
  1343. ss += line[xx + 0];
  1344. }
  1345. }
  1346. IMAGING_PIXEL_F(imOut, x, y) = ss * multiplier;
  1347. }
  1348. }
  1349. if (box[3] % yscale) {
  1350. double multiplier = 1.0 / (xscale * (box[3] % yscale));
  1351. y = box[3] / yscale;
  1352. for (x = 0; x < box[2] / xscale; x++) {
  1353. int xx_from = box[0] + x * xscale;
  1354. double ss = 0;
  1355. for (yy = box[1] + y * yscale; yy < box[1] + box[3]; yy++) {
  1356. FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
  1357. for (xx = xx_from; xx < xx_from + xscale; xx++) {
  1358. ss += line[xx + 0];
  1359. }
  1360. }
  1361. IMAGING_PIXEL_F(imOut, x, y) = ss * multiplier;
  1362. }
  1363. }
  1364. if (box[2] % xscale && box[3] % yscale) {
  1365. double multiplier = 1.0 / ((box[2] % xscale) * (box[3] % yscale));
  1366. double ss = 0;
  1367. x = box[2] / xscale;
  1368. y = box[3] / yscale;
  1369. for (yy = box[1] + y * yscale; yy < box[1] + box[3]; yy++) {
  1370. FLOAT32 *line = (FLOAT32 *)imIn->image32[yy];
  1371. for (xx = box[0] + x * xscale; xx < box[0] + box[2]; xx++) {
  1372. ss += line[xx + 0];
  1373. }
  1374. }
  1375. IMAGING_PIXEL_F(imOut, x, y) = ss * multiplier;
  1376. }
  1377. break;
  1378. }
  1379. }
  1380. Imaging
  1381. ImagingReduce(Imaging imIn, int xscale, int yscale, int box[4]) {
  1382. ImagingSectionCookie cookie;
  1383. Imaging imOut = NULL;
  1384. if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "1") == 0) {
  1385. return (Imaging)ImagingError_ModeError();
  1386. }
  1387. if (imIn->type == IMAGING_TYPE_SPECIAL) {
  1388. return (Imaging)ImagingError_ModeError();
  1389. }
  1390. imOut = ImagingNewDirty(
  1391. imIn->mode, (box[2] + xscale - 1) / xscale, (box[3] + yscale - 1) / yscale);
  1392. if (!imOut) {
  1393. return NULL;
  1394. }
  1395. ImagingSectionEnter(&cookie);
  1396. switch (imIn->type) {
  1397. case IMAGING_TYPE_UINT8:
  1398. if (xscale == 1) {
  1399. if (yscale == 2) {
  1400. ImagingReduce1x2(imOut, imIn, box);
  1401. } else if (yscale == 3) {
  1402. ImagingReduce1x3(imOut, imIn, box);
  1403. } else {
  1404. ImagingReduce1xN(imOut, imIn, box, yscale);
  1405. }
  1406. } else if (yscale == 1) {
  1407. if (xscale == 2) {
  1408. ImagingReduce2x1(imOut, imIn, box);
  1409. } else if (xscale == 3) {
  1410. ImagingReduce3x1(imOut, imIn, box);
  1411. } else {
  1412. ImagingReduceNx1(imOut, imIn, box, xscale);
  1413. }
  1414. } else if (xscale == yscale && xscale <= 5) {
  1415. if (xscale == 2) {
  1416. ImagingReduce2x2(imOut, imIn, box);
  1417. } else if (xscale == 3) {
  1418. ImagingReduce3x3(imOut, imIn, box);
  1419. } else if (xscale == 4) {
  1420. ImagingReduce4x4(imOut, imIn, box);
  1421. } else {
  1422. ImagingReduce5x5(imOut, imIn, box);
  1423. }
  1424. } else {
  1425. ImagingReduceNxN(imOut, imIn, box, xscale, yscale);
  1426. }
  1427. ImagingReduceCorners(imOut, imIn, box, xscale, yscale);
  1428. break;
  1429. case IMAGING_TYPE_INT32:
  1430. case IMAGING_TYPE_FLOAT32:
  1431. ImagingReduceNxN_32bpc(imOut, imIn, box, xscale, yscale);
  1432. ImagingReduceCorners_32bpc(imOut, imIn, box, xscale, yscale);
  1433. break;
  1434. }
  1435. ImagingSectionLeave(&cookie);
  1436. return imOut;
  1437. }