Resizer.cxx 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  1. /* Copyright (C) 2011-2013 Doubango Telecom <http://www.doubango.org>
  2. *
  3. * This file is part of Open Source Doubango Framework.
  4. *
  5. * DOUBANGO is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * DOUBANGO is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with DOUBANGO.
  17. */
  18. /*
  19. * Copyright (c) Microsoft Corporation. All rights reserved.
  20. */
  21. #if !defined(RESIZER_DO_NOT_INCLUDE_HEADER)
  22. #include "internals/Resizer.h"
  23. #endif /* DO_NOT_INCLUDE_HEADER */
  24. /* stretch proportions */
  25. #define STRETCH_1_1 1
  26. #define STRETCH_1_2 2
  27. #define STRETCH_1_4 3
  28. #define STRETCH_1_N 4
  29. #define STRETCH_N_1 5
  30. #define STRETCH_4_1 6
  31. #define STRETCH_2_1 7
  32. void __stdcall StretchDIB(
  33. LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of destination
  34. LPVOID lpvDst, // --> to destination bits
  35. int DstX, // Destination origin - x coordinate
  36. int DstY, // Destination origin - y coordinate
  37. int DstXE, // x extent of the BLT
  38. int DstYE, // y extent of the BLT
  39. LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of source
  40. LPVOID lpvSrc, // --> to source bits
  41. int SrcX, // Source origin - x coordinate
  42. int SrcY, // Source origin - y coordinate
  43. int SrcXE, // x extent of the BLT
  44. int SrcYE // y extent of the BLT
  45. );
  46. /*
  47. * an X_FUNC is a function that copies one scanline, stretching or shrinking it
  48. * to fit a destination scanline. Pick an X_FUNC depending on
  49. * bitdepth and stretch ratio (1:1, 1:2, 1:4, 1:N, N:1, 4:1, 2:1)
  50. *
  51. * the x_fract argument is the delta fraction: it is a representation
  52. * of the smaller extent (whichever that is) as a fraction of the larger,
  53. * and is used when stretching or shrinking to advance the pointer to the
  54. * smaller scanline every (fract) pixels of the larger.
  55. * Thus if we are expanding 1:8, x_fract will be 1/8, we will advance the
  56. * source pointer once every 8 pixels, and thus copy each source pixel to
  57. * 8 dest pixels. Note that if shrinking 8:1, x_fract will still be 1/8
  58. * and we will use it to control advancement of the dest pointer.
  59. * the fraction is multiplied by 65536.
  60. */
  61. typedef void (*X_FUNC) (LPBYTE lpSrc,
  62. LPBYTE lpDst,
  63. int SrcXE,
  64. int DstXE,
  65. int x_fract);
  66. void X_Stretch_1_1_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  67. void X_Stretch_1_2_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  68. void X_Stretch_1_4_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  69. void X_Stretch_1_N_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  70. void X_Stretch_N_1_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  71. void X_Stretch_1_1_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  72. void X_Stretch_1_2_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  73. void X_Stretch_1_N_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  74. void X_Stretch_N_1_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  75. void X_Stretch_1_1_24Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  76. void X_Stretch_1_N_24Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  77. void X_Stretch_N_1_24Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  78. void X_Stretch_1_1_32Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  79. void X_Stretch_1_N_32Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  80. void X_Stretch_N_1_32Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE, int DstXE, int x_fract);
  81. /*
  82. * Y_Stretch_* functions copy DstYE scanlines (using
  83. * an X_FUNC to copy each scanline) omitting or duplicating scanlines to
  84. * fit the destination extent. Pick a Y_ depending on the ratio
  85. * (1:N, N:1...)
  86. */
  87. void Y_Stretch_1_N(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  88. int DstYE, int SrcWidth, int DstWidth, int x_fract,
  89. X_FUNC x_func, int nBits);
  90. void Y_Stretch_N_1(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  91. int DstYE, int SrcWidth, int DstWidth, int x_fract,
  92. X_FUNC x_func);
  93. /*
  94. * special case y-stretch functions for 1:2 in both dimensions for 8 and 16 bits
  95. * takes no X_FUNC arg. Will do entire stretch.
  96. */
  97. void Stretch_1_2_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  98. int DstYE, int SrcWidth, int DstWidth, int x_fract);
  99. void Stretch_1_2_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  100. int DstYE, int SrcWidth, int DstWidth, int x_fract);
  101. /* straight copy of one scanline of count bytes */
  102. void X_CopyScanline(LPBYTE lpSrc, LPBYTE lpDst, int count);
  103. //
  104. // Resize function
  105. //
  106. void ResizeRGB( BITMAPINFOHEADER *pbiIn, //Src's BitMapInFoHeader
  107. const unsigned char * dibBits, //Src bits
  108. BITMAPINFOHEADER *pbiOut,
  109. unsigned char *pFrame, //Dst bits
  110. int iNewWidth, //new W in pixel
  111. int iNewHeight) //new H in pixel
  112. {
  113. StretchDIB( pbiOut, // --> BITMAPINFO of destination
  114. pFrame, // --> to destination bits
  115. 0, // Destination origin - x coordinate
  116. 0, // Destination origin - y coordinate
  117. iNewWidth, // x extent of the BLT
  118. iNewHeight, // y extent of the BLT
  119. pbiIn, // --> BITMAPINFO of destination
  120. (void*) dibBits, // --> to source bits
  121. 0, // Source origin - x coordinate
  122. 0, // Source origin - y coordinate
  123. pbiIn->biWidth, // x extent of the BLT
  124. pbiIn->biHeight // y extent of the BLT
  125. );
  126. return;
  127. }
  128. /* -------------------------------------------------------------------- */
  129. /*
  130. * StretchFactor
  131. *
  132. * calculate the stretch factor (proportion of source extent to destination
  133. * extent: 1:1, 1:2, 1:4, 1:N, N:1, 4:1,or 2:1) and also the
  134. * delta fraction (see above comment on X_FUNC). This is the ratio of
  135. * the smaller extent to the larger extent, represented as a fraction
  136. * multiplied by 65536.
  137. *
  138. * returns: the stretch factor (stores the delta fraction in *pfract)
  139. */
  140. int
  141. StretchFactor(int SrcE, int DstE, int *pfract)
  142. {
  143. if (SrcE == DstE) {
  144. if (pfract != NULL) {
  145. pfract = 0;
  146. }
  147. return(STRETCH_1_1);
  148. }
  149. if (SrcE > DstE) {
  150. if (pfract != NULL) {
  151. *pfract = ( (DstE << 16) / SrcE) & 0xffff;
  152. }
  153. if (SrcE == (DstE * 2)) {
  154. return(STRETCH_2_1);
  155. }
  156. else if (SrcE == (DstE * 4)) {
  157. return(STRETCH_4_1);
  158. }
  159. else {
  160. return(STRETCH_N_1);
  161. }
  162. }
  163. else {
  164. /* calculate delta fraction based on smallest / largest */
  165. if (pfract != NULL) {
  166. *pfract = ( (SrcE << 16) / DstE) & 0xffff;
  167. }
  168. if (DstE == (SrcE * 2)) {
  169. return(STRETCH_1_2);
  170. }
  171. else if (DstE == (SrcE * 4)) {
  172. return(STRETCH_1_4);
  173. }
  174. else {
  175. return(STRETCH_1_N);
  176. }
  177. }
  178. }
  179. /* -------------------------------------------------------------------- */
  180. /*
  181. * StretchDIB
  182. *
  183. */
  184. void FAR PASCAL
  185. StretchDIB(
  186. LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of destination
  187. LPVOID lpvDst, // --> to destination bits
  188. int DstX, // Destination origin - x coordinate
  189. int DstY, // Destination origin - y coordinate
  190. int DstXE, // x extent of the BLT
  191. int DstYE, // y extent of the BLT
  192. LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of source
  193. LPVOID lpvSrc, // --> to source bits
  194. int SrcX, // Source origin - x coordinate
  195. int SrcY, // Source origin - y coordinate
  196. int SrcXE, // x extent of the BLT
  197. int SrcYE // y extent of the BLT
  198. )
  199. {
  200. int nBits;
  201. int SrcWidth, DstWidth;
  202. LPBYTE lpDst = (LPBYTE)lpvDst, lpSrc = (LPBYTE)lpvSrc;
  203. int x_fract;
  204. int x_factor;
  205. int y_factor;
  206. X_FUNC xfunc;
  207. /*
  208. * chek that sizes are not same
  209. */
  210. /*if(DstXE == SrcXE && DstYE == SrcYE)
  211. {
  212. return;
  213. }*/
  214. /*
  215. * check that bit depths are same and 8, 16 or 24
  216. */
  217. if ((nBits = biDst->biBitCount) != biSrc->biBitCount) {
  218. return;
  219. }
  220. if ( (nBits != 8 ) && (nBits != 16) && (nBits != 24) &&
  221. (nBits != 32)) {
  222. return;
  223. }
  224. /*
  225. * check that extents are not bad
  226. */
  227. if ( (SrcXE <= 0) || (SrcYE <= 0) || (DstXE <= 0) || (DstYE <= 0)) {
  228. return;
  229. }
  230. /*
  231. * calculate width of one scan line in bytes, rounded up to
  232. * DWORD boundary.
  233. */
  234. SrcWidth = (((biSrc->biWidth * nBits) + 31) & ~31) / 8;
  235. DstWidth = (((biDst->biWidth * nBits) + 31) & ~31) / 8;
  236. /*
  237. * set initial source and dest pointers
  238. */
  239. lpSrc += (SrcY * SrcWidth) + ((SrcX * nBits) / 8);
  240. lpDst += (DstY * DstWidth) + ((DstX * nBits) / 8);
  241. /*
  242. * calculate stretch proportions (1:1, 1:2, 1:N, N:1 etc) and
  243. * also the fractional stretch factor. (we are not interested in
  244. * the y stretch fraction - this is only used in x stretching.
  245. */
  246. y_factor = StretchFactor(SrcYE, DstYE, NULL);
  247. x_factor = StretchFactor(SrcXE, DstXE, &x_fract);
  248. /*
  249. * we have special case routines for 1:2 in both dimensions
  250. * for 8 and 16 bits
  251. */
  252. if ((y_factor == x_factor) && (y_factor == STRETCH_1_2)) {
  253. if (nBits == 8) {
  254. //StartCounting();
  255. Stretch_1_2_8Bits(lpSrc, lpDst, SrcXE, SrcYE,
  256. DstXE, DstYE, SrcWidth, DstWidth,
  257. x_fract);
  258. //EndCounting("8 bit");
  259. return;
  260. }
  261. else if (nBits == 16) {
  262. //StartCounting();
  263. Stretch_1_2_16Bits(lpSrc, lpDst, SrcXE, SrcYE,
  264. DstXE, DstYE, SrcWidth, DstWidth,
  265. x_fract);
  266. //EndCounting("16 bit");
  267. return;
  268. }
  269. }
  270. /* pick an X stretch function */
  271. switch(nBits) {
  272. case 8:
  273. switch(x_factor) {
  274. case STRETCH_1_1:
  275. xfunc = X_Stretch_1_1_8Bits;
  276. break;
  277. case STRETCH_1_2:
  278. xfunc = X_Stretch_1_2_8Bits;
  279. break;
  280. case STRETCH_1_4:
  281. xfunc = X_Stretch_1_4_8Bits;
  282. break;
  283. case STRETCH_1_N:
  284. xfunc = X_Stretch_1_N_8Bits;
  285. break;
  286. case STRETCH_N_1:
  287. case STRETCH_4_1:
  288. case STRETCH_2_1:
  289. xfunc = X_Stretch_N_1_8Bits;
  290. break;
  291. }
  292. break;
  293. case 16:
  294. switch(x_factor) {
  295. case STRETCH_1_1:
  296. xfunc = X_Stretch_1_1_16Bits;
  297. break;
  298. case STRETCH_1_2:
  299. xfunc = X_Stretch_1_2_16Bits;
  300. break;
  301. case STRETCH_1_4:
  302. case STRETCH_1_N:
  303. xfunc = X_Stretch_1_N_16Bits;
  304. break;
  305. case STRETCH_N_1:
  306. case STRETCH_4_1:
  307. case STRETCH_2_1:
  308. xfunc = X_Stretch_N_1_16Bits;
  309. break;
  310. }
  311. break;
  312. case 24:
  313. switch(x_factor) {
  314. case STRETCH_1_1:
  315. xfunc = X_Stretch_1_1_24Bits;
  316. break;
  317. case STRETCH_1_2:
  318. case STRETCH_1_4:
  319. case STRETCH_1_N:
  320. xfunc = X_Stretch_1_N_24Bits;
  321. break;
  322. case STRETCH_N_1:
  323. case STRETCH_4_1:
  324. case STRETCH_2_1:
  325. xfunc = X_Stretch_N_1_24Bits;
  326. break;
  327. }
  328. break;
  329. case 32:
  330. switch(x_factor) {
  331. case STRETCH_1_1:
  332. xfunc = X_Stretch_1_1_32Bits;
  333. break;
  334. case STRETCH_1_2:
  335. case STRETCH_1_4:
  336. case STRETCH_1_N:
  337. xfunc = X_Stretch_1_N_32Bits;
  338. break;
  339. case STRETCH_N_1:
  340. case STRETCH_4_1:
  341. case STRETCH_2_1:
  342. xfunc = X_Stretch_N_1_32Bits;
  343. break;
  344. }
  345. break;
  346. }
  347. /*
  348. * now call appropriate stretching function depending
  349. * on the y stretch factor
  350. */
  351. switch (y_factor) {
  352. case STRETCH_1_1:
  353. case STRETCH_1_2:
  354. case STRETCH_1_4:
  355. case STRETCH_1_N:
  356. Y_Stretch_1_N(lpSrc, lpDst, SrcXE, SrcYE,
  357. DstXE, DstYE, SrcWidth, DstWidth, x_fract, xfunc, nBits);
  358. break;
  359. case STRETCH_N_1:
  360. case STRETCH_4_1:
  361. case STRETCH_2_1:
  362. Y_Stretch_N_1(lpSrc, lpDst, SrcXE, SrcYE,
  363. DstXE, DstYE, SrcWidth, DstWidth, x_fract, xfunc);
  364. break;
  365. }
  366. return;
  367. }
  368. /* ---- y stretching -------------------------------------------- */
  369. /*
  370. * call an X_FUNC to copy scanlines from lpSrc to lpDst. Duplicate or
  371. * omit scanlines to stretch SrcYE to DstYE.
  372. */
  373. /*
  374. * Y_Stretch_1_N
  375. *
  376. * write DstYE scanlines based on SrcYE scanlines, DstYE > SrcYE
  377. *
  378. */
  379. void
  380. Y_Stretch_1_N(LPBYTE lpSrc,
  381. LPBYTE lpDst,
  382. int SrcXE,
  383. int SrcYE,
  384. int DstXE,
  385. int DstYE,
  386. int SrcWidth,
  387. int DstWidth,
  388. int x_fract,
  389. X_FUNC x_func,
  390. int nBits)
  391. {
  392. int ydelta;
  393. register int i;
  394. LPBYTE lpPrev = NULL;
  395. ydelta = DstYE -1;
  396. for (i = 0; i < DstYE; i++) {
  397. /* have we already stretched this scanline ? */
  398. if (lpPrev == NULL) {
  399. /* no - copy one scanline */
  400. (*x_func)(lpSrc, lpDst, SrcXE, DstXE, x_fract);
  401. lpPrev = lpDst;
  402. }
  403. else {
  404. /* yes - this is a duplicate scanline. do
  405. * a straight copy of one that has already
  406. * been stretched/shrunk
  407. */
  408. X_CopyScanline(lpPrev, lpDst, DstXE * nBits / 8);
  409. }
  410. /* advance dest pointer */
  411. lpDst += DstWidth;
  412. /* should we advance source pointer this time ? */
  413. if ( (ydelta -= SrcYE) < 0) {
  414. ydelta += DstYE;
  415. lpSrc += SrcWidth;
  416. lpPrev = NULL;
  417. }
  418. }
  419. }
  420. /*
  421. * Y_Stretch_N_1
  422. *
  423. * write DstYE scanlines based on SrcYE scanlines, DstYE < SrcYE
  424. *
  425. */
  426. void
  427. Y_Stretch_N_1(LPBYTE lpSrc,
  428. LPBYTE lpDst,
  429. int SrcXE,
  430. int SrcYE,
  431. int DstXE,
  432. int DstYE,
  433. int SrcWidth,
  434. int DstWidth,
  435. int x_fract,
  436. X_FUNC x_func)
  437. {
  438. int ydelta;
  439. register int i;
  440. ydelta = SrcYE -1;
  441. for (i = 0; i < DstYE; i++) {
  442. /* copy one scanline */
  443. (*x_func)(lpSrc, lpDst, SrcXE, DstXE, x_fract);
  444. /* advance dest pointer */
  445. lpDst += DstWidth;
  446. /* how many times do we advance source pointer this time ? */
  447. do {
  448. lpSrc += SrcWidth;
  449. ydelta -= DstYE;
  450. }
  451. while (ydelta >= 0);
  452. ydelta += SrcYE;
  453. }
  454. }
  455. /* ---8-bit X stretching -------------------------------------------------- */
  456. /*
  457. * X_Stretch_1_N_8Bits
  458. *
  459. * copy one scan line, stretching 1:N (DstXE > SrcXE). For 8-bit depth.
  460. */
  461. void
  462. X_Stretch_1_N_8Bits(LPBYTE lpSrc,
  463. LPBYTE lpDst,
  464. int SrcXE,
  465. int DstXE,
  466. int x_fract)
  467. {
  468. int xdelta;
  469. register int i;
  470. xdelta = DstXE -1;
  471. for (i = 0; i < DstXE; i++) {
  472. /* copy one byte and advance dest */
  473. *lpDst++ = *lpSrc;
  474. /* should we advance source pointer this time ? */
  475. if ( (xdelta -= SrcXE) < 0) {
  476. xdelta += DstXE;
  477. lpSrc++;
  478. }
  479. }
  480. }
  481. /*
  482. * X_Stretch_N_1_8Bits
  483. *
  484. * copy one scan line, shrinking N:1 (DstXE < SrcXE). For 8-bit depth.
  485. */
  486. void
  487. X_Stretch_N_1_8Bits(LPBYTE lpSrc,
  488. LPBYTE lpDst,
  489. int SrcXE,
  490. int DstXE,
  491. int x_fract)
  492. {
  493. int xdelta;
  494. register int i;
  495. xdelta = SrcXE -1;
  496. for (i = 0; i < DstXE; i++) {
  497. /* copy one byte and advance dest */
  498. *lpDst++ = *lpSrc;
  499. /* how many times do we advance source pointer this time ? */
  500. do {
  501. lpSrc++;
  502. xdelta -= DstXE;
  503. }
  504. while (xdelta >= 0);
  505. xdelta += SrcXE;
  506. }
  507. }
  508. /*
  509. * copy one scanline of count bytes from lpSrc to lpDst. used by 1:1
  510. * scanline functions for all bit depths
  511. */
  512. void
  513. X_CopyScanline(LPBYTE lpSrc, LPBYTE lpDst, int count)
  514. {
  515. register int i;
  516. /*
  517. * if the alignment of lpSrc and lpDst is the same, then
  518. * we can get them aligned and do a faster copy
  519. */
  520. if (((DWORD_PTR) lpSrc & 0x3) == ( (DWORD_PTR) lpDst & 0x3)) {
  521. /* align on WORD boundary */
  522. if ( (DWORD_PTR) lpSrc & 0x1) {
  523. *lpDst++ = *lpSrc++;
  524. count--;
  525. }
  526. /* align on DWORD boundary */
  527. if ((DWORD_PTR) lpSrc & 0x2) {
  528. * ((LPWORD) lpDst) = *((LPWORD) lpSrc);
  529. lpDst += sizeof(WORD);
  530. lpSrc += sizeof(WORD);
  531. count -= sizeof(WORD);
  532. }
  533. /* copy whole DWORDS */
  534. for ( i = (count / 4); i > 0; i--) {
  535. *((LPDWORD) lpDst) = *((LPDWORD) lpSrc);
  536. lpSrc += sizeof(DWORD);
  537. lpDst += sizeof(DWORD);
  538. }
  539. }
  540. else {
  541. /* the lpSrc and lpDst pointers are different
  542. * alignment, so leave them unaligned and
  543. * copy all the whole DWORDs
  544. */
  545. for (i = (count / 4); i> 0; i--) {
  546. *( (DWORD UNALIGNED FAR *) lpDst) =
  547. *((DWORD UNALIGNED FAR *) lpSrc);
  548. lpSrc += sizeof(DWORD);
  549. lpDst += sizeof(DWORD);
  550. }
  551. }
  552. /* in either case, copy last (up to 3) bytes. */
  553. for ( i = count % 4; i > 0; i--) {
  554. *lpDst++ = *lpSrc++;
  555. }
  556. }
  557. /*
  558. * X_Stretch_1_1_8Bits
  559. *
  560. * copy a scanline with no change (1:1)
  561. */
  562. void
  563. X_Stretch_1_1_8Bits(LPBYTE lpSrc,
  564. LPBYTE lpDst,
  565. int SrcXE,
  566. int DstXE,
  567. int x_fract)
  568. {
  569. X_CopyScanline(lpSrc, lpDst, DstXE);
  570. }
  571. /*
  572. * X_Stretch_1_2_8Bits
  573. *
  574. * copy a scanline, doubling all the pixels (1:2)
  575. */
  576. void
  577. X_Stretch_1_2_8Bits(LPBYTE lpSrc,
  578. LPBYTE lpDst,
  579. int SrcXE,
  580. int DstXE,
  581. int x_fract)
  582. {
  583. WORD wPix;
  584. register int i;
  585. for (i = 0; i < SrcXE; i++) {
  586. /* get a pixel and double it */
  587. wPix = *lpSrc++;
  588. wPix |= (wPix << 8);
  589. * ((WORD UNALIGNED *) lpDst) = wPix;
  590. lpDst += sizeof(WORD);
  591. }
  592. }
  593. /*
  594. * X_Stretch_1_4_8Bits
  595. *
  596. * copy a scanline, quadrupling all the pixels (1:4)
  597. */
  598. void
  599. X_Stretch_1_4_8Bits(LPBYTE lpSrc,
  600. LPBYTE lpDst,
  601. int SrcXE,
  602. int DstXE,
  603. int x_fract)
  604. {
  605. DWORD dwPix;
  606. register int i;
  607. for (i = 0; i < SrcXE; i++) {
  608. /* get a pixel and make four copies of it */
  609. dwPix = *lpSrc++;
  610. dwPix |= (dwPix <<8);
  611. dwPix |= (dwPix << 16);
  612. * ((DWORD UNALIGNED *) lpDst) = dwPix;
  613. lpDst += sizeof(DWORD);
  614. }
  615. }
  616. /* -- 16-bit X functions -----------------------------------------------*/
  617. /*
  618. * copy one scan-line of 16 bits with no change (1:1)
  619. */
  620. void
  621. X_Stretch_1_1_16Bits(LPBYTE lpSrc,
  622. LPBYTE lpDst,
  623. int SrcXE,
  624. int DstXE,
  625. int x_fract)
  626. {
  627. X_CopyScanline(lpSrc, lpDst, DstXE * sizeof(WORD));
  628. }
  629. /*
  630. * copy one scanline of 16 bpp duplicating each pixel
  631. */
  632. void
  633. X_Stretch_1_2_16Bits(LPBYTE lpSrc,
  634. LPBYTE lpDst,
  635. int SrcXE,
  636. int DstXE,
  637. int x_fract)
  638. {
  639. DWORD dwPix;
  640. register int i;
  641. for (i = 0; i < SrcXE; i++) {
  642. /* get a pixel and double it */
  643. dwPix = * ((WORD *)lpSrc);
  644. dwPix |= (dwPix << 16);
  645. * ((DWORD UNALIGNED *) lpDst) = dwPix;
  646. lpDst += sizeof(DWORD);
  647. lpSrc += sizeof(WORD);
  648. }
  649. }
  650. /*
  651. * copy one scanline of 16 bits, stretching 1:n (dest > source)
  652. */
  653. void
  654. X_Stretch_1_N_16Bits(LPBYTE lpSrc,
  655. LPBYTE lpDst,
  656. int SrcXE,
  657. int DstXE,
  658. int x_fract)
  659. {
  660. int xdelta;
  661. register int i;
  662. xdelta = DstXE -1;
  663. for (i = 0; i < DstXE; i++) {
  664. /* copy one pixel and advance dest */
  665. *((WORD *) lpDst) = *((WORD *) lpSrc);
  666. lpDst += sizeof(WORD);
  667. /* should we advance source pointer this time ? */
  668. if ( (xdelta -= SrcXE) < 0) {
  669. xdelta += DstXE;
  670. lpSrc += sizeof(WORD);
  671. }
  672. }
  673. }
  674. /*
  675. * copy one scanline of 16bits, shrinking n:1 (dest < source)
  676. */
  677. void
  678. X_Stretch_N_1_16Bits(LPBYTE lpSrc,
  679. LPBYTE lpDst,
  680. int SrcXE,
  681. int DstXE,
  682. int x_fract)
  683. {
  684. int xdelta;
  685. register int i;
  686. xdelta = SrcXE -1;
  687. for (i = 0; i < DstXE; i++) {
  688. /* copy one pixel and advance dest */
  689. *((WORD *) lpDst) = *((WORD *)lpSrc);
  690. lpDst += sizeof(WORD);
  691. /* how many times do we advance source pointer this time ? */
  692. do {
  693. lpSrc += sizeof(WORD);
  694. xdelta -= DstXE;
  695. }
  696. while (xdelta >= 0);
  697. xdelta += SrcXE;
  698. }
  699. }
  700. /* 24-bits ---------------------------------------------------------*/
  701. /*
  702. * copy one 24-bpp scanline as is (1:1)
  703. */
  704. void
  705. X_Stretch_1_1_24Bits(LPBYTE lpSrc,
  706. LPBYTE lpDst,
  707. int SrcXE,
  708. int DstXE,
  709. int x_fract)
  710. {
  711. X_CopyScanline(lpSrc, lpDst, DstXE * 3);
  712. }
  713. /*
  714. * copy one 24-bpp scanline stretching 1:n (dest > source)
  715. */
  716. void
  717. X_Stretch_1_N_24Bits(LPBYTE lpSrc,
  718. LPBYTE lpDst,
  719. int SrcXE,
  720. int DstXE,
  721. int x_fract)
  722. {
  723. int xdelta;
  724. register int i;
  725. xdelta = DstXE -1;
  726. for (i = 0; i < DstXE; i++) {
  727. /* copy first word of pixel and advance dest */
  728. *((WORD UNALIGNED *) lpDst) = *((WORD UNALIGNED *) lpSrc);
  729. lpDst += sizeof(WORD);
  730. /* copy third byte and advance dest */
  731. *lpDst++ = lpSrc[sizeof(WORD)];
  732. /* should we advance source pointer this time ? */
  733. if ( (xdelta -= SrcXE) < 0) {
  734. xdelta += DstXE;
  735. lpSrc += 3;
  736. }
  737. }
  738. }
  739. /*
  740. * copy one scanline of 24 bits, shrinking n:1 (dest < source)
  741. */
  742. void
  743. X_Stretch_N_1_24Bits(LPBYTE lpSrc,
  744. LPBYTE lpDst,
  745. int SrcXE,
  746. int DstXE,
  747. int x_fract)
  748. {
  749. int xdelta;
  750. register int i;
  751. xdelta = SrcXE -1;
  752. for (i = 0; i < DstXE; i++) {
  753. /* copy first word of pixel and advance dest */
  754. *((WORD UNALIGNED *) lpDst) = *((WORD UNALIGNED *) lpSrc);
  755. lpDst += sizeof(WORD);
  756. /* copy third byte and advance dest */
  757. *lpDst++ = lpSrc[sizeof(WORD)];
  758. /* how many times do we advance source pointer this time ? */
  759. do {
  760. lpSrc += 3;
  761. xdelta -= DstXE;
  762. }
  763. while (xdelta >= 0);
  764. xdelta += SrcXE;
  765. }
  766. }
  767. /* 32-bits ---------------------------------------------------------*/
  768. /*
  769. * copy one 32-bpp scanline as is (1:1)
  770. */
  771. void
  772. X_Stretch_1_1_32Bits(LPBYTE lpSrc,
  773. LPBYTE lpDst,
  774. int SrcXE,
  775. int DstXE,
  776. int x_fract)
  777. {
  778. X_CopyScanline((BYTE*) lpSrc, (BYTE*) lpDst, DstXE * sizeof( RGBQUAD ) );
  779. }
  780. /*
  781. * copy one 32-bpp scanline stretching 1:n (dest > source)
  782. */
  783. void
  784. X_Stretch_1_N_32Bits(LPBYTE lpSrc0,
  785. LPBYTE lpDst0,
  786. int SrcXE,
  787. int DstXE,
  788. int x_fract)
  789. {
  790. int xdelta;
  791. register int i;
  792. RGBQUAD *lpSrc=(RGBQUAD *)lpSrc0;
  793. RGBQUAD *lpDst=(RGBQUAD *)lpDst0;
  794. xdelta = DstXE -1;
  795. for (i = 0; i < DstXE; i++) {
  796. /* copy first word of pixel and advance dest */
  797. *lpDst = *lpSrc;
  798. lpDst++;
  799. /* should we advance source pointer this time ? */
  800. if ( (xdelta -= SrcXE) < 0) {
  801. xdelta += DstXE;
  802. lpSrc++;
  803. }
  804. }
  805. }
  806. /*
  807. * copy one scanline of 32 bits, shrinking n:1 (dest < source)
  808. */
  809. void
  810. X_Stretch_N_1_32Bits(LPBYTE lpSrc0,
  811. LPBYTE lpDst0,
  812. int SrcXE,
  813. int DstXE,
  814. int x_fract)
  815. {
  816. int xdelta;
  817. register int i;
  818. RGBQUAD *lpSrc=(RGBQUAD *)lpSrc0;
  819. RGBQUAD *lpDst=(RGBQUAD *)lpDst0;
  820. xdelta = SrcXE -1;
  821. for (i = 0; i < DstXE; i++) {
  822. *lpDst = *lpSrc;
  823. lpDst++;
  824. /* how many times do we advance source pointer this time ? */
  825. do {
  826. lpSrc++;
  827. xdelta -= DstXE;
  828. }
  829. while (xdelta >= 0);
  830. xdelta += SrcXE;
  831. }
  832. }
  833. /* -- special-case 1:2 -------------------------------------------*/
  834. /*
  835. * stretch 1:2 in both directions, for 8 bits.
  836. *
  837. * An experiment was done on x86 to only write every other line during
  838. * the stretch and when the whole frame was done to use memcpy to fill
  839. * in the gaps. This is slower than doing the stretch in a single pass.
  840. */
  841. void
  842. Stretch_1_2_8Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  843. int DstYE, int SrcWidth, int DstWidth, int x_fract)
  844. {
  845. int SrcInc, DstInc;
  846. register int i, j;
  847. WORD wPix;
  848. DWORD dwPix4;
  849. /* amount to advance source by at the end of each scan */
  850. SrcInc = SrcWidth - SrcXE;
  851. /* amount to advance dest by at the end of each scan - note
  852. * that we write two scans at once, so advance past the next
  853. * scan line
  854. */
  855. DstInc = (DstWidth * 2) - DstXE;
  856. /*
  857. * we would like to copy the pixels DWORD at a time. this means
  858. * being aligned. if we are currently aligned on a WORD boundary,
  859. * then copy one pixel to get aligned. If we are on a byte
  860. * boundary, we can never get aligned, so use the slower loop.
  861. */
  862. if ( ((DWORD_PTR)lpDst) & 1) {
  863. /*
  864. * dest is byte aligned - so we can never align it
  865. * by writing WORDs - use slow loop.
  866. */
  867. for (i = 0; i < SrcYE; i++) {
  868. for (j = 0; j < SrcXE; j++) {
  869. /* get a pixel and double it */
  870. wPix = *lpSrc++;
  871. wPix |= (wPix<<8);
  872. /* write doubled pixel to this scanline */
  873. *( (WORD UNALIGNED *) lpDst) = wPix;
  874. /* write double pixel to next scanline */
  875. *( (WORD UNALIGNED *) (lpDst + DstWidth)) = wPix;
  876. lpDst += sizeof(WORD);
  877. }
  878. lpSrc += SrcInc;
  879. lpDst += DstInc;
  880. }
  881. return;
  882. }
  883. /*
  884. * this will be the aligned version. align each scan line
  885. */
  886. for ( i = 0; i < SrcYE; i++) {
  887. /* count of pixels remaining */
  888. j = SrcXE;
  889. /* align this scan line */
  890. if (((DWORD_PTR)lpDst) & 2) {
  891. /* word aligned - copy one doubled pixel and we are ok */
  892. wPix = *lpSrc++;
  893. wPix |= (wPix << 8);
  894. *( (WORD *) lpDst) = wPix;
  895. *( (WORD *) (lpDst + DstWidth)) = wPix;
  896. lpDst += sizeof(WORD);
  897. j -= 1;
  898. }
  899. /* now dest is aligned - so loop eating two pixels at a time
  900. * until there is at most one left
  901. */
  902. for ( ; j > 1; j -= 2) {
  903. /* read two pixels and double them */
  904. wPix = * ((WORD UNALIGNED *) lpSrc);
  905. lpSrc += sizeof(WORD);
  906. dwPix4 = (wPix & 0xff) | ((wPix & 0xff) << 8);
  907. dwPix4 |= ((wPix & 0xff00) << 8) | ((wPix & 0xff00) << 16);
  908. *((DWORD *) lpDst) = dwPix4;
  909. *((DWORD *) (lpDst + DstWidth)) = dwPix4;
  910. lpDst += sizeof(DWORD);
  911. }
  912. /* odd byte remaining ? */
  913. if (j > 0) {
  914. /* word aligned - copy one doubled pixel and we are ok */
  915. wPix = *lpSrc++;
  916. wPix |= (wPix << 8);
  917. *( (WORD *) lpDst) = wPix;
  918. *( (WORD *) (lpDst + DstWidth)) = wPix;
  919. lpDst += sizeof(WORD);
  920. j -= 1;
  921. }
  922. lpSrc += SrcInc;
  923. lpDst += DstInc;
  924. }
  925. }
  926. /* ----------------------------------------------------------------*/
  927. /*
  928. * stretch 1:2 in both directions, for 16-bits
  929. */
  930. void
  931. Stretch_1_2_16Bits(LPBYTE lpSrc, LPBYTE lpDst, int SrcXE,int SrcYE, int DstXE,
  932. int DstYE, int SrcWidth, int DstWidth, int x_fract)
  933. {
  934. int SrcInc, DstInc;
  935. register int i, j;
  936. DWORD dwPix;
  937. /* amount to advance source by at the end of each scan */
  938. SrcInc = SrcWidth - (SrcXE * sizeof(WORD));
  939. /* amount to advance dest by at the end of each scan - note
  940. * that we write two scans at once, so advance past the next
  941. * scan line
  942. */
  943. DstInc = (DstWidth * 2) - (DstXE * sizeof(WORD));
  944. for (i = 0; i < SrcYE; i++) {
  945. for (j = 0; j < SrcXE; j++) {
  946. /* get a pixel and double it */
  947. dwPix = *((WORD *)lpSrc);
  948. dwPix |= (dwPix<<16);
  949. lpSrc += sizeof(WORD);
  950. /* write doubled pixel to this scanline */
  951. *( (DWORD UNALIGNED *) lpDst) = dwPix;
  952. /* write double pixel to next scanline */
  953. *( (DWORD UNALIGNED *) (lpDst + DstWidth)) = dwPix;
  954. lpDst += sizeof(DWORD);
  955. }
  956. lpSrc += SrcInc;
  957. lpDst += DstInc;
  958. }
  959. }